mirror of
https://github.com/aziascreations/PB-MessagePack.git
synced 2026-11-03 17:01:24 +01:00
Improved buffer growth mechanism, Added tests for it some still missing
This commit is contained in:
@@ -41,7 +41,7 @@ Procedure.i MsgPackCreate(InitialSize.i)
|
||||
If *ReturnedValue <> #Null
|
||||
*ReturnedValue\BufferOffset = 0
|
||||
*ReturnedValue\BufferSize = InitialSize
|
||||
*ReturnedValue\BufferGrowthIncrements = InitialSize
|
||||
*ReturnedValue\BufferGrowthIncrement = InitialSize
|
||||
*ReturnedValue\DataFlags = 0
|
||||
|
||||
*ReturnedValue\Buffer = AllocateMemory(InitialSize)
|
||||
@@ -72,7 +72,7 @@ Procedure.i MsgPackWrapMsgBuffer(*Buffer, BufferSize.i)
|
||||
|
||||
*ReturnedValue\BufferOffset = 0
|
||||
*ReturnedValue\BufferSize = BufferSize
|
||||
*ReturnedValue\BufferGrowthIncrements = 0
|
||||
*ReturnedValue\BufferGrowthIncrement = 0
|
||||
*ReturnedValue\DataFlags = 0
|
||||
*ReturnedValue\Buffer = *Buffer
|
||||
|
||||
@@ -93,3 +93,60 @@ Procedure.b MsgPackFree(*MsgPackData.MsgPackData, FreeDataBuffer.b = #False)
|
||||
|
||||
ProcedureReturn #True
|
||||
EndProcedure
|
||||
|
||||
|
||||
; TODO: Add callback in the structure, maybe ?
|
||||
; FIXME: Use a .q for the size !!!!
|
||||
Procedure.MsgPack_ErrorCode MsgPackGrow(*MsgPackData.MsgPackData, DesiredSizeIncrease.i)
|
||||
Protected GrowthSize.q
|
||||
Protected NewSize.q
|
||||
Protected *NewBuffer
|
||||
|
||||
CompilerIf Not #MsgPack_DisableNullChecks
|
||||
If Not *MsgPackData
|
||||
DebuggerError("A #Null MsgPackData pointer was passed !")
|
||||
ProcedureReturn #MsgPack_Error_NullPointerGiven
|
||||
EndIf
|
||||
CompilerEndIf
|
||||
|
||||
If _MsgPackHasFlag(*MsgPackData, #MsgPack_DataFlags_CannotGrow)
|
||||
*MsgPackData\LastError = #MsgPack_Error_CannotGrowBufferDueToConfig
|
||||
ProcedureReturn #MsgPack_Error_CannotGrowBufferDueToConfig
|
||||
EndIf
|
||||
|
||||
If DesiredSizeIncrease <= 0
|
||||
DebuggerError("Negative growth value was passed !")
|
||||
*MsgPackData\LastError = #MsgPack_Error_InvalidValue
|
||||
ProcedureReturn #MsgPack_Error_InvalidValue
|
||||
EndIf
|
||||
|
||||
If *MsgPackData\BufferGrowthIncrement <= 1
|
||||
GrowthSize = DesiredSizeIncrease
|
||||
NewSize = *MsgPackData\BufferSize + GrowthSize
|
||||
Else
|
||||
GrowthSize = (DesiredSizeIncrease % *MsgPackData\BufferGrowthIncrement) + DesiredSizeIncrease
|
||||
NewSize = ((*MsgPackData\BufferSize + GrowthSize) % *MsgPackData\BufferGrowthIncrement) + (*MsgPackData\BufferSize + GrowthSize)
|
||||
EndIf
|
||||
|
||||
If (GrowthSize < 0) Or (*MsgPackData\BufferSize + GrowthSize < 0) Or (NewSize < 0) Or (NewSize < *MsgPackData\BufferSize)
|
||||
DebuggerError("We had an overflow in one of the growth values, the calculation is messed up !")
|
||||
*MsgPackData\LastError = #MsgPack_Error_ValueOverflow
|
||||
ProcedureReturn #MsgPack_Error_ValueOverflow
|
||||
EndIf
|
||||
|
||||
*NewBuffer = ReAllocateMemory(*MsgPackData\Buffer, NewSize)
|
||||
If Not *NewBuffer
|
||||
DebuggerError("Failed to reallocate memory for buffer !")
|
||||
|
||||
*MsgPackData\LastError = #MsgPack_Error_FailedToGrowBuffer
|
||||
ProcedureReturn #MsgPack_Error_FailedToGrowBuffer
|
||||
EndIf
|
||||
|
||||
*MsgPackData\Buffer = *NewBuffer
|
||||
*MsgPackData\BufferSize = NewSize
|
||||
|
||||
; Often set by the callers, but programmers are likely to use this
|
||||
; function directly, so I'm leaving it here.
|
||||
*MsgPackData\LastError = #MsgPack_Error_Success
|
||||
ProcedureReturn #MsgPack_Error_Success
|
||||
EndProcedure
|
||||
|
||||
@@ -30,6 +30,7 @@ CompilerIf #PB_Compiler_IsMainFile
|
||||
CompilerEndIf
|
||||
|
||||
XIncludeFile "./_Commons.pbi"
|
||||
XIncludeFile "./_Allocators.pbi"
|
||||
|
||||
|
||||
|
||||
|
||||
+18
-60
@@ -138,12 +138,14 @@ Enumeration _MsgPack_ErrorCodes
|
||||
; Common errors
|
||||
#MsgPack_Error_NullPointerGiven = 1
|
||||
#MsgPack_Error_BufferTooSmall = 2
|
||||
#MsgPack_Error_InvalidValue = 3
|
||||
#MsgPack_Error_ValueOverflow = 4
|
||||
|
||||
; Shouldn't re-use it.
|
||||
#MsgPack_Error_FailedToGrowBuffer = 3
|
||||
#MsgPack_Error_AtOrPastTheEndOfBuffer = 4
|
||||
#MsgPack_Error_ReadPastEndOfBuffer = 5
|
||||
#MsgPack_Error_InvalidFormatCode = 6
|
||||
#MsgPack_Error_FailedToGrowBuffer = 10
|
||||
#MsgPack_Error_AtOrPastTheEndOfBuffer = 11
|
||||
#MsgPack_Error_ReadPastEndOfBuffer = 12
|
||||
#MsgPack_Error_InvalidFormatCode = 13
|
||||
|
||||
; 5x - Binary
|
||||
#MsgPack_Error_BinaryDataSizeIsNegative = 50
|
||||
@@ -154,15 +156,14 @@ Enumeration _MsgPack_ErrorCodes
|
||||
EndEnumeration
|
||||
|
||||
EnumerationBinary _MsgPack_DataFlags
|
||||
; Not implemented
|
||||
; FIXME: Not implemented
|
||||
#MsgPack_DataFlags_IsReadOnly = %0000000000000001
|
||||
|
||||
; FIXME: Not implemented
|
||||
; Prevents a `MsgPackData` structure from auto-growing its buffer when needed.
|
||||
; It may make some functions return `#`
|
||||
; It may make some functions return `#MsgPack_Error_CannotGrowBufferDueToConfig`.
|
||||
#MsgPack_DataFlags_CannotGrow = %0000000000000010
|
||||
|
||||
; Not implemented
|
||||
; FIXME: Not implemented
|
||||
#MsgPack_DataFlags_NoBufferFree = %0000000000000100
|
||||
|
||||
; Indicates a given `MsgPackData` should increment its buffer offset after
|
||||
@@ -173,11 +174,12 @@ EnumerationBinary _MsgPack_DataFlags
|
||||
; writing a value using the standard procedures.
|
||||
#MsgPack_DataFlags_MoveOffsetAfterWrite = %0000000000010000
|
||||
|
||||
; FIXME: Not implemented
|
||||
; Indicates a given `MsgPackData` is made to be iterated on.
|
||||
; And it implies it represents a Map or Array.
|
||||
#MsgPack_DataFlags_Iterator = %0000000000001000
|
||||
#MsgPack_DataFlags_CanProvideKeys = %0000000000010000
|
||||
#MsgPack_DataFlags_CanProvideVals = %0000000000100000
|
||||
#MsgPack_DataFlags_Iterator = %0000000000100000
|
||||
#MsgPack_DataFlags_CanProvideKeys = %0000000001000000
|
||||
#MsgPack_DataFlags_CanProvideVals = %0000000010000000
|
||||
EndEnumeration
|
||||
|
||||
EnumerationBinary _MsgPack_ExaminationOptions
|
||||
@@ -212,8 +214,11 @@ Structure MsgPackData
|
||||
; Used in place of `MemorySize()` to reduce syscalls.
|
||||
BufferSize.i
|
||||
|
||||
; Temp mechanism for buffer growth.
|
||||
BufferGrowthIncrements.i
|
||||
; Multiple of which any buffer size increase should match.
|
||||
; Also applies to its initial size. (FIXME)
|
||||
; If the requested size doesn't match one, we'll use the nearest next multiple.
|
||||
; If set to `1` or lower, we'll ignore this mechanism.
|
||||
BufferGrowthIncrement.i
|
||||
|
||||
; IteratorSizeLeft, or snoething like this.
|
||||
|
||||
@@ -260,53 +265,6 @@ Procedure.MsgPack_ErrorCode MsgPackLastError(*MsgPackData.MsgPackData)
|
||||
EndProcedure
|
||||
|
||||
|
||||
; Should be moved to allocators.
|
||||
; But it would fuck up the splitting of responsibility.
|
||||
; TODO: Add callback in the structure, maybe ?
|
||||
; FIXME: Use a .q for the size !!!!
|
||||
Procedure.MsgPack_ErrorCode MsgPackGrow(*MsgPackData.MsgPackData, MinimalGrowthSize.i = -1)
|
||||
Protected GrowthSize.i
|
||||
Protected *NewBuffer
|
||||
|
||||
CompilerIf Not #MsgPack_DisableNullChecks
|
||||
If Not *MsgPackData
|
||||
DebuggerError("A #Null MsgPackData pointer was passed !")
|
||||
ProcedureReturn #MsgPack_Error_NullPointerGiven
|
||||
EndIf
|
||||
CompilerEndIf
|
||||
|
||||
; Often set by the callers, but programmers are likely to use it too,
|
||||
; so I'm leaving it here.
|
||||
*MsgPackData\LastError = #MsgPack_Error_Success
|
||||
|
||||
If *MsgPackData\BufferGrowthIncrements <= 0
|
||||
DebuggerError("Cannot grow a buffer with no growth increments !")
|
||||
|
||||
*MsgPackData\LastError = #MsgPack_Error_CannotGrowBufferDueToConfig
|
||||
ProcedureReturn #MsgPack_Error_CannotGrowBufferDueToConfig
|
||||
EndIf
|
||||
|
||||
; TODO: Improve logic later, i can't be bothered now
|
||||
GrowthSize = *MsgPackData\BufferGrowthIncrements
|
||||
If MinimalGrowthSize > GrowthSize
|
||||
GrowthSize = ((MinimalGrowthSize + GrowthSize - 1) / GrowthSize) * GrowthSize
|
||||
EndIf
|
||||
|
||||
*NewBuffer = ReAllocateMemory(*MsgPackData\Buffer, *MsgPackData\BufferSize + GrowthSize)
|
||||
If Not *NewBuffer
|
||||
DebuggerError("Failed to reallocate memory for buffer !")
|
||||
|
||||
*MsgPackData\LastError = #MsgPack_Error_FailedToGrowBuffer
|
||||
ProcedureReturn #MsgPack_Error_FailedToGrowBuffer
|
||||
EndIf
|
||||
|
||||
*MsgPackData\Buffer = *NewBuffer
|
||||
*MsgPackData\BufferSize + GrowthSize
|
||||
|
||||
ProcedureReturn #MsgPack_Error_Success
|
||||
EndProcedure
|
||||
|
||||
|
||||
|
||||
; ------------------------------------------------------------------------------
|
||||
;- Debugging
|
||||
|
||||
@@ -24,6 +24,7 @@ CompilerIf #PB_Compiler_IsMainFile
|
||||
CompilerEndIf
|
||||
|
||||
XIncludeFile "./_Commons.pbi"
|
||||
XIncludeFile "./_Allocators.pbi"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ CompilerEndIf
|
||||
|
||||
; Includes the required "Endianness.pbi"
|
||||
XIncludeFile "./_Commons.pbi"
|
||||
XIncludeFile "./_Allocators.pbi"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
;- Compiler directive
|
||||
|
||||
XIncludeFile "./_Commons.pbi"
|
||||
XIncludeFile "./_Allocators.pbi"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
|
||||
EnableExplicit
|
||||
|
||||
XIncludeFile "../_UnitTesting.pbi"
|
||||
XIncludeFile "../../Includes/MessagePack.pbi"
|
||||
|
||||
|
||||
; ???
|
||||
@@ -0,0 +1,43 @@
|
||||
|
||||
EnableExplicit
|
||||
|
||||
XIncludeFile "../_UnitTesting.pbi"
|
||||
XIncludeFile "../../Includes/MessagePack.pbi"
|
||||
|
||||
|
||||
; Setup
|
||||
Define *BufferHolder.MsgPackData = MsgPackCreate(1)
|
||||
Define LastMeasuredSize.q = MemorySize(*BufferHolder\Buffer)
|
||||
|
||||
|
||||
; Checking defaults, should be able to grow
|
||||
AssertIsFalse(Bool(_MsgPackHasFlag(*BufferHolder, #MsgPack_DataFlags_CannotGrow)), "The `#MsgPack_DataFlags_CannotGrow` flag isn't set by default.")
|
||||
|
||||
|
||||
; Testing null
|
||||
AssertEquals(MsgPackGrow(#Null, 64), #MsgPack_Error_NullPointerGiven, "Passing #Null is rejected properly")
|
||||
|
||||
|
||||
; Testing negative growth
|
||||
AssertEquals(MsgPackGrow(*BufferHolder, -1), #MsgPack_Error_InvalidValue, "Negative growth is blocked.")
|
||||
AssertEquals(*BufferHolder\LastError, #MsgPack_Error_InvalidValue, "Negative growth's error is set in structure.")
|
||||
|
||||
|
||||
; Testing blocked growth
|
||||
*BufferHolder\DataFlags = *BufferHolder\DataFlags | #MsgPack_DataFlags_CannotGrow
|
||||
AssertIsTrue(Bool(_MsgPackHasFlag(*BufferHolder, #MsgPack_DataFlags_CannotGrow)), "The `#MsgPack_DataFlags_CannotGrow` flag is now set.")
|
||||
|
||||
AssertEquals(MsgPackGrow(*BufferHolder, 64), #MsgPack_Error_CannotGrowBufferDueToConfig, "Testing disabled growth.")
|
||||
AssertEquals(*BufferHolder\LastError, #MsgPack_Error_CannotGrowBufferDueToConfig, "Blocked growth's error is set in structure.")
|
||||
|
||||
AssertEquals(*BufferHolder\BufferSize, LastMeasuredSize, "Buffer's length is untouched. (1)")
|
||||
AssertEquals(MemorySize(*BufferHolder\Buffer), LastMeasuredSize, "Buffer's length is untouched. (2)")
|
||||
|
||||
|
||||
If FailedUnitTests
|
||||
End 1
|
||||
EndIf
|
||||
|
||||
Debug "Done !"
|
||||
|
||||
End 0
|
||||
Reference in New Issue
Block a user