Added parameter and test for growth increments and rounding

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-10-24 08:27:22 +02:00
parent e3ffec7547
commit c177dbf142
2 changed files with 96 additions and 6 deletions
+16 -6
View File
@@ -28,20 +28,25 @@ XIncludeFile "./_Commons.pbi"
;-> Thingies
Procedure.i MsgPackCreate(InitialSize.i)
Procedure.i MsgPackCreate(InitialSize.i, GrowthIncrement.i = 1)
Protected *ReturnedValue.MsgPackData = #Null
If InitialSize <= 0
DebuggerWarning("Returning #Null, requested size was zero or negative")
ProcedureReturn #Null
EndIf
If GrowthIncrement <= 0
DebuggerWarning("Returning #Null, growth increment was zero or negative")
ProcedureReturn #Null
EndIf
*ReturnedValue = AllocateStructure(MsgPackData)
If *ReturnedValue <> #Null
*ReturnedValue\BufferOffset = 0
*ReturnedValue\BufferSize = InitialSize
*ReturnedValue\BufferGrowthIncrement = InitialSize
*ReturnedValue\BufferGrowthIncrement = GrowthIncrement
*ReturnedValue\DataFlags = 0
*ReturnedValue\Buffer = AllocateMemory(InitialSize)
@@ -60,12 +65,17 @@ EndProcedure
; be grown or freed by this include, and the caller must free it themselves.
; If `GiveOwnership` is `#True`, `*Buffer` MUST come from `AllocateMemory()`, since it
; may be reallocated when growing, and it can be freed through `MsgPackFree()`.
Procedure.i MsgPackWrapMsgBuffer(*Buffer, BufferSize.i, GiveOwnership.b = #False)
Procedure.i MsgPackWrapMsgBuffer(*Buffer, BufferSize.i, GiveOwnership.b = #False, GrowthIncrement.i = 1)
Protected *ReturnedValue.MsgPackData = #Null
If *Buffer = #Null Or BufferSize <= 0
ProcedureReturn #Null
EndIf
If GrowthIncrement <= 0
DebuggerWarning("Returning #Null, growth increment was zero or negative")
ProcedureReturn #Null
EndIf
*ReturnedValue = AllocateStructure(MsgPackData)
If *ReturnedValue = #Null
@@ -74,7 +84,7 @@ Procedure.i MsgPackWrapMsgBuffer(*Buffer, BufferSize.i, GiveOwnership.b = #False
*ReturnedValue\BufferOffset = 0
*ReturnedValue\BufferSize = BufferSize
*ReturnedValue\BufferGrowthIncrement = 0
*ReturnedValue\BufferGrowthIncrement = GrowthIncrement
*ReturnedValue\DataFlags = 0
*ReturnedValue\Buffer = *Buffer
@@ -0,0 +1,80 @@
EnableExplicit
XIncludeFile "../_UnitTesting.pbi"
XIncludeFile "../../Includes/MessagePack.pbi"
; Default growth increment is 1, no rounding
Define *BufferHolder.MsgPackData = MsgPackCreate(16)
AssertEquals(*BufferHolder\BufferGrowthIncrement, 1, "Default growth increment is 1.")
AssertEquals(MsgPackGrow(*BufferHolder, 3), #MsgPack_Error_Success, "Growing 16 by 3 with the default increment.")
AssertEquals(*BufferHolder\BufferSize, 19, "Size is exactly 19.")
MsgPackFree(*BufferHolder, #True)
; Rounding up to the next multiple of the growth increment
*BufferHolder = MsgPackCreate(16, 16)
AssertEquals(MsgPackGrow(*BufferHolder, 2), #MsgPack_Error_Success, "Growing 16 by 2 with an increment of 16.")
AssertEquals(*BufferHolder\BufferSize, 32, "Size was rounded up to 32. (1)")
AssertEquals(MemorySize(*BufferHolder\Buffer), 32, "Size was rounded up to 32. (2)")
AssertEquals(MsgPackGrow(*BufferHolder, 17), #MsgPack_Error_Success, "Growing 32 by 17 with an increment of 16.")
AssertEquals(*BufferHolder\BufferSize, 64, "Size was rounded up to 64.")
AssertEquals(MsgPackGrow(*BufferHolder, 16), #MsgPack_Error_Success, "Growing 64 by an exact multiple.")
AssertEquals(*BufferHolder\BufferSize, 80, "Size is exactly 80.")
*BufferHolder\BufferGrowthIncrement = 1
AssertEquals(MsgPackGrow(*BufferHolder, 3), #MsgPack_Error_Success, "Growing 80 by 3 without increment.")
AssertEquals(*BufferHolder\BufferSize, 83, "Size is exactly 83.")
MsgPackFree(*BufferHolder, #True)
; Writers only grow by the missing amount
*BufferHolder = MsgPackCreate(4)
*BufferHolder\BufferOffset = 3
AssertEquals(MsgPackWriteUInt16(*BufferHolder, $1234), #MsgPack_Error_Success, "Writing 3 bytes at offset 3 of a 4 bytes buffer.")
AssertEquals(*BufferHolder\BufferSize, 6, "Buffer grew by the 2 missing bytes only.")
AssertEquals(*BufferHolder\BufferOffset, 6, "Offset is now at the end.")
MsgPackFree(*BufferHolder, #True)
; Wrapped buffer that stays owned by the caller
Define *RawBuffer = AllocateMemory(2)
*BufferHolder = MsgPackWrapMsgBuffer(*RawBuffer, 2)
AssertIsTrue(Bool(_MsgPackHasFlag(*BufferHolder, #MsgPack_DataFlags_CannotGrow)), "Non-owned wrap cannot grow.")
AssertIsTrue(Bool(_MsgPackHasFlag(*BufferHolder, #MsgPack_DataFlags_NoBufferFree)), "Non-owned wrap cannot be freed.")
AssertEquals(MsgPackWriteUInt16(*BufferHolder, $1234), #MsgPack_Error_CannotGrowBufferDueToConfig, "Writing past a non-owned wrap is refused.")
AssertEquals(*BufferHolder\Buffer, *RawBuffer, "Buffer pointer is untouched.")
AssertEquals(*BufferHolder\BufferSize, 2, "Buffer size is untouched.")
AssertIsTrue(MsgPackFree(*BufferHolder, #False), "Non-owned wrap is freed without its buffer.")
FreeMemory(*RawBuffer)
; Wrapped buffer whose ownership is given
*RawBuffer = AllocateMemory(2)
*BufferHolder = MsgPackWrapMsgBuffer(*RawBuffer, 2, #True)
AssertIsFalse(Bool(_MsgPackHasFlag(*BufferHolder, #MsgPack_DataFlags_CannotGrow)), "Owned wrap can grow.")
AssertIsFalse(Bool(_MsgPackHasFlag(*BufferHolder, #MsgPack_DataFlags_NoBufferFree)), "Owned wrap can be freed.")
AssertEquals(MsgPackWriteUInt16(*BufferHolder, $1234), #MsgPack_Error_Success, "Writing past an owned wrap grows it.")
AssertEquals(*BufferHolder\BufferSize, 3, "Buffer grew by the missing byte.")
AssertIsTrue(MsgPackFree(*BufferHolder, #True), "Owned wrap is freed with its buffer.")
If FailedUnitTests
End 1
EndIf
Debug "Done !"
End 0