8 #define MARKER_CHAR 0xff
9 #define STUFF_MARKER 0x00
11 void init_bit_source(struct bit_source* source, input_func_t* input_func,
12 unsigned padding_bytes, void* userdata)
14 memset(source, 0, sizeof(*source));
15 source->bytes = (uint8_t*)malloc(BYTERESERVOIR_SIZE);
16 source->byte_read_ptr = source->bytes;
17 source->input_func = input_func;
18 source->padding_bytes_available = padding_bytes;
19 source->userdata = userdata;
22 void possibly_refill_slow_path(struct bit_source* source, unsigned num_bits)
24 // First, move out the data we already read.
25 assert(source->bytes_available <= BYTERESERVOIR_SIZE);
26 assert(source->byte_read_ptr >= source->bytes);
27 memmove(source->bytes, source->byte_read_ptr, source->bytes_available);
28 source->byte_read_ptr = source->bytes;
30 // Then, make sure there's stuff in the byte reservoir if we can.
31 // Read data from the source until we have enough to satisfy the request.
32 while (source->bits_available + 8 * source->bytes_available < num_bits) {
33 const size_t bytes_to_read = BYTERESERVOIR_SIZE - source->bytes_available;
34 const ssize_t bytes_read =
35 (*source->input_func)(source->userdata,
36 source->bytes + source->bytes_available,
38 assert(bytes_read <= (ssize_t)bytes_to_read);
39 assert(bytes_read >= (ssize_t)-1);
41 // TODO: We need better error handling here. setjmp()/longjmp()
42 // should hopefully do the trick, but we need to take care for
44 if (bytes_read == (ssize_t)-1) {
45 fprintf(stderr, "Input function returned error\n");
48 if (bytes_read == 0) {
49 source->source_eof = true;
50 if (source->padding_bytes_available > 0) {
51 unsigned padding_to_add = source->padding_bytes_available;
52 if (padding_to_add > bytes_to_read) {
53 padding_to_add = bytes_to_read;
55 memset(source->bytes + source->bytes_available, 0, padding_to_add);
56 source->padding_bytes_available -= padding_to_add;
57 source->bytes_available += padding_to_add;
59 fprintf(stderr, "Premature EOF\n");
63 source->bytes_available += bytes_read;
67 // Fill the bit reservoir one by one byte until we have enough.
68 while (source->bits_available < num_bits) {
69 assert(source->bytes_available > 0);
70 assert(source->bits_available + 8 <= BITRESERVOIR_SIZE);
71 uint8_t byte = *(source->byte_read_ptr);
72 ++source->byte_read_ptr;
73 --source->bytes_available;
74 source->bits |= ((bitreservoir_t)byte << (BITRESERVOIR_SIZE - source->bits_available - 8));
75 source->bits_available += 8;