196 lines
5.3 KiB
C
196 lines
5.3 KiB
C
////////////////////////////////////////////////////////////
|
|
//~ 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
|