mirror of
https://github.com/aziascreations/PB-MessagePack.git
synced 2026-11-03 17:01:24 +01:00
Updated primitives to new helper-based structure, Added generic reader/writer too
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -131,6 +131,32 @@ PureBasic include for creating/reading MessagePack data.
|
||||
Returns `#MsgPack_Error_Success` on success, something else otherwise.
|
||||
|
||||
|
||||
### Integers & Floats
|
||||
* `MsgPackWriteInteger.MsgPack_ErrorCode(*MsgPackData.MsgPackData, Value.q)` \
|
||||
Writes `Value` using the smallest int format code that fits, fixints included. \
|
||||
Positive values always use the unsigned format codes. \
|
||||
UInt64 values above `(2^63)-1` must be written with `MsgPackWriteUInt64`.
|
||||
|
||||
* `MsgPackWriteFixInt.MsgPack_ErrorCode(*MsgPackData.MsgPackData, Value.q)` \
|
||||
Writes `Value` as a fixint, from `-32` to `127`. \
|
||||
Returns `#MsgPack_Error_ValueOverflow` if it doesn't fit.
|
||||
|
||||
* `MsgPackWrite/Read[U]Int8/16/32/64`, `MsgPackWrite/ReadFloat32/64` \
|
||||
Force the given format code. Aliases: `MsgPackWrite/ReadU8`, `I8`, ..., `F64`. \
|
||||
`UInt32` and `UInt64` use `.l` and `.q`, so their values above the signed max come back negative.
|
||||
|
||||
* `MsgPackReadInteger.q(*MsgPackData.MsgPackData)` \
|
||||
Reads any int field at the current internal offset, fixints included. \
|
||||
Returns `0` on errors and sets the internal error code. \
|
||||
UInt64 values above `(2^63)-1` fail with `#MsgPack_Error_ValueOverflow` without moving the offset, so they can be read with `MsgPackReadUInt64`. \
|
||||
See: `MsgPackLastError`
|
||||
|
||||
* `MsgPackReadFloat.d(*MsgPackData.MsgPackData)` \
|
||||
Reads any float field at the current internal offset. \
|
||||
Returns `0` on errors and sets the internal error code. \
|
||||
See: `MsgPackLastError`
|
||||
|
||||
|
||||
### Binary
|
||||
* `MsgPackWriteBinary.MsgPack_ErrorCode(*MsgPackData.MsgPackData, *Buffer, BufferSize.q)` \
|
||||
Writes `BufferSize` bytes from `*Buffer` using the smallest bin format code that fits. \
|
||||
|
||||
+237
-208
@@ -26,6 +26,7 @@ CompilerEndIf
|
||||
; Includes the required "Endianness.pbi"
|
||||
XIncludeFile "./_Commons.pbi"
|
||||
XIncludeFile "./_Allocators.pbi"
|
||||
XIncludeFile "./_Utils.pbi"
|
||||
|
||||
|
||||
|
||||
@@ -96,255 +97,283 @@ EndProcedure
|
||||
|
||||
|
||||
|
||||
;-> Getters & Setters
|
||||
; The "fixed field" helpers below handle every `[FormatCode][Value]` layout
|
||||
; shared by the int and float families.
|
||||
; The `ValueByteLength` parameter is the number of bytes used to store the value:
|
||||
; * `0` - Value is stored in the format code's lower bits. (FixIntPositive, FixIntNegative)
|
||||
; * `1` - UInt8, Int8
|
||||
; * `2` - UInt16, Int16
|
||||
; * `4` - UInt32, Int32, Float32
|
||||
; * `8` - UInt64, Int64, Float64
|
||||
; Values are passed around as raw bits in a quad, floats included.
|
||||
|
||||
;-> > UInt8
|
||||
Procedure.MsgPack_ErrorCode MsgPackWriteUInt8(*MsgPackData.MsgPackData, Value.a)
|
||||
; Reserves space for the whole field, writes its format code and big-endian value,
|
||||
; and moves the offset right after them.
|
||||
; Sets the structure's error code and returns it.
|
||||
Procedure.MsgPack_ErrorCode _MsgPackWriteFixedField(*MsgPackData.MsgPackData, FormatCode.MsgPack_FormatCode, ValueByteLength.a, Value.q)
|
||||
Protected ErrorCode.MsgPack_ErrorCode
|
||||
|
||||
ErrorCode = _MsgPackReserveWrite(*MsgPackData, 2)
|
||||
|
||||
ErrorCode = _MsgPackReserveWrite(*MsgPackData, 1 + ValueByteLength)
|
||||
If ErrorCode <> #MsgPack_Error_Success
|
||||
ProcedureReturn ErrorCode
|
||||
EndIf
|
||||
|
||||
PokeA(*MsgPackData\Buffer + *MsgPackData\BufferOffset, #MsgPack_FormatCode_UInt8)
|
||||
PokeA(*MsgPackData\Buffer + *MsgPackData\BufferOffset + 1, Value)
|
||||
*MsgPackData\BufferOffset = *MsgPackData\BufferOffset + 2
|
||||
|
||||
|
||||
Select ValueByteLength
|
||||
Case 0
|
||||
PokeA(*MsgPackData\Buffer + *MsgPackData\BufferOffset, FormatCode | (Value & $FF))
|
||||
Case 1
|
||||
PokeA(*MsgPackData\Buffer + *MsgPackData\BufferOffset, FormatCode)
|
||||
PokeA(*MsgPackData\Buffer + *MsgPackData\BufferOffset + 1, Value)
|
||||
Case 2
|
||||
PokeA(*MsgPackData\Buffer + *MsgPackData\BufferOffset, FormatCode)
|
||||
PokeU(*MsgPackData\Buffer + *MsgPackData\BufferOffset + 1, EndianSwapU16(Value))
|
||||
Case 4
|
||||
PokeA(*MsgPackData\Buffer + *MsgPackData\BufferOffset, FormatCode)
|
||||
PokeL(*MsgPackData\Buffer + *MsgPackData\BufferOffset + 1, EndianSwapI32(Value))
|
||||
Case 8
|
||||
PokeA(*MsgPackData\Buffer + *MsgPackData\BufferOffset, FormatCode)
|
||||
PokeQ(*MsgPackData\Buffer + *MsgPackData\BufferOffset + 1, EndianSwapI64(Value))
|
||||
EndSelect
|
||||
*MsgPackData\BufferOffset = *MsgPackData\BufferOffset + 1 + ValueByteLength
|
||||
|
||||
ProcedureReturn #MsgPack_Error_Success
|
||||
EndProcedure
|
||||
|
||||
|
||||
Procedure.a MsgPackReadUInt8(*MsgPackData.MsgPackData)
|
||||
Protected ReturnedValue.a
|
||||
|
||||
If _MsgPackExpectRead(*MsgPackData, #MsgPack_FormatCode_UInt8, 2) <> #MsgPack_Error_Success
|
||||
; Reads the value of the field at the current offset if its format code is `FormatCode`.
|
||||
; Doesn't support fixints, since their format code varies with the value.
|
||||
; Returns: The value's raw bits, zero-extended. (e.g.: `$FF` for an Int8 `-1`)
|
||||
; OnError: Returns `0` and sets the `MsgPackData\LastError` field.
|
||||
Procedure.q _MsgPackReadFixedField(*MsgPackData.MsgPackData, FormatCode.MsgPack_FormatCode, ValueByteLength.a)
|
||||
Protected ReturnedValue.q
|
||||
|
||||
If _MsgPackExpectRead(*MsgPackData, FormatCode, 1 + ValueByteLength) <> #MsgPack_Error_Success
|
||||
ProcedureReturn 0
|
||||
EndIf
|
||||
|
||||
ReturnedValue = PeekA(*MsgPackData\Buffer + *MsgPackData\BufferOffset + 1)
|
||||
*MsgPackData\BufferOffset = *MsgPackData\BufferOffset + 2
|
||||
|
||||
|
||||
Select ValueByteLength
|
||||
Case 1
|
||||
ReturnedValue = PeekA(*MsgPackData\Buffer + *MsgPackData\BufferOffset + 1)
|
||||
Case 2
|
||||
ReturnedValue = EndianSwapU16(PeekU(*MsgPackData\Buffer + *MsgPackData\BufferOffset + 1))
|
||||
Case 4
|
||||
ReturnedValue = EndianSwapI32(PeekL(*MsgPackData\Buffer + *MsgPackData\BufferOffset + 1)) & $FFFFFFFF
|
||||
Case 8
|
||||
ReturnedValue = EndianSwapI64(PeekQ(*MsgPackData\Buffer + *MsgPackData\BufferOffset + 1))
|
||||
EndSelect
|
||||
*MsgPackData\BufferOffset = *MsgPackData\BufferOffset + 1 + ValueByteLength
|
||||
|
||||
ProcedureReturn ReturnedValue
|
||||
EndProcedure
|
||||
|
||||
|
||||
|
||||
;-> Getters & Setters
|
||||
|
||||
;-> > UInt8
|
||||
Procedure.MsgPack_ErrorCode MsgPackWriteUInt8(*MsgPackData.MsgPackData, Value.a)
|
||||
ProcedureReturn _MsgPackWriteFixedField(*MsgPackData, #MsgPack_FormatCode_UInt8, 1, Value)
|
||||
EndProcedure
|
||||
|
||||
|
||||
Procedure.a MsgPackReadUInt8(*MsgPackData.MsgPackData)
|
||||
ProcedureReturn _MsgPackReadFixedField(*MsgPackData, #MsgPack_FormatCode_UInt8, 1)
|
||||
EndProcedure
|
||||
|
||||
|
||||
;-> > Int8
|
||||
Procedure.MsgPack_ErrorCode MsgPackWriteInt8(*MsgPackData.MsgPackData, Value.b)
|
||||
Protected ErrorCode.MsgPack_ErrorCode
|
||||
|
||||
ErrorCode = _MsgPackReserveWrite(*MsgPackData, 2)
|
||||
If ErrorCode <> #MsgPack_Error_Success
|
||||
ProcedureReturn ErrorCode
|
||||
EndIf
|
||||
|
||||
PokeA(*MsgPackData\Buffer + *MsgPackData\BufferOffset, #MsgPack_FormatCode_Int8)
|
||||
PokeB(*MsgPackData\Buffer + *MsgPackData\BufferOffset + 1, Value)
|
||||
*MsgPackData\BufferOffset = *MsgPackData\BufferOffset + 2
|
||||
|
||||
ProcedureReturn #MsgPack_Error_Success
|
||||
ProcedureReturn _MsgPackWriteFixedField(*MsgPackData, #MsgPack_FormatCode_Int8, 1, Value)
|
||||
EndProcedure
|
||||
|
||||
|
||||
Procedure.b MsgPackReadInt8(*MsgPackData.MsgPackData)
|
||||
Protected ReturnedValue.b
|
||||
|
||||
If _MsgPackExpectRead(*MsgPackData, #MsgPack_FormatCode_Int8, 2) <> #MsgPack_Error_Success
|
||||
ProcedureReturn 0
|
||||
EndIf
|
||||
|
||||
ReturnedValue = PeekB(*MsgPackData\Buffer + *MsgPackData\BufferOffset + 1)
|
||||
*MsgPackData\BufferOffset = *MsgPackData\BufferOffset + 2
|
||||
|
||||
ProcedureReturn ReturnedValue
|
||||
ProcedureReturn _MsgPackReadFixedField(*MsgPackData, #MsgPack_FormatCode_Int8, 1)
|
||||
EndProcedure
|
||||
|
||||
|
||||
;-> > UInt16
|
||||
Procedure.MsgPack_ErrorCode MsgPackWriteUInt16(*MsgPackData.MsgPackData, Value.u)
|
||||
Protected ErrorCode.MsgPack_ErrorCode
|
||||
|
||||
ErrorCode = _MsgPackReserveWrite(*MsgPackData, 3)
|
||||
If ErrorCode <> #MsgPack_Error_Success
|
||||
ProcedureReturn ErrorCode
|
||||
EndIf
|
||||
|
||||
PokeA(*MsgPackData\Buffer + *MsgPackData\BufferOffset, #MsgPack_FormatCode_UInt16)
|
||||
PokeU(*MsgPackData\Buffer + *MsgPackData\BufferOffset + 1, EndianSwapU16(Value))
|
||||
*MsgPackData\BufferOffset = *MsgPackData\BufferOffset + 3
|
||||
|
||||
ProcedureReturn #MsgPack_Error_Success
|
||||
ProcedureReturn _MsgPackWriteFixedField(*MsgPackData, #MsgPack_FormatCode_UInt16, 2, Value)
|
||||
EndProcedure
|
||||
|
||||
|
||||
Procedure.u MsgPackReadUInt16(*MsgPackData.MsgPackData)
|
||||
Protected ReturnedValue.u
|
||||
|
||||
If _MsgPackExpectRead(*MsgPackData, #MsgPack_FormatCode_UInt16, 3) <> #MsgPack_Error_Success
|
||||
ProcedureReturn 0
|
||||
EndIf
|
||||
|
||||
ReturnedValue = EndianSwapU16(PeekU(*MsgPackData\Buffer + *MsgPackData\BufferOffset + 1))
|
||||
*MsgPackData\BufferOffset = *MsgPackData\BufferOffset + 3
|
||||
|
||||
ProcedureReturn ReturnedValue
|
||||
ProcedureReturn _MsgPackReadFixedField(*MsgPackData, #MsgPack_FormatCode_UInt16, 2)
|
||||
EndProcedure
|
||||
|
||||
|
||||
;-> > > Int16
|
||||
Procedure.MsgPack_ErrorCode MsgPackWriteInt16(*MsgPackData.MsgPackData, Value.w)
|
||||
Protected ErrorCode.MsgPack_ErrorCode
|
||||
|
||||
ErrorCode = _MsgPackReserveWrite(*MsgPackData, 3)
|
||||
If ErrorCode <> #MsgPack_Error_Success
|
||||
ProcedureReturn ErrorCode
|
||||
EndIf
|
||||
|
||||
PokeA(*MsgPackData\Buffer + *MsgPackData\BufferOffset, #MsgPack_FormatCode_Int16)
|
||||
PokeW(*MsgPackData\Buffer + *MsgPackData\BufferOffset + 1, EndianSwapI16(Value))
|
||||
*MsgPackData\BufferOffset = *MsgPackData\BufferOffset + 3
|
||||
|
||||
ProcedureReturn #MsgPack_Error_Success
|
||||
ProcedureReturn _MsgPackWriteFixedField(*MsgPackData, #MsgPack_FormatCode_Int16, 2, Value)
|
||||
EndProcedure
|
||||
|
||||
|
||||
Procedure.w MsgPackReadInt16(*MsgPackData.MsgPackData)
|
||||
Protected ReturnedValue.w
|
||||
|
||||
If _MsgPackExpectRead(*MsgPackData, #MsgPack_FormatCode_Int16, 3) <> #MsgPack_Error_Success
|
||||
ProcedureReturn 0
|
||||
EndIf
|
||||
|
||||
ReturnedValue = EndianSwapI16(PeekW(*MsgPackData\Buffer + *MsgPackData\BufferOffset + 1))
|
||||
*MsgPackData\BufferOffset = *MsgPackData\BufferOffset + 3
|
||||
|
||||
ProcedureReturn ReturnedValue
|
||||
ProcedureReturn _MsgPackReadFixedField(*MsgPackData, #MsgPack_FormatCode_Int16, 2)
|
||||
EndProcedure
|
||||
|
||||
|
||||
;-> > > UInt32
|
||||
; No unsigned Long in PureBasic: value is peeked/poked as-is via .l and returned unchanged.
|
||||
Procedure.MsgPack_ErrorCode MsgPackWriteUInt32(*MsgPackData.MsgPackData, Value.l)
|
||||
Protected ErrorCode.MsgPack_ErrorCode
|
||||
|
||||
ErrorCode = _MsgPackReserveWrite(*MsgPackData, 5)
|
||||
If ErrorCode <> #MsgPack_Error_Success
|
||||
ProcedureReturn ErrorCode
|
||||
EndIf
|
||||
|
||||
PokeA(*MsgPackData\Buffer + *MsgPackData\BufferOffset, #MsgPack_FormatCode_UInt32)
|
||||
PokeL(*MsgPackData\Buffer + *MsgPackData\BufferOffset + 1, EndianSwapI32(Value))
|
||||
*MsgPackData\BufferOffset = *MsgPackData\BufferOffset + 5
|
||||
|
||||
ProcedureReturn #MsgPack_Error_Success
|
||||
ProcedureReturn _MsgPackWriteFixedField(*MsgPackData, #MsgPack_FormatCode_UInt32, 4, Value)
|
||||
EndProcedure
|
||||
|
||||
|
||||
Procedure.l MsgPackReadUInt32(*MsgPackData.MsgPackData)
|
||||
Protected ReturnedValue.l
|
||||
|
||||
If _MsgPackExpectRead(*MsgPackData, #MsgPack_FormatCode_UInt32, 5) <> #MsgPack_Error_Success
|
||||
ProcedureReturn 0
|
||||
EndIf
|
||||
|
||||
ReturnedValue = EndianSwapI32(PeekL(*MsgPackData\Buffer + *MsgPackData\BufferOffset + 1))
|
||||
*MsgPackData\BufferOffset = *MsgPackData\BufferOffset + 5
|
||||
|
||||
ProcedureReturn ReturnedValue
|
||||
ProcedureReturn _MsgPackReadFixedField(*MsgPackData, #MsgPack_FormatCode_UInt32, 4)
|
||||
EndProcedure
|
||||
|
||||
|
||||
;-> > > Int32
|
||||
Procedure.MsgPack_ErrorCode MsgPackWriteInt32(*MsgPackData.MsgPackData, Value.l)
|
||||
Protected ErrorCode.MsgPack_ErrorCode
|
||||
|
||||
ErrorCode = _MsgPackReserveWrite(*MsgPackData, 5)
|
||||
If ErrorCode <> #MsgPack_Error_Success
|
||||
ProcedureReturn ErrorCode
|
||||
EndIf
|
||||
|
||||
PokeA(*MsgPackData\Buffer + *MsgPackData\BufferOffset, #MsgPack_FormatCode_Int32)
|
||||
PokeL(*MsgPackData\Buffer + *MsgPackData\BufferOffset + 1, EndianSwapI32(Value))
|
||||
*MsgPackData\BufferOffset = *MsgPackData\BufferOffset + 5
|
||||
|
||||
ProcedureReturn #MsgPack_Error_Success
|
||||
ProcedureReturn _MsgPackWriteFixedField(*MsgPackData, #MsgPack_FormatCode_Int32, 4, Value)
|
||||
EndProcedure
|
||||
|
||||
|
||||
Procedure.l MsgPackReadInt32(*MsgPackData.MsgPackData)
|
||||
Protected ReturnedValue.l
|
||||
|
||||
If _MsgPackExpectRead(*MsgPackData, #MsgPack_FormatCode_Int32, 5) <> #MsgPack_Error_Success
|
||||
ProcedureReturn 0
|
||||
EndIf
|
||||
|
||||
ReturnedValue = EndianSwapI32(PeekL(*MsgPackData\Buffer + *MsgPackData\BufferOffset + 1))
|
||||
*MsgPackData\BufferOffset = *MsgPackData\BufferOffset + 5
|
||||
|
||||
ProcedureReturn ReturnedValue
|
||||
ProcedureReturn _MsgPackReadFixedField(*MsgPackData, #MsgPack_FormatCode_Int32, 4)
|
||||
EndProcedure
|
||||
|
||||
|
||||
;-> > > UInt64
|
||||
; No unsigned Quad in PureBasic: value is peeked/poked as-is via .q and returned unchanged.
|
||||
Procedure.MsgPack_ErrorCode MsgPackWriteUInt64(*MsgPackData.MsgPackData, Value.q)
|
||||
Protected ErrorCode.MsgPack_ErrorCode
|
||||
|
||||
ErrorCode = _MsgPackReserveWrite(*MsgPackData, 9)
|
||||
If ErrorCode <> #MsgPack_Error_Success
|
||||
ProcedureReturn ErrorCode
|
||||
EndIf
|
||||
|
||||
PokeA(*MsgPackData\Buffer + *MsgPackData\BufferOffset, #MsgPack_FormatCode_UInt64)
|
||||
PokeQ(*MsgPackData\Buffer + *MsgPackData\BufferOffset + 1, EndianSwapI64(Value))
|
||||
*MsgPackData\BufferOffset = *MsgPackData\BufferOffset + 9
|
||||
|
||||
ProcedureReturn #MsgPack_Error_Success
|
||||
ProcedureReturn _MsgPackWriteFixedField(*MsgPackData, #MsgPack_FormatCode_UInt64, 8, Value)
|
||||
EndProcedure
|
||||
|
||||
|
||||
Procedure.q MsgPackReadUInt64(*MsgPackData.MsgPackData)
|
||||
Protected ReturnedValue.q
|
||||
|
||||
If _MsgPackExpectRead(*MsgPackData, #MsgPack_FormatCode_UInt64, 9) <> #MsgPack_Error_Success
|
||||
ProcedureReturn 0
|
||||
EndIf
|
||||
|
||||
ReturnedValue = EndianSwapI64(PeekQ(*MsgPackData\Buffer + *MsgPackData\BufferOffset + 1))
|
||||
*MsgPackData\BufferOffset = *MsgPackData\BufferOffset + 9
|
||||
|
||||
ProcedureReturn ReturnedValue
|
||||
ProcedureReturn _MsgPackReadFixedField(*MsgPackData, #MsgPack_FormatCode_UInt64, 8)
|
||||
EndProcedure
|
||||
|
||||
|
||||
;-> > > Int64
|
||||
Procedure.MsgPack_ErrorCode MsgPackWriteInt64(*MsgPackData.MsgPackData, Value.q)
|
||||
Protected ErrorCode.MsgPack_ErrorCode
|
||||
|
||||
ErrorCode = _MsgPackReserveWrite(*MsgPackData, 9)
|
||||
If ErrorCode <> #MsgPack_Error_Success
|
||||
ProcedureReturn ErrorCode
|
||||
EndIf
|
||||
|
||||
PokeA(*MsgPackData\Buffer + *MsgPackData\BufferOffset, #MsgPack_FormatCode_Int64)
|
||||
PokeQ(*MsgPackData\Buffer + *MsgPackData\BufferOffset + 1, EndianSwapI64(Value))
|
||||
*MsgPackData\BufferOffset = *MsgPackData\BufferOffset + 9
|
||||
|
||||
ProcedureReturn #MsgPack_Error_Success
|
||||
ProcedureReturn _MsgPackWriteFixedField(*MsgPackData, #MsgPack_FormatCode_Int64, 8, Value)
|
||||
EndProcedure
|
||||
|
||||
|
||||
Procedure.q MsgPackReadInt64(*MsgPackData.MsgPackData)
|
||||
ProcedureReturn _MsgPackReadFixedField(*MsgPackData, #MsgPack_FormatCode_Int64, 8)
|
||||
EndProcedure
|
||||
|
||||
|
||||
;-> > > FixInt
|
||||
|
||||
; Writes `Value` as a positive (`0` to `127`) or negative (`-32` to `-1`) fixint.
|
||||
; Returns `#MsgPack_Error_Success` on success, something else otherwise.
|
||||
Procedure.MsgPack_ErrorCode MsgPackWriteFixInt(*MsgPackData.MsgPackData, Value.q)
|
||||
CompilerIf Not #MsgPack_DisableNullChecks
|
||||
If Not *MsgPackData
|
||||
DebuggerError("A #Null MsgPackData pointer was passed !")
|
||||
ProcedureReturn #MsgPack_Error_NullPointerGiven
|
||||
EndIf
|
||||
CompilerEndIf
|
||||
|
||||
If Value >= 0 And Value <= 127
|
||||
ProcedureReturn _MsgPackWriteFixedField(*MsgPackData, #MsgPack_FormatCode_FixIntPositive, 0, Value)
|
||||
ElseIf Value >= -32 And Value < 0
|
||||
ProcedureReturn _MsgPackWriteFixedField(*MsgPackData, #MsgPack_FormatCode_FixIntNegative, 0, Value)
|
||||
EndIf
|
||||
|
||||
DebuggerWarning("Value doesn't fit in a fixint: " + Str(Value))
|
||||
*MsgPackData\LastError = #MsgPack_Error_ValueOverflow
|
||||
ProcedureReturn #MsgPack_Error_ValueOverflow
|
||||
EndProcedure
|
||||
|
||||
|
||||
;-> > > Any integer
|
||||
|
||||
; Writes `Value` using the smallest int format code that fits.
|
||||
; Positive values always use the unsigned format codes, as recommended by the spec.
|
||||
; Returns `#MsgPack_Error_Success` on success, something else otherwise.
|
||||
; Remark: UInt64 values above `(2^63)-1` must be written with `MsgPackWriteUInt64()`.
|
||||
Procedure.MsgPack_ErrorCode MsgPackWriteInteger(*MsgPackData.MsgPackData, Value.q)
|
||||
If Value >= 0
|
||||
If Value <= 127
|
||||
ProcedureReturn _MsgPackWriteFixedField(*MsgPackData, #MsgPack_FormatCode_FixIntPositive, 0, Value)
|
||||
ElseIf Value <= 255
|
||||
ProcedureReturn _MsgPackWriteFixedField(*MsgPackData, #MsgPack_FormatCode_UInt8, 1, Value)
|
||||
ElseIf Value <= 65535
|
||||
ProcedureReturn _MsgPackWriteFixedField(*MsgPackData, #MsgPack_FormatCode_UInt16, 2, Value)
|
||||
ElseIf Value <= 4294967295
|
||||
ProcedureReturn _MsgPackWriteFixedField(*MsgPackData, #MsgPack_FormatCode_UInt32, 4, Value)
|
||||
Else
|
||||
ProcedureReturn _MsgPackWriteFixedField(*MsgPackData, #MsgPack_FormatCode_UInt64, 8, Value)
|
||||
EndIf
|
||||
Else
|
||||
If Value >= -32
|
||||
ProcedureReturn _MsgPackWriteFixedField(*MsgPackData, #MsgPack_FormatCode_FixIntNegative, 0, Value)
|
||||
ElseIf Value >= -128
|
||||
ProcedureReturn _MsgPackWriteFixedField(*MsgPackData, #MsgPack_FormatCode_Int8, 1, Value)
|
||||
ElseIf Value >= -32768
|
||||
ProcedureReturn _MsgPackWriteFixedField(*MsgPackData, #MsgPack_FormatCode_Int16, 2, Value)
|
||||
ElseIf Value >= -2147483648
|
||||
ProcedureReturn _MsgPackWriteFixedField(*MsgPackData, #MsgPack_FormatCode_Int32, 4, Value)
|
||||
Else
|
||||
ProcedureReturn _MsgPackWriteFixedField(*MsgPackData, #MsgPack_FormatCode_Int64, 8, Value)
|
||||
EndIf
|
||||
EndIf
|
||||
EndProcedure
|
||||
|
||||
|
||||
; Reads any int field at the current offset, fixints included.
|
||||
; Returns: The value as a signed quad.
|
||||
; OnError: Returns `0` and sets the `MsgPackData\LastError` field.
|
||||
; UInt64 values above `(2^63)-1` fail with `#MsgPack_Error_ValueOverflow` and
|
||||
; leave the offset untouched, so they can be read with `MsgPackReadUInt64()`.
|
||||
Procedure.q MsgPackReadInteger(*MsgPackData.MsgPackData)
|
||||
Protected ReturnedValue.q
|
||||
|
||||
If _MsgPackExpectRead(*MsgPackData, #MsgPack_FormatCode_Int64, 9) <> #MsgPack_Error_Success
|
||||
|
||||
CompilerIf Not #MsgPack_DisableNullChecks
|
||||
If Not *MsgPackData
|
||||
DebuggerError("A #Null MsgPackData pointer was passed !")
|
||||
ProcedureReturn 0
|
||||
EndIf
|
||||
CompilerEndIf
|
||||
|
||||
If _MsgPackIsAtTheEnd(*MsgPackData)
|
||||
Debug("End of buffer reached, cannot check data format code !")
|
||||
*MsgPackData\LastError = #MsgPack_Error_AtOrPastTheEndOfBuffer
|
||||
ProcedureReturn 0
|
||||
EndIf
|
||||
|
||||
ReturnedValue = EndianSwapI64(PeekQ(*MsgPackData\Buffer + *MsgPackData\BufferOffset + 1))
|
||||
*MsgPackData\BufferOffset = *MsgPackData\BufferOffset + 9
|
||||
|
||||
ProcedureReturn ReturnedValue
|
||||
|
||||
Select MsgPackGetFormatCode(*MsgPackData)
|
||||
Case #MsgPack_FormatCode_FixIntPositive,
|
||||
#MsgPack_FormatCode_FixIntNegative:
|
||||
; The whole byte is the value, both ranges are valid signed bytes.
|
||||
ReturnedValue = PeekB(*MsgPackData\Buffer + *MsgPackData\BufferOffset)
|
||||
*MsgPackData\BufferOffset = *MsgPackData\BufferOffset + 1
|
||||
*MsgPackData\LastError = #MsgPack_Error_Success
|
||||
ProcedureReturn ReturnedValue
|
||||
Case #MsgPack_FormatCode_UInt8:
|
||||
ProcedureReturn _MsgPackReadFixedField(*MsgPackData, #MsgPack_FormatCode_UInt8, 1)
|
||||
Case #MsgPack_FormatCode_UInt16:
|
||||
ProcedureReturn _MsgPackReadFixedField(*MsgPackData, #MsgPack_FormatCode_UInt16, 2)
|
||||
Case #MsgPack_FormatCode_UInt32:
|
||||
ProcedureReturn _MsgPackReadFixedField(*MsgPackData, #MsgPack_FormatCode_UInt32, 4)
|
||||
Case #MsgPack_FormatCode_UInt64:
|
||||
If _MsgPackHasSpaceLeft(*MsgPackData, 9) And (PeekA(*MsgPackData\Buffer + *MsgPackData\BufferOffset + 1) & $80)
|
||||
Debug("UInt64 value doesn't fit in a signed quad !")
|
||||
*MsgPackData\LastError = #MsgPack_Error_ValueOverflow
|
||||
ProcedureReturn 0
|
||||
EndIf
|
||||
ProcedureReturn _MsgPackReadFixedField(*MsgPackData, #MsgPack_FormatCode_UInt64, 8)
|
||||
Case #MsgPack_FormatCode_Int8:
|
||||
ProcedureReturn MsgPackReadInt8(*MsgPackData)
|
||||
Case #MsgPack_FormatCode_Int16:
|
||||
ProcedureReturn MsgPackReadInt16(*MsgPackData)
|
||||
Case #MsgPack_FormatCode_Int32:
|
||||
ProcedureReturn MsgPackReadInt32(*MsgPackData)
|
||||
Case #MsgPack_FormatCode_Int64:
|
||||
ProcedureReturn MsgPackReadInt64(*MsgPackData)
|
||||
EndSelect
|
||||
|
||||
Debug("Unexpected format code ! (" + RSet(Hex(PeekA(*MsgPackData\Buffer + *MsgPackData\BufferOffset)), 2, "0") + ")")
|
||||
*MsgPackData\LastError = #MsgPack_Error_InvalidFormatCode
|
||||
ProcedureReturn 0
|
||||
EndProcedure
|
||||
|
||||
|
||||
@@ -353,31 +382,15 @@ EndProcedure
|
||||
; The value's bits are moved and swapped as an integer, since loading a byte-swapped
|
||||
; float into the FPU can alter its bits. (e.g.: NaN quieting on x87)
|
||||
Procedure.MsgPack_ErrorCode MsgPackWriteFloat32(*MsgPackData.MsgPackData, Value.f)
|
||||
Protected ErrorCode.MsgPack_ErrorCode
|
||||
|
||||
ErrorCode = _MsgPackReserveWrite(*MsgPackData, 5)
|
||||
If ErrorCode <> #MsgPack_Error_Success
|
||||
ProcedureReturn ErrorCode
|
||||
EndIf
|
||||
|
||||
PokeA(*MsgPackData\Buffer + *MsgPackData\BufferOffset, #MsgPack_FormatCode_Float32)
|
||||
PokeL(*MsgPackData\Buffer + *MsgPackData\BufferOffset + 1, EndianSwapI32(PeekL(@Value)))
|
||||
*MsgPackData\BufferOffset = *MsgPackData\BufferOffset + 5
|
||||
|
||||
ProcedureReturn #MsgPack_Error_Success
|
||||
ProcedureReturn _MsgPackWriteFixedField(*MsgPackData, #MsgPack_FormatCode_Float32, 4, PeekL(@Value))
|
||||
EndProcedure
|
||||
|
||||
|
||||
Procedure.f MsgPackReadFloat32(*MsgPackData.MsgPackData)
|
||||
Protected ReturnedValue.f
|
||||
|
||||
If _MsgPackExpectRead(*MsgPackData, #MsgPack_FormatCode_Float32, 5) <> #MsgPack_Error_Success
|
||||
ProcedureReturn 0
|
||||
EndIf
|
||||
|
||||
PokeL(@ReturnedValue, EndianSwapI32(PeekL(*MsgPackData\Buffer + *MsgPackData\BufferOffset + 1)))
|
||||
*MsgPackData\BufferOffset = *MsgPackData\BufferOffset + 5
|
||||
|
||||
|
||||
PokeL(@ReturnedValue, _MsgPackReadFixedField(*MsgPackData, #MsgPack_FormatCode_Float32, 4))
|
||||
|
||||
ProcedureReturn ReturnedValue
|
||||
EndProcedure
|
||||
|
||||
@@ -387,32 +400,48 @@ EndProcedure
|
||||
; The value's bits are moved and swapped as an integer, since loading a byte-swapped
|
||||
; float into the FPU can alter its bits. (e.g.: NaN quieting on x87)
|
||||
Procedure.MsgPack_ErrorCode MsgPackWriteFloat64(*MsgPackData.MsgPackData, Value.d)
|
||||
Protected ErrorCode.MsgPack_ErrorCode
|
||||
|
||||
ErrorCode = _MsgPackReserveWrite(*MsgPackData, 9)
|
||||
If ErrorCode <> #MsgPack_Error_Success
|
||||
ProcedureReturn ErrorCode
|
||||
EndIf
|
||||
|
||||
PokeA(*MsgPackData\Buffer + *MsgPackData\BufferOffset, #MsgPack_FormatCode_Float64)
|
||||
PokeQ(*MsgPackData\Buffer + *MsgPackData\BufferOffset + 1, EndianSwapI64(PeekQ(@Value)))
|
||||
*MsgPackData\BufferOffset = *MsgPackData\BufferOffset + 9
|
||||
|
||||
ProcedureReturn #MsgPack_Error_Success
|
||||
ProcedureReturn _MsgPackWriteFixedField(*MsgPackData, #MsgPack_FormatCode_Float64, 8, PeekQ(@Value))
|
||||
EndProcedure
|
||||
|
||||
|
||||
Procedure.d MsgPackReadFloat64(*MsgPackData.MsgPackData)
|
||||
Protected ReturnedValue.d
|
||||
|
||||
If _MsgPackExpectRead(*MsgPackData, #MsgPack_FormatCode_Float64, 9) <> #MsgPack_Error_Success
|
||||
|
||||
PokeQ(@ReturnedValue, _MsgPackReadFixedField(*MsgPackData, #MsgPack_FormatCode_Float64, 8))
|
||||
|
||||
ProcedureReturn ReturnedValue
|
||||
EndProcedure
|
||||
|
||||
|
||||
;-> > > Any float
|
||||
|
||||
; Reads any float field at the current offset.
|
||||
; Returns: The value as a double, float32 values being widened losslessly.
|
||||
; OnError: Returns `0` and sets the `MsgPackData\LastError` field.
|
||||
Procedure.d MsgPackReadFloat(*MsgPackData.MsgPackData)
|
||||
CompilerIf Not #MsgPack_DisableNullChecks
|
||||
If Not *MsgPackData
|
||||
DebuggerError("A #Null MsgPackData pointer was passed !")
|
||||
ProcedureReturn 0
|
||||
EndIf
|
||||
CompilerEndIf
|
||||
|
||||
If _MsgPackIsAtTheEnd(*MsgPackData)
|
||||
Debug("End of buffer reached, cannot check data format code !")
|
||||
*MsgPackData\LastError = #MsgPack_Error_AtOrPastTheEndOfBuffer
|
||||
ProcedureReturn 0
|
||||
EndIf
|
||||
|
||||
PokeQ(@ReturnedValue, EndianSwapI64(PeekQ(*MsgPackData\Buffer + *MsgPackData\BufferOffset + 1)))
|
||||
*MsgPackData\BufferOffset = *MsgPackData\BufferOffset + 9
|
||||
|
||||
ProcedureReturn ReturnedValue
|
||||
|
||||
Select MsgPackGetFormatCode(*MsgPackData)
|
||||
Case #MsgPack_FormatCode_Float32:
|
||||
ProcedureReturn MsgPackReadFloat32(*MsgPackData)
|
||||
Case #MsgPack_FormatCode_Float64:
|
||||
ProcedureReturn MsgPackReadFloat64(*MsgPackData)
|
||||
EndSelect
|
||||
|
||||
Debug("Unexpected format code ! (" + RSet(Hex(PeekA(*MsgPackData\Buffer + *MsgPackData\BufferOffset)), 2, "0") + ")")
|
||||
*MsgPackData\LastError = #MsgPack_Error_InvalidFormatCode
|
||||
ProcedureReturn 0
|
||||
EndProcedure
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
EnableExplicit
|
||||
|
||||
XIncludeFile "../_UnitTesting.pbi"
|
||||
XIncludeFile "../../Includes/MessagePack.pbi"
|
||||
|
||||
|
||||
; /!\ Every case here calls `DebuggerError()`, which halts the program under the debugger.
|
||||
; Run it without the debugger and check the exit code.
|
||||
|
||||
|
||||
; Null MsgPack pointers
|
||||
AssertEquals(MsgPackWriteInteger(#Null, 1), #MsgPack_Error_NullPointerGiven, "MsgPackWriteInteger is given #Null for a fixint")
|
||||
AssertEquals(MsgPackWriteInteger(#Null, 100000), #MsgPack_Error_NullPointerGiven, "MsgPackWriteInteger is given #Null for a UInt32")
|
||||
AssertEquals(MsgPackWriteInteger(#Null, -100), #MsgPack_Error_NullPointerGiven, "MsgPackWriteInteger is given #Null for an Int8")
|
||||
AssertEquals(MsgPackWriteFixInt(#Null, 1), #MsgPack_Error_NullPointerGiven, "MsgPackWriteFixInt is given #Null")
|
||||
AssertEquals(MsgPackWriteFixInt(#Null, 1000), #MsgPack_Error_NullPointerGiven, "MsgPackWriteFixInt is given #Null before the range check")
|
||||
AssertEquals(MsgPackWriteUInt8(#Null, 1), #MsgPack_Error_NullPointerGiven, "MsgPackWriteUInt8 is given #Null")
|
||||
AssertEquals(MsgPackWriteInt64(#Null, 1), #MsgPack_Error_NullPointerGiven, "MsgPackWriteInt64 is given #Null")
|
||||
AssertEqualsQ(MsgPackReadInteger(#Null), 0, "MsgPackReadInteger is given #Null")
|
||||
AssertEqualsA(MsgPackReadUInt8(#Null), 0, "MsgPackReadUInt8 is given #Null")
|
||||
AssertEqualsQ(MsgPackReadInt64(#Null), 0, "MsgPackReadInt64 is given #Null")
|
||||
|
||||
; The generic float reader shares the integer one's checks.
|
||||
Assert(Bool(MsgPackReadFloat(#Null) = 0), "MsgPackReadFloat is given #Null")
|
||||
|
||||
|
||||
; Ending
|
||||
If FailedUnitTests
|
||||
End 1
|
||||
EndIf
|
||||
|
||||
Debug "Done !"
|
||||
|
||||
End 0
|
||||
@@ -0,0 +1,194 @@
|
||||
EnableExplicit
|
||||
|
||||
XIncludeFile "../_UnitTesting.pbi"
|
||||
XIncludeFile "../../Includes/MessagePack.pbi"
|
||||
XIncludeFile "../_TestBuffers.pbi"
|
||||
|
||||
|
||||
; Writes `Value` with `MsgPackWriteInteger()` into a 1 byte buffer that has to grow,
|
||||
; checks its first byte and size, and reads it back with `MsgPackReadInteger()`.
|
||||
; For fixints, `ExpectedFirstByte` is the value itself.
|
||||
Procedure CheckInteger(Value.q, ExpectedFirstByte.a, ExpectedSize.i)
|
||||
Protected *MsgPack.MsgPackData = MsgPackCreate(1)
|
||||
Protected Name.s = Str(Value)
|
||||
|
||||
AssertEquals(MsgPackWriteInteger(*MsgPack, Value), #MsgPack_Error_Success, "Wrote " + Name)
|
||||
AssertEquals(*MsgPack\BufferOffset, ExpectedSize, Name + " takes " + Str(ExpectedSize) + " bytes")
|
||||
AssertEquals(*MsgPack\BufferSize, ExpectedSize, Name + " grew the buffer exactly")
|
||||
AssertEqualsA(PeekA(*MsgPack\Buffer), ExpectedFirstByte, Name + " first byte")
|
||||
|
||||
*MsgPack\BufferOffset = 0
|
||||
AssertEqualsQ(MsgPackReadInteger(*MsgPack), Value, "Read back " + Name)
|
||||
AssertEquals(MsgPackLastError(*MsgPack), #MsgPack_Error_Success, "Read back " + Name + " without errors")
|
||||
AssertEquals(*MsgPack\BufferOffset, ExpectedSize, "Read back " + Name + " moved the offset")
|
||||
|
||||
MsgPackFree(*MsgPack, #True)
|
||||
EndProcedure
|
||||
|
||||
|
||||
; Setup
|
||||
Define *MsgPack.MsgPackData
|
||||
Define QuadMin.q = -9223372036854775807 - 1
|
||||
|
||||
|
||||
; Automatic format code selection, on each boundary
|
||||
CheckInteger(0, $00, 1)
|
||||
CheckInteger(1, $01, 1)
|
||||
CheckInteger(127, $7F, 1)
|
||||
CheckInteger(128, #MsgPack_FormatCode_UInt8, 2)
|
||||
CheckInteger(255, #MsgPack_FormatCode_UInt8, 2)
|
||||
CheckInteger(256, #MsgPack_FormatCode_UInt16, 3)
|
||||
CheckInteger(65535, #MsgPack_FormatCode_UInt16, 3)
|
||||
CheckInteger(65536, #MsgPack_FormatCode_UInt32, 5)
|
||||
CheckInteger(4294967295, #MsgPack_FormatCode_UInt32, 5)
|
||||
CheckInteger(4294967296, #MsgPack_FormatCode_UInt64, 9)
|
||||
CheckInteger(9223372036854775807, #MsgPack_FormatCode_UInt64, 9)
|
||||
|
||||
CheckInteger(-1, $FF, 1)
|
||||
CheckInteger(-32, $E0, 1)
|
||||
CheckInteger(-33, #MsgPack_FormatCode_Int8, 2)
|
||||
CheckInteger(-128, #MsgPack_FormatCode_Int8, 2)
|
||||
CheckInteger(-129, #MsgPack_FormatCode_Int16, 3)
|
||||
CheckInteger(-32768, #MsgPack_FormatCode_Int16, 3)
|
||||
CheckInteger(-32769, #MsgPack_FormatCode_Int32, 5)
|
||||
CheckInteger(-2147483648, #MsgPack_FormatCode_Int32, 5)
|
||||
CheckInteger(-2147483649, #MsgPack_FormatCode_Int64, 9)
|
||||
CheckInteger(QuadMin, #MsgPack_FormatCode_Int64, 9)
|
||||
|
||||
|
||||
; Big-endian layouts
|
||||
*MsgPack = MsgPackCreate(16)
|
||||
MsgPackWriteInteger(*MsgPack, 4294967295)
|
||||
MsgPackWriteInteger(*MsgPack, -129)
|
||||
AssertEqualsA(PeekA(*MsgPack\Buffer + 1), $FF, "UInt32 byte 1")
|
||||
AssertEqualsA(PeekA(*MsgPack\Buffer + 4), $FF, "UInt32 byte 4")
|
||||
AssertEqualsA(PeekA(*MsgPack\Buffer + 5), #MsgPack_FormatCode_Int16, "Int16 format code")
|
||||
AssertEqualsA(PeekA(*MsgPack\Buffer + 6), $FF, "Int16 high byte first")
|
||||
AssertEqualsA(PeekA(*MsgPack\Buffer + 7), $7F, "Int16 low byte last")
|
||||
MsgPackFree(*MsgPack, #True)
|
||||
|
||||
|
||||
; Reading values written with forced format codes
|
||||
*MsgPack = MsgPackCreate(1)
|
||||
|
||||
AssertEquals(MsgPackWriteUInt32(*MsgPack, $89ABCDEF), #MsgPack_Error_Success, "Wrote UInt32 with its high bit set")
|
||||
AssertEquals(MsgPackWriteInt8(*MsgPack, -1), #MsgPack_Error_Success, "Wrote Int8")
|
||||
AssertEquals(MsgPackWriteUInt8(*MsgPack, 200), #MsgPack_Error_Success, "Wrote UInt8")
|
||||
AssertEquals(MsgPackWriteInt16(*MsgPack, 5), #MsgPack_Error_Success, "Wrote small Int16")
|
||||
AssertEquals(MsgPackWriteUInt16(*MsgPack, $ABCD), #MsgPack_Error_Success, "Wrote UInt16")
|
||||
AssertEquals(MsgPackWriteInt32(*MsgPack, -123456), #MsgPack_Error_Success, "Wrote Int32")
|
||||
AssertEquals(MsgPackWriteInt64(*MsgPack, -2), #MsgPack_Error_Success, "Wrote small Int64")
|
||||
AssertEquals(MsgPackWriteFixInt(*MsgPack, -5), #MsgPack_Error_Success, "Wrote negative fixint")
|
||||
AssertEquals(MsgPackWriteFixInt(*MsgPack, 100), #MsgPack_Error_Success, "Wrote positive fixint")
|
||||
AssertEquals(MsgPackWriteUInt8(*MsgPack, 42), #MsgPack_Error_Success, "Wrote trailing UInt8")
|
||||
|
||||
AssertEqualsA(PeekA(*MsgPack\Buffer + 5 + 2 + 2 + 3 + 3 + 5 + 9), $FB, "Negative fixint byte")
|
||||
AssertEqualsA(PeekA(*MsgPack\Buffer + 5 + 2 + 2 + 3 + 3 + 5 + 9 + 1), $64, "Positive fixint byte")
|
||||
|
||||
*MsgPack\BufferOffset = 0
|
||||
AssertEqualsQ(MsgPackReadInteger(*MsgPack), $89ABCDEF, "UInt32 is read as unsigned")
|
||||
AssertEqualsQ(MsgPackReadInteger(*MsgPack), -1, "Int8 is read as signed")
|
||||
AssertEqualsQ(MsgPackReadInteger(*MsgPack), 200, "UInt8 is read as unsigned")
|
||||
AssertEqualsQ(MsgPackReadInteger(*MsgPack), 5, "Small Int16 is read")
|
||||
AssertEqualsQ(MsgPackReadInteger(*MsgPack), $ABCD, "UInt16 is read as unsigned")
|
||||
AssertEqualsQ(MsgPackReadInteger(*MsgPack), -123456, "Int32 is read as signed")
|
||||
AssertEqualsQ(MsgPackReadInteger(*MsgPack), -2, "Small Int64 is read")
|
||||
AssertEqualsQ(MsgPackReadInteger(*MsgPack), -5, "Negative fixint is read")
|
||||
AssertEqualsQ(MsgPackReadInteger(*MsgPack), 100, "Positive fixint is read")
|
||||
AssertEqualsA(MsgPackReadUInt8(*MsgPack), 42, "Read trailing UInt8")
|
||||
AssertEquals(*MsgPack\BufferOffset, *MsgPack\BufferSize, "Offset is at the end")
|
||||
AssertEquals(MsgPackLastError(*MsgPack), #MsgPack_Error_Success, "No error after reading")
|
||||
|
||||
MsgPackFree(*MsgPack, #True)
|
||||
|
||||
|
||||
; Known fixint vectors
|
||||
*MsgPack = WrapHex("007F80E0FF")
|
||||
AssertEqualsQ(MsgPackReadInteger(*MsgPack), 0, "0x00 is 0")
|
||||
AssertEqualsQ(MsgPackReadInteger(*MsgPack), 127, "0x7F is 127")
|
||||
AssertEqualsQ(MsgPackReadInteger(*MsgPack), 0, "0x80 is a fixmap, not an int")
|
||||
AssertEquals(MsgPackLastError(*MsgPack), #MsgPack_Error_InvalidFormatCode, "Fixmap error is set")
|
||||
AssertEquals(*MsgPack\BufferOffset, 2, "Offset is untouched by the fixmap")
|
||||
*MsgPack\BufferOffset = 3
|
||||
AssertEqualsQ(MsgPackReadInteger(*MsgPack), -32, "0xE0 is -32")
|
||||
AssertEqualsQ(MsgPackReadInteger(*MsgPack), -1, "0xFF is -1")
|
||||
FreeWrappedHex(*MsgPack)
|
||||
|
||||
|
||||
; Fixints out of range
|
||||
*MsgPack = MsgPackCreate(8)
|
||||
AssertEquals(MsgPackWriteFixInt(*MsgPack, 128), #MsgPack_Error_ValueOverflow, "128 isn't a fixint")
|
||||
AssertEquals(MsgPackLastError(*MsgPack), #MsgPack_Error_ValueOverflow, "Fixint overflow error is set")
|
||||
AssertEquals(MsgPackWriteFixInt(*MsgPack, -33), #MsgPack_Error_ValueOverflow, "-33 isn't a fixint")
|
||||
AssertEquals(MsgPackWriteFixInt(*MsgPack, 256 + 5), #MsgPack_Error_ValueOverflow, "261 isn't truncated into a fixint")
|
||||
AssertEquals(*MsgPack\BufferOffset, 0, "Offset is untouched by rejected writes")
|
||||
AssertEquals(MsgPackWriteFixInt(*MsgPack, 0), #MsgPack_Error_Success, "0 is a fixint")
|
||||
AssertEquals(MsgPackLastError(*MsgPack), #MsgPack_Error_Success, "Successful write cleared the error")
|
||||
MsgPackFree(*MsgPack, #True)
|
||||
|
||||
|
||||
; Buffers that can't grow
|
||||
*MsgPack = WrapHex("0000")
|
||||
AssertEquals(MsgPackWriteInteger(*MsgPack, 256), #MsgPack_Error_CannotGrowBufferDueToConfig, "UInt16's 3 bytes don't fit in 2")
|
||||
AssertEquals(*MsgPack\BufferOffset, 0, "Offset is untouched by the failed write")
|
||||
AssertEquals(MsgPackWriteInteger(*MsgPack, -100), #MsgPack_Error_Success, "Int8's 2 bytes fit exactly")
|
||||
FreeWrappedHex(*MsgPack)
|
||||
|
||||
|
||||
; Reading errors
|
||||
*MsgPack = WrapHex("01")
|
||||
*MsgPack\BufferOffset = 1
|
||||
AssertEqualsQ(MsgPackReadInteger(*MsgPack), 0, "Read at the end fails")
|
||||
AssertEquals(MsgPackLastError(*MsgPack), #MsgPack_Error_AtOrPastTheEndOfBuffer, "Read at the end error is set")
|
||||
FreeWrappedHex(*MsgPack)
|
||||
|
||||
*MsgPack = WrapHex("CA3F800000")
|
||||
AssertEqualsQ(MsgPackReadInteger(*MsgPack), 0, "Reading a float as an int fails")
|
||||
AssertEquals(MsgPackLastError(*MsgPack), #MsgPack_Error_InvalidFormatCode, "Float as int error is set")
|
||||
AssertEquals(*MsgPack\BufferOffset, 0, "Offset is untouched by the wrong format code")
|
||||
FreeWrappedHex(*MsgPack)
|
||||
|
||||
*MsgPack = WrapHex("A161")
|
||||
AssertEqualsQ(MsgPackReadInteger(*MsgPack), 0, "Reading a str as an int fails")
|
||||
AssertEquals(MsgPackLastError(*MsgPack), #MsgPack_Error_InvalidFormatCode, "Str as int error is set")
|
||||
FreeWrappedHex(*MsgPack)
|
||||
|
||||
*MsgPack = WrapHex("CD00")
|
||||
AssertEqualsQ(MsgPackReadInteger(*MsgPack), 0, "UInt16 with half its value fails")
|
||||
AssertEquals(MsgPackLastError(*MsgPack), #MsgPack_Error_BufferTooSmall, "Truncated UInt16 error is set")
|
||||
AssertEquals(*MsgPack\BufferOffset, 0, "Offset is untouched by the truncated value")
|
||||
FreeWrappedHex(*MsgPack)
|
||||
|
||||
*MsgPack = WrapHex("D1")
|
||||
AssertEqualsQ(MsgPackReadInteger(*MsgPack), 0, "Int16 without its value fails")
|
||||
AssertEquals(MsgPackLastError(*MsgPack), #MsgPack_Error_BufferTooSmall, "Truncated Int16 error is set")
|
||||
FreeWrappedHex(*MsgPack)
|
||||
|
||||
|
||||
; UInt64 values that don't fit in a signed quad
|
||||
*MsgPack = WrapHex("CF7FFFFFFFFFFFFFFF")
|
||||
AssertEqualsQ(MsgPackReadInteger(*MsgPack), 9223372036854775807, "UInt64 (2^63)-1 fits")
|
||||
FreeWrappedHex(*MsgPack)
|
||||
|
||||
*MsgPack = WrapHex("CF8000000000000000")
|
||||
AssertEqualsQ(MsgPackReadInteger(*MsgPack), 0, "UInt64 2^63 doesn't fit")
|
||||
AssertEquals(MsgPackLastError(*MsgPack), #MsgPack_Error_ValueOverflow, "UInt64 overflow error is set")
|
||||
AssertEquals(*MsgPack\BufferOffset, 0, "Offset is untouched by the overflow")
|
||||
AssertEqualsQ(MsgPackReadUInt64(*MsgPack), QuadMin, "It can still be read as raw bits with MsgPackReadUInt64")
|
||||
AssertEquals(MsgPackLastError(*MsgPack), #MsgPack_Error_Success, "Raw read is a success")
|
||||
FreeWrappedHex(*MsgPack)
|
||||
|
||||
*MsgPack = WrapHex("CF80")
|
||||
AssertEqualsQ(MsgPackReadInteger(*MsgPack), 0, "Truncated UInt64 with its high bit set fails")
|
||||
AssertEquals(MsgPackLastError(*MsgPack), #MsgPack_Error_BufferTooSmall, "Truncation is reported over the overflow")
|
||||
FreeWrappedHex(*MsgPack)
|
||||
|
||||
|
||||
; Ending
|
||||
If FailedUnitTests
|
||||
End 1
|
||||
EndIf
|
||||
|
||||
Debug "Done !"
|
||||
|
||||
End 0
|
||||
@@ -0,0 +1,58 @@
|
||||
EnableExplicit
|
||||
|
||||
XIncludeFile "../_UnitTesting.pbi"
|
||||
XIncludeFile "../../Includes/MessagePack.pbi"
|
||||
XIncludeFile "../_TestBuffers.pbi"
|
||||
|
||||
|
||||
; Setup
|
||||
Define *MsgPack.MsgPackData = MsgPackCreate(1)
|
||||
|
||||
|
||||
; Reading both float sizes
|
||||
AssertEquals(MsgPackWriteFloat32(*MsgPack, 1.5), #MsgPack_Error_Success, "Wrote Float32")
|
||||
AssertEquals(MsgPackWriteFloat64(*MsgPack, -2.25), #MsgPack_Error_Success, "Wrote Float64")
|
||||
AssertEquals(MsgPackWriteFloat32(*MsgPack, 0.1), #MsgPack_Error_Success, "Wrote inexact Float32")
|
||||
AssertEquals(MsgPackWriteUInt8(*MsgPack, 42), #MsgPack_Error_Success, "Wrote trailing UInt8")
|
||||
|
||||
*MsgPack\BufferOffset = 0
|
||||
Assert(Bool(MsgPackReadFloat(*MsgPack) = 1.5), "Float32 is read")
|
||||
AssertEquals(*MsgPack\BufferOffset, 5, "Float32 moved the offset by 5")
|
||||
Assert(Bool(MsgPackReadFloat(*MsgPack) = -2.25), "Float64 is read")
|
||||
AssertEquals(*MsgPack\BufferOffset, 5 + 9, "Float64 moved the offset by 9")
|
||||
; 0.1 isn't exact as a float32, so it must match the float32 value, not the double one.
|
||||
Assert(Bool(MsgPackReadFloat(*MsgPack) = ValF("0.1")), "Inexact Float32 is widened as-is")
|
||||
AssertEqualsA(MsgPackReadUInt8(*MsgPack), 42, "Read trailing UInt8")
|
||||
AssertEquals(MsgPackLastError(*MsgPack), #MsgPack_Error_Success, "No error after reading")
|
||||
|
||||
MsgPackFree(*MsgPack, #True)
|
||||
|
||||
|
||||
; Reading errors
|
||||
*MsgPack = WrapHex("CA")
|
||||
*MsgPack\BufferOffset = 1
|
||||
Assert(Bool(MsgPackReadFloat(*MsgPack) = 0), "Read at the end fails")
|
||||
AssertEquals(MsgPackLastError(*MsgPack), #MsgPack_Error_AtOrPastTheEndOfBuffer, "Read at the end error is set")
|
||||
FreeWrappedHex(*MsgPack)
|
||||
|
||||
*MsgPack = WrapHex("01")
|
||||
Assert(Bool(MsgPackReadFloat(*MsgPack) = 0), "Reading an int as a float fails")
|
||||
AssertEquals(MsgPackLastError(*MsgPack), #MsgPack_Error_InvalidFormatCode, "Int as float error is set")
|
||||
AssertEquals(*MsgPack\BufferOffset, 0, "Offset is untouched by the wrong format code")
|
||||
FreeWrappedHex(*MsgPack)
|
||||
|
||||
*MsgPack = WrapHex("CB3FF0000000")
|
||||
Assert(Bool(MsgPackReadFloat(*MsgPack) = 0), "Truncated Float64 fails")
|
||||
AssertEquals(MsgPackLastError(*MsgPack), #MsgPack_Error_BufferTooSmall, "Truncated Float64 error is set")
|
||||
AssertEquals(*MsgPack\BufferOffset, 0, "Offset is untouched by the truncated value")
|
||||
FreeWrappedHex(*MsgPack)
|
||||
|
||||
|
||||
; Ending
|
||||
If FailedUnitTests
|
||||
End 1
|
||||
EndIf
|
||||
|
||||
Debug "Done !"
|
||||
|
||||
End 0
|
||||
Reference in New Issue
Block a user