//////////////////////////////////////////////////////////// //~ Bitbuff types //- Buff Struct(BB_Buff) { b32 is_backed_by_arena; /* If `is_arena_bitbuff` is 1, this dynamically-sized arena will be used for reading & writing (meaning writing cannot overflow) */ Arena *arena; /* If `is_arena_bitbuff` is 0, this fixed-sized buffer willl be used for reading & writing */ String fixed_buffer; }; //- Writer /* NOTE: base_len is not stored with the writer (as it is with the reader) since a dynamic arena-backed bitbuff could grow, meaning len needs to be re-checked */ #define BB_WriterOverflowArenaPushSize 4096 Struct(BB_Writer) { b32 overflowed; BB_Buff *bb; u8 *base; u64 cur_bit; #if BITBUFF_DEBUG b32 debug_enabled; #endif }; //- Reader Struct(BB_Reader) { b32 overflowed; u64 base_len; u8 *base; u64 cur_bit; #if BITBUFF_DEBUG b32 debug_enabled; #endif }; //////////////////////////////////////////////////////////// //~ Debug types #if BITBUFF_DEBUG /* Magic numbers inserted to verify read/write type & length */ Enum(BB_DebugMagicKind) { BB_DebugMagicKind_AlignBytes = 0x20A4, BB_DebugMagicKind_AlignToNextByte = 0x379A, BB_DebugMagicKind_UBits = 0xCB4A, BB_DebugMagicKind_IBits = 0xB30D, BB_DebugMagicKind_UV = 0xE179, BB_DebugMagicKind_IV = 0x981f, BB_DebugMagicKind_F32 = 0x56F9, BB_DebugMagicKind_F64 = 0x7053, BB_DebugMagicKind_Uid = 0xA24E, BB_DebugMagicKind_String = 0x7866 }; #endif //////////////////////////////////////////////////////////// //~ Buff management //- Growable-arena backed bitbuff BB_Buff BB_AcquireBuff(u64 arena_reserve); void BB_ReleaseBuff(BB_Buff *bitbuff); //- Fixed-buffer backed bitbuff BB_Buff BB_BuffFromString(String s); //////////////////////////////////////////////////////////// //~ Writer management BB_Writer BB_WriterFromBuff(BB_Buff *bb); BB_Writer BB_WriterFromBuffNoDebug(BB_Buff *bb); u64 BB_GetNumBitsWritten(BB_Writer *bw); u64 BB_GetNumBytesWritten(BB_Writer *bw); String BB_GetWritten(Arena *arena, BB_Writer *bw); u8 *BB_GetWrittenRaw(BB_Writer *bw); b32 BB_CheckWriterOverflowBits(BB_Writer *bw, u64 num_bits); //////////////////////////////////////////////////////////// //~ Writer ops //- Align void BB_WriteAlignToNextByte(BB_Writer *bw); void BB_WriteAlignBytes(BB_Writer *bw, u64 align); //- Bits void BB_WriteUBitsNoMagic(BB_Writer *bw, u64 value, u8 num_bits); void BB_WriteUBits(BB_Writer *bw, u64 value, u8 num_bits); void BB_WriteIBits(BB_Writer *bw, i64 value, u8 num_bits); b32 BB_WriteBit(BB_Writer *bw, u8 value); //- Variable length integers void BB_WriteUV(BB_Writer *bw, u64 value); void BB_WriteIV(BB_Writer *bw, i64 value); //- Floating point void BB_WriteF32(BB_Writer *bw, f32 value); void BB_WriteF64(BB_Writer *bw, f64 value); //- Uid void BB_WriteUid(BB_Writer *bw, Uid value); //- Raw data void BB_WriteString(BB_Writer *bw, String s); void BB_WriteBytes(BB_Writer *bw, String bytes); void BB_WriteSeekBytes(BB_Writer *bw, u64 num_bytes); //////////////////////////////////////////////////////////// //~ Writer debug #if BITBUFF_DEBUG void BB_WriteDebugMagic(BB_Writer *bw, BB_DebugMagicKind magic, u8 num_bits); void BB_WriteDebugMarker(BB_Writer *bw, String name); #else #define BB_WriteDebugMagic(bw, magic, num_bits) #define BB_WriteDebugMarker(bw, name) #endif //////////////////////////////////////////////////////////// //~ Reader management BB_Reader BB_ReaderFromBuff(BB_Buff *bb); BB_Reader BB_ReaderFromBuffNoDebug(BB_Buff *bb); u64 BB_GetCurrentReaderBit(BB_Reader *br); u64 BB_GetCurrentReaderByte(BB_Reader *br); u64 BB_NumBitsRemaining(BB_Reader *br); u64 BB_NumBytesRemaining(BB_Reader *br); b32 BB_CheckReaderOverflowBits(BB_Reader *br, u64 num_bits); //////////////////////////////////////////////////////////// //~ Reader ops //- Align void BB_ReadAlignToNextByte(BB_Reader *br); void BB_ReadAlignBytes(BB_Reader *br, u64 align); //- Bits u64 BB_ReadUBitsNoMagic(BB_Reader *br, u8 num_bits); u64 BB_ReadUBits(BB_Reader *br, u8 num_bits); i64 BB_ReadIBits(BB_Reader *br, u8 num_bits); u8 BB_ReadBit(BB_Reader *br); //- Variable length integers u64 BB_ReadUV(BB_Reader *br); i64 BB_ReadIV(BB_Reader *br); //- Floating point f32 BB_ReadF32(BB_Reader *br); f64 BB_ReadF64(BB_Reader *br); //- Uid Uid BB_ReadUid(BB_Reader *br); //- Raw data String BB_ReadString(Arena *arena, BB_Reader *br); void BB_ReadBytes(BB_Reader *br, String dst); u8 *BB_ReadBytesRaw(BB_Reader *br, u64 num_bytes); void BB_ReadSeekBytes(BB_Reader *br, u64 num_bytes); void BB_ReadSeekToByte(BB_Reader *br, u64 pos); //////////////////////////////////////////////////////////// //~ Reader debug #if BITBUFF_DEBUG void BB_ReadDebugMagic(BB_Reader *br, BB_DebugMagicKind expected_magic, u8 expected_num_bits); void BB_ReadDebugMarker(BB_Reader *br, String name); #else #define BB_ReadDebugMagic(br, expected_magic, expected_num_bits) #define BB_ReadDebugMarker(br, name) #endif //////////////////////////////////////////////////////////// //~ Utils u64 BB_TwosComplimentFromUint(u64 value, u8 num_bits); i64 BB_IntFromTwosCompliment(u64 tc, u8 num_bits); //////////////////////////////////////////////////////////// //~ Test #if BITBUFF_TEST void BB_Test(void); #endif