#define _BITSOURCE_H 1
#include <assert.h>
+#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <sys/types.h>
#include <arpa/inet.h>
+#include "input.h"
+
// Optimize for 64 bits. We might want to replace this for 32-bit machines
// (benchmark later).
typedef uint64_t 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,
// 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);
// 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;