Skip to content

Commit

Permalink
feat: Add bitstream module
Browse files Browse the repository at this point in the history
  • Loading branch information
mrswastik-robot committed Dec 25, 2024
1 parent b08c5fa commit 83fb2d7
Show file tree
Hide file tree
Showing 4 changed files with 484 additions and 1 deletion.
65 changes: 65 additions & 0 deletions src/lib_ccx/cc_bitstream.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,21 @@
// Hold functions to read streams on a bit or byte oriented basis
// plus some data related helper functions.

#ifndef DISABLE_RUST
extern void* ccxr_init_bitstream(const uint8_t *start, const uint8_t *end);
extern void ccxr_free_bitstream(void *bs);
extern uint64_t ccxr_next_bits(void *bs, uint32_t bnum);
extern uint64_t ccxr_read_bits(void *bs, uint32_t bnum);
extern int ccxr_skip_bits(void *bs, uint32_t bnum);
extern int ccxr_is_byte_aligned(const void *bs);
extern void ccxr_make_byte_aligned(void *bs);
extern const uint8_t* ccxr_next_bytes(void *bs, size_t bynum);
extern const uint8_t* ccxr_read_bytes(void *bs, size_t bynum);
extern uint64_t ccxr_read_exp_golomb_unsigned(void *bs);
extern int64_t ccxr_read_exp_golomb(void *bs);
extern uint8_t ccxr_reverse8(uint8_t data);
#endif

// Guidelines for all bitsream functions:
// * No function shall advance the pointer past the end marker
// * If bitstream.bitsleft < 0 do not attempt any read access,
Expand All @@ -12,6 +27,16 @@
// Initialize bitstream
int init_bitstream(struct bitstream *bstr, unsigned char *start, unsigned char *end)
{
#ifndef DISABLE_RUST
void *rust_bs = ccxr_init_bitstream(start, end);
if (!rust_bs)
{
mprint("init_bitstream: bitstream has negative length!");
return 1;
}
bstr->rust_bs = rust_bs;
#endif

bstr->pos = start;
bstr->bpos = 8;
bstr->end = end;
Expand All @@ -35,6 +60,9 @@ int init_bitstream(struct bitstream *bstr, unsigned char *start, unsigned char *
// there are not enough bits left in the bitstream.
uint64_t next_bits(struct bitstream *bstr, unsigned bnum)
{
#ifndef DISABLE_RUST
return ccxr_next_bits(bstr->rust_bs, bnum);
#else
uint64_t res = 0;

if (bnum > 64)
Expand Down Expand Up @@ -99,12 +127,16 @@ uint64_t next_bits(struct bitstream *bstr, unsigned bnum)
bstr->_i_pos = vpos;

return res;
#endif
}

// Read bnum bits from bitstream bstr with the most significant
// bit read first. A 64 bit unsigned integer is returned.
uint64_t read_bits(struct bitstream *bstr, unsigned bnum)
{
#ifndef DISABLE_RUST
return ccxr_read_bits(bstr->rust_bs, bnum);
#else
uint64_t res = next_bits(bstr, bnum);

// Special case for reading zero bits. Also abort when not enough
Expand All @@ -117,13 +149,17 @@ uint64_t read_bits(struct bitstream *bstr, unsigned bnum)
bstr->pos = bstr->_i_pos;

return res;
#endif
}

// This function will advance the bitstream by bnum bits, if possible.
// Advancing of more than 64 bits is possible.
// Return TRUE when successful, otherwise FALSE
int skip_bits(struct bitstream *bstr, unsigned bnum)
{
#ifndef DISABLE_RUST
return ccxr_skip_bits(bstr->rust_bs, bnum);
#else
// Sanity check
if (bstr->end - bstr->pos < 0)
fatal(CCX_COMMON_EXIT_BUG_BUG, "In skip_bits: bitstream length cannot be negative!");
Expand Down Expand Up @@ -153,13 +189,17 @@ int skip_bits(struct bitstream *bstr, unsigned bnum)
bstr->pos += 1;
}
return 1;
#endif
}

// Return TRUE if the current position in the bitstream is on a byte
// boundary, i.e., the next bit in the bitstream is the first bit in
// a byte, otherwise return FALSE
int is_byte_aligned(struct bitstream *bstr)
{
#ifndef DISABLE_RUST
return ccxr_is_byte_aligned(bstr->rust_bs);
#else
// Sanity check
if (bstr->end - bstr->pos < 0)
fatal(CCX_COMMON_EXIT_BUG_BUG, "In is_byte_aligned: bitstream length can not be negative!");
Expand All @@ -175,11 +215,15 @@ int is_byte_aligned(struct bitstream *bstr)
return 1;
else
return 0;
#endif
}

// Move bitstream to next byte border. Adjust bitsleft.
void make_byte_aligned(struct bitstream *bstr)
{
#ifndef DISABLE_RUST
ccxr_make_byte_aligned(bstr->rust_bs);
#else
// Sanity check
if (bstr->end - bstr->pos < 0)
fatal(CCX_COMMON_EXIT_BUG_BUG, "In make_byte_aligned: bitstream length can not be negative!");
Expand Down Expand Up @@ -208,6 +252,7 @@ void make_byte_aligned(struct bitstream *bstr)
bstr->bitsleft = 0LL + 8 * (bstr->end - bstr->pos - 1) + bstr->bpos;

return;
#endif
}

// Return pointer to first of bynum bytes from the bitstream if the
Expand All @@ -217,6 +262,9 @@ void make_byte_aligned(struct bitstream *bstr)
// This function does not advance the bitstream pointer.
unsigned char *next_bytes(struct bitstream *bstr, unsigned bynum)
{
#ifndef DISABLE_RUST
return (unsigned char *)ccxr_next_bytes(bstr->rust_bs, bynum);
#else
// Sanity check
if (bstr->end - bstr->pos < 0)
fatal(CCX_COMMON_EXIT_BUG_BUG, "In next_bytes: bitstream length can not be negative!");
Expand All @@ -238,6 +286,7 @@ unsigned char *next_bytes(struct bitstream *bstr, unsigned bynum)
bstr->_i_pos = bstr->pos + bynum;

return bstr->pos;
#endif
}

// Return pointer to first of bynum bytes from the bitstream if the
Expand All @@ -247,6 +296,9 @@ unsigned char *next_bytes(struct bitstream *bstr, unsigned bynum)
// This function does advance the bitstream pointer.
unsigned char *read_bytes(struct bitstream *bstr, unsigned bynum)
{
#ifndef DISABLE_RUST
return (unsigned char *)ccxr_read_bytes(bstr->rust_bs, bynum);
#else
unsigned char *res = next_bytes(bstr, bynum);

// Advance the bitstream when a read was possible
Expand All @@ -256,6 +308,7 @@ unsigned char *read_bytes(struct bitstream *bstr, unsigned bynum)
bstr->pos = bstr->_i_pos;
}
return res;
#endif
}

// Return an integer number with "bytes" precision from the current
Expand Down Expand Up @@ -301,6 +354,9 @@ uint64_t bitstream_get_num(struct bitstream *bstr, unsigned bytes, int advance)
// Read unsigned Exp-Golomb code from bitstream
uint64_t read_exp_golomb_unsigned(struct bitstream *bstr)
{
#ifndef DISABLE_RUST
return ccxr_read_exp_golomb_unsigned(bstr->rust_bs);
#else
uint64_t res = 0;
int zeros = 0;

Expand All @@ -310,11 +366,15 @@ uint64_t read_exp_golomb_unsigned(struct bitstream *bstr)
res = (0x01 << zeros) - 1 + read_bits(bstr, zeros);

return res;
#endif
}

// Read signed Exp-Golomb code from bitstream
int64_t read_exp_golomb(struct bitstream *bstr)
{
#ifndef DISABLE_RUST
return ccxr_read_exp_golomb(bstr->rust_bs);
#else
int64_t res = 0;

res = read_exp_golomb_unsigned(bstr);
Expand All @@ -325,6 +385,7 @@ int64_t read_exp_golomb(struct bitstream *bstr)
res = (res / 2 + (res % 2 ? 1 : 0)) * (res % 2 ? 1 : -1);

return res;
#endif
}

// Read unsigned integer with bnum bits length. Basically an
Expand All @@ -349,6 +410,9 @@ int64_t read_int(struct bitstream *bstr, unsigned bnum)
// Return the value with the bit order reversed.
uint8_t reverse8(uint8_t data)
{
#ifndef DISABLE_RUST
return ccxr_reverse8(data);
#else
uint8_t res = 0;

for (int k = 0; k < 8; k++)
Expand All @@ -358,4 +422,5 @@ uint8_t reverse8(uint8_t data)
}

return res;
#endif
}
4 changes: 3 additions & 1 deletion src/lib_ccx/cc_bitstream.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#ifndef _BITSTREAM_
#define _BITSTREAM_


// The structure holds the current position in the bitstream.
// pos points to the current byte position and bpos counts the
// bits left unread at the current byte pos. No bit read means
Expand All @@ -25,6 +24,9 @@ struct bitstream
// increased by the calling function, or not.
unsigned char *_i_pos;
int _i_bpos;
#ifndef DISABLE_RUST
void *rust_bs; // Pointer to Rust's Bitstream struct
#endif
};

#define read_u8(bstream) (uint8_t)bitstream_get_num(bstream,1,1)
Expand Down
Loading

0 comments on commit 83fb2d7

Please sign in to comment.