X-Git-Url: https://git.sesse.net/?p=fjl;a=blobdiff_plain;f=bitsource.h;h=60744b32e12bdc7809f8b0d7cf47d3271a8b8295;hp=e5bdd282ae104de0c9017f651efa6a7d60dd3751;hb=0932a33d5fa817a07778f85c05681ed77131bac6;hpb=0b02847989970a190c2cfaec4d1abaa1f616284a diff --git a/bitsource.h b/bitsource.h index e5bdd28..60744b3 100644 --- a/bitsource.h +++ b/bitsource.h @@ -2,11 +2,14 @@ #define _BITSOURCE_H 1 #include +#include #include #include #include #include +#include "input.h" + // Optimize for 64 bits. We might want to replace this for 32-bit machines // (benchmark later). typedef uint64_t bitreservoir_t; @@ -21,11 +24,6 @@ static const unsigned BITRESERVOIR_SIZE = 8 * sizeof(bitreservoir_t); static const unsigned BITRESERVOIR_FILL_SIZE = 8 * sizeof(bitreservoir_fill_t); static const unsigned BYTERESERVOIR_SIZE = 4096; -// A function to read bytes from some input source. The bytes should be -// already unstuffed (and thus without markers). -// A return value of -1 indicates error, a return value of 0 indicates EOF. -typedef ssize_t (input_func_t)(void*, uint8_t*, size_t); - // A data source for efficient reading of bit-level data. struct bit_source { // Short-term bit reservoir; holds up to 64 bits. When it's empty, @@ -37,14 +35,22 @@ struct bit_source { // When this is empty, it needs to be refilled from the input // stream. uint8_t* bytes; + uint8_t* byte_read_ptr; unsigned bytes_available; + // Some clients will purposedly read a bit ahead of the stream, causing + // problems at EOF. Thus, the client is allowed to request that we pad + // the end stream with a few bytes after the source reports EOF. + int padding_bytes_available; + // Data source. input_func_t* input_func; void* userdata; + bool source_eof; }; -void init_bit_source(struct bit_source* source, input_func_t* input_func, void* userdata); +void init_bit_source(struct bit_source* source, input_func_t* input_func, + unsigned padding_bytes, void* userdata); // Internal function. Do not use. void possibly_refill_slow_path(struct bit_source* source, unsigned num_bits); @@ -65,8 +71,8 @@ static inline void possibly_refill(struct bit_source* source, unsigned num_bits) // Slower path (~99% of remaining invocations?) assert(source->bits_available + BITRESERVOIR_FILL_SIZE < BITRESERVOIR_SIZE); if (source->bytes_available >= sizeof(bitreservoir_fill_t)) { - bitreservoir_fill_t fill = read_bitreservoir_fill(source->bytes); - source->bytes += sizeof(bitreservoir_fill_t); + bitreservoir_fill_t fill = read_bitreservoir_fill(source->byte_read_ptr); + source->byte_read_ptr += sizeof(bitreservoir_fill_t); source->bytes_available -= sizeof(bitreservoir_fill_t); source->bits |= (bitreservoir_t)fill << (BITRESERVOIR_SIZE - BITRESERVOIR_FILL_SIZE - source->bits_available); source->bits_available += BITRESERVOIR_FILL_SIZE;