mirror of
https://github.com/aziascreations/PB-MessagePack.git
synced 2026-11-03 17:01:24 +01:00
201 lines
6.8 KiB
Plaintext
201 lines
6.8 KiB
Plaintext
;{- Code Header
|
|
; ==- Basic Info -================================
|
|
; Name: _Strings.pbi
|
|
; Version: 0.0.1
|
|
; Author: Herwin Bozet (NibblePoker)
|
|
;
|
|
; ==- Compatibility -=============================
|
|
; Tested compiler version:
|
|
; * PureBasic 5.73 LTS (x86/x64)
|
|
; * PureBasic 6.21 (x86/x64)
|
|
; * PureBasic 6.21 C Backend (x86/x64/arm64)
|
|
;
|
|
; ==- Links & License -===========================
|
|
; License: CC0 1.0 Universal (Public Domain)
|
|
; GitHub: https://github.com/aziascreations/PB-MessagePack
|
|
;}
|
|
|
|
; ------------------------------------------------------------------------------
|
|
;- Notes
|
|
|
|
; The spec defines str as UTF-8, which is the default everywhere.
|
|
; `#PB_Ascii` and `#PB_Unicode` (UTF-16 LE) are supported for peers that don't follow it.
|
|
; Sizes are always in bytes of the encoded string, without any null terminator.
|
|
; Strings containing a null character will be truncated on read, as with `PeekS()`.
|
|
|
|
|
|
|
|
; ------------------------------------------------------------------------------
|
|
;- Compiler directive
|
|
|
|
CompilerIf #PB_Compiler_IsMainFile
|
|
EnableExplicit
|
|
CompilerEndIf
|
|
|
|
XIncludeFile "./_Commons.pbi"
|
|
XIncludeFile "./_Allocators.pbi"
|
|
XIncludeFile "./_Binary.pbi"
|
|
|
|
|
|
|
|
; ------------------------------------------------------------------------------
|
|
;- Private macros
|
|
|
|
Macro _MsgPackIsSupportedStringEncoding(Encoding)
|
|
(Encoding = #PB_UTF8 Or Encoding = #PB_Ascii Or Encoding = #PB_Unicode)
|
|
EndMacro
|
|
|
|
|
|
|
|
; ------------------------------------------------------------------------------
|
|
;- Procedures
|
|
|
|
;-> Internal helpers
|
|
|
|
; Returns the byte length of `String` once encoded in `Encoding`, without a null terminator.
|
|
; Sets the structure's error code and returns `#MsgPack_InvalidSize` on unsupported encodings.
|
|
Procedure.q _MsgPackGetEncodedStringSize(*MsgPackData.MsgPackData, String.s, Encoding.i)
|
|
CompilerIf Not #MsgPack_DisableNullChecks
|
|
If Not *MsgPackData
|
|
DebuggerError("A #Null MsgPackData pointer was passed !")
|
|
ProcedureReturn #MsgPack_InvalidSize
|
|
EndIf
|
|
CompilerEndIf
|
|
|
|
If Not _MsgPackIsSupportedStringEncoding(Encoding)
|
|
DebuggerError("Unsupported string encoding: " + Str(Encoding))
|
|
*MsgPackData\LastError = #MsgPack_Error_UnsupportedStringEncoding
|
|
ProcedureReturn #MsgPack_InvalidSize
|
|
EndIf
|
|
|
|
ProcedureReturn StringByteLength(String, Encoding)
|
|
EndProcedure
|
|
|
|
|
|
; Writes a full str field whose encoded size is already known.
|
|
; Sets the structure's error code and returns it.
|
|
Procedure.MsgPack_ErrorCode _MsgPackWriteStringField(*MsgPackData.MsgPackData, FormatCode.MsgPack_FormatCode, SizeFieldByteLength.a, String.s, StringSize.q, Encoding.i)
|
|
Protected ErrorCode.MsgPack_ErrorCode
|
|
|
|
ErrorCode = _MsgPackWriteSizedFieldHeader(*MsgPackData, FormatCode, SizeFieldByteLength, StringSize)
|
|
If ErrorCode <> #MsgPack_Error_Success
|
|
ProcedureReturn ErrorCode
|
|
EndIf
|
|
|
|
If StringSize > 0
|
|
PokeS(*MsgPackData\Buffer + *MsgPackData\BufferOffset, String, -1, Encoding | #PB_String_NoZero)
|
|
*MsgPackData\BufferOffset = *MsgPackData\BufferOffset + StringSize
|
|
EndIf
|
|
_MsgPackRewindOffsetAfterWrite(*MsgPackData, 1 + SizeFieldByteLength + StringSize)
|
|
|
|
ProcedureReturn #MsgPack_Error_Success
|
|
EndProcedure
|
|
|
|
|
|
; Writes a str field with an explicit format code.
|
|
; Sets the structure's error code and returns it.
|
|
Procedure.MsgPack_ErrorCode _MsgPackWriteStringAs(*MsgPackData.MsgPackData, FormatCode.MsgPack_FormatCode, SizeFieldByteLength.a, String.s, Encoding.i)
|
|
Protected StringSize.q
|
|
|
|
StringSize = _MsgPackGetEncodedStringSize(*MsgPackData, String, Encoding)
|
|
If StringSize = #MsgPack_InvalidSize
|
|
ProcedureReturn MsgPackLastError(*MsgPackData)
|
|
EndIf
|
|
|
|
ProcedureReturn _MsgPackWriteStringField(*MsgPackData, FormatCode, SizeFieldByteLength, String, StringSize, Encoding)
|
|
EndProcedure
|
|
|
|
|
|
|
|
;-> Getters
|
|
|
|
; Reads the str field at the current offset and decodes it from `Encoding`.
|
|
; Returns: The decoded string.
|
|
; OnError: Returns `""` and sets the `MsgPackData\LastError` field.
|
|
Procedure.s MsgPackReadString(*MsgPackData.MsgPackData, Encoding.i = #PB_UTF8)
|
|
Protected HeaderSize.i
|
|
Protected StringSize.q
|
|
Protected *StringStart
|
|
Protected ReturnedValue.s = ""
|
|
|
|
If _MsgPackReadSizedFieldHeader(*MsgPackData, #MsgPack_DataTypes_String, @HeaderSize, @StringSize) <> #MsgPack_Error_Success
|
|
ProcedureReturn ""
|
|
EndIf
|
|
|
|
If Not _MsgPackIsSupportedStringEncoding(Encoding)
|
|
DebuggerError("Unsupported string encoding: " + Str(Encoding))
|
|
*MsgPackData\LastError = #MsgPack_Error_UnsupportedStringEncoding
|
|
ProcedureReturn ""
|
|
EndIf
|
|
|
|
If Encoding = #PB_Unicode And StringSize % 2 <> 0
|
|
Debug("UTF-16 string has an odd byte size !")
|
|
*MsgPackData\LastError = #MsgPack_Error_InvalidStringSize
|
|
ProcedureReturn ""
|
|
EndIf
|
|
|
|
*StringStart = *MsgPackData\Buffer + *MsgPackData\BufferOffset + HeaderSize
|
|
|
|
If StringSize > 0
|
|
Select Encoding
|
|
Case #PB_UTF8
|
|
ReturnedValue = PeekS(*StringStart, StringSize, #PB_UTF8 | #PB_ByteLength)
|
|
Case #PB_Ascii
|
|
ReturnedValue = PeekS(*StringStart, StringSize, #PB_Ascii)
|
|
Case #PB_Unicode
|
|
ReturnedValue = PeekS(*StringStart, StringSize / 2, #PB_Unicode)
|
|
EndSelect
|
|
EndIf
|
|
|
|
_MsgPackMoveOffsetAfterRead(*MsgPackData, HeaderSize + StringSize)
|
|
|
|
ProcedureReturn ReturnedValue
|
|
EndProcedure
|
|
|
|
|
|
|
|
;-> Setters
|
|
|
|
; Writes `String` encoded as `Encoding` using the smallest str format code that fits.
|
|
; Returns `#MsgPack_Error_Success` on success, something else otherwise.
|
|
Procedure.MsgPack_ErrorCode MsgPackWriteString(*MsgPackData.MsgPackData, String.s, Encoding.i = #PB_UTF8)
|
|
Protected StringSize.q
|
|
|
|
StringSize = _MsgPackGetEncodedStringSize(*MsgPackData, String, Encoding)
|
|
If StringSize = #MsgPack_InvalidSize
|
|
ProcedureReturn MsgPackLastError(*MsgPackData)
|
|
EndIf
|
|
|
|
If StringSize <= 31
|
|
ProcedureReturn _MsgPackWriteStringField(*MsgPackData, #MsgPack_FormatCode_FixStr, 0, String, StringSize, Encoding)
|
|
ElseIf StringSize <= 255
|
|
ProcedureReturn _MsgPackWriteStringField(*MsgPackData, #MsgPack_FormatCode_Str8, 1, String, StringSize, Encoding)
|
|
ElseIf StringSize <= 65535
|
|
ProcedureReturn _MsgPackWriteStringField(*MsgPackData, #MsgPack_FormatCode_Str16, 2, String, StringSize, Encoding)
|
|
Else
|
|
; Sizes above `(2^32)-1` are rejected by the helper.
|
|
ProcedureReturn _MsgPackWriteStringField(*MsgPackData, #MsgPack_FormatCode_Str32, 4, String, StringSize, Encoding)
|
|
EndIf
|
|
EndProcedure
|
|
|
|
|
|
|
|
; ------------------------------------------------------------------------------
|
|
;- Macros
|
|
|
|
Macro MsgPackWriteFixStr(MsgPackData, String, Encoding = #PB_UTF8)
|
|
_MsgPackWriteStringAs(MsgPackData, #MsgPack_FormatCode_FixStr, 0, String, Encoding)
|
|
EndMacro
|
|
|
|
Macro MsgPackWriteStr8(MsgPackData, String, Encoding = #PB_UTF8)
|
|
_MsgPackWriteStringAs(MsgPackData, #MsgPack_FormatCode_Str8, 1, String, Encoding)
|
|
EndMacro
|
|
|
|
Macro MsgPackWriteStr16(MsgPackData, String, Encoding = #PB_UTF8)
|
|
_MsgPackWriteStringAs(MsgPackData, #MsgPack_FormatCode_Str16, 2, String, Encoding)
|
|
EndMacro
|
|
|
|
Macro MsgPackWriteStr32(MsgPackData, String, Encoding = #PB_UTF8)
|
|
_MsgPackWriteStringAs(MsgPackData, #MsgPack_FormatCode_Str32, 4, String, Encoding)
|
|
EndMacro
|