10 // Optimize for 64 bits. We might want to replace this for 32-bit machines
12 typedef uint64_t bitreservoir_t;
13 typedef uint32_t bitreservoir_fill_t;
15 static inline bitreservoir_fill_t read_bitreservoir_fill(uint8_t* source)
17 return ntohl(*(bitreservoir_fill_t*)(source));
20 static const unsigned bitreservoir_size = 8 * sizeof(bitreservoir_t);
21 static const unsigned bitreservoir_fill_size = 8 * sizeof(bitreservoir_fill_t);
22 static const unsigned bytereservoir_size = 4096;
24 // A function to read bytes from some input source.
25 // A return value of -1 indicates error, a return value of 0 indicates EOF.
26 typedef ssize_t (input_func_t)(void*, uint8_t*, size_t);
29 // Short-term bit reservoir; holds up to 64 bits. When it's empty,
30 // it needs to get refilled from the medium-term bit reservoir.
32 unsigned bits_available;
34 // Medium-term bit reservoir; holds a few kilobytes of spare data.
35 // When this is empty, it needs to be refilled from the input
38 unsigned bytes_available;
41 input_func_t* input_func;
45 void init_data_source(struct data_source* source, input_func_t* input_func, void* userdata);
47 // Internal function. Do not use.
48 void possibly_refill_slow_path(struct data_source* source, unsigned num_bits);
50 // Make sure there's at least NUM_BITS available in the short-term bit reservoir.
51 // You usually want to call this before read_bits(). The reason it's separate
52 // is that if you want two reads and you know the size of both, it's faster to
53 // refill A+B, read A, read B than refill A, read A, refill B, read B.
54 static inline void possibly_refill(struct data_source* source, unsigned num_bits)
56 assert(num_bits <= bitreservoir_fill_size + 1);
58 if (source->bits_available >= num_bits) {
59 // Fast path (~90% of invocations?)
63 // Slower path (~99% of remaining invocations?)
64 assert(source->bits_available + bitreservoir_fill_size < bitreservoir_size);
65 if (source->bytes_available >= sizeof(bitreservoir_fill_t)) {
66 bitreservoir_fill_t fill = read_bitreservoir_fill(source->bytes);
67 source->bytes += sizeof(bitreservoir_fill_t);
68 source->bytes_available -= sizeof(bitreservoir_fill_t);
69 source->bits |= (bitreservoir_t)fill << (bitreservoir_size - bitreservoir_fill_size - source->bits_available);
70 source->bits_available += bitreservoir_fill_size;
74 // Slow path: Refill from data source.
75 // Should not be inlined, so split into a separate function.
76 possibly_refill_slow_path(source, num_bits);
79 static inline unsigned read_bits(struct data_source* source, unsigned num_bits)
81 assert(source->bits_available >= num_bits);
82 unsigned ret = (source->bits >> (bitreservoir_size - num_bits));
83 source->bits <<= num_bits;
84 source->bits_available -= num_bits;
88 #endif /* !defined(_INPUT_H) */