diff --git a/lib/allocator.h b/lib/allocator.h index 3cea5906f1df279f0cfa6592515ac5d4c6d300f3..130804ad589d36f0f864713b8f9802f0f3eeaf16 100644 --- a/lib/allocator.h +++ b/lib/allocator.h @@ -1,5 +1,5 @@ -#ifndef LIB_ALLOCATOR__H__ -#define LIB_ALLOCATOR__H__ +#ifndef HAMMER_ALLOCATOR__H__ +#define HAMMER_ALLOCATOR__H__ #include <sys/types.h> typedef struct arena* arena_t; // hidden implementation diff --git a/src/bitreader.c b/src/bitreader.c new file mode 100644 index 0000000000000000000000000000000000000000..431c351c7b1a7e97c224436367d150bb130e6c0d --- /dev/null +++ b/src/bitreader.c @@ -0,0 +1,49 @@ +#include <stdint.h> +#include "internal.h" +#include "hammer.h" + +#define LSB(range) (0:range) +#define MSB(range) (1:range) +#define LDB(range,i) (((i)>>LSB(range))&((1<<(MSB(range)-LSB(range)+1))-1)) + +long long read_bits(parse_state_t* state, int count) { + long long out = 0; + int offset = 0; + while (count) { + int segment, segment_len; + // Read a segment... + if (state->endianness & BIT_BIG_ENDIAN) { + if (count >= state->bit_offset) { + segment_len = state->bit_offset; + state->bit_offset = 8; + segment = state->input[state->index] & ((1 << segment_len) - 1); + state->index++; + } else { + segment_len = count; + state->bit_offset -= count; + segment = (state->input[state->index] >> state->bit_offset) & ((1 << segment_len) - 1); + } + } else { // BIT_LITTLE_ENDIAN + if (count + state->bit_offset >= 8) { + segment_len = 8 - state->bit_offset; + segment = (state->input[state->index] >> state->bit_offset); + state->index++; + state->bit_offset = 0; + } else { + segment_len = count; + segment = (state->input[state->index] >> state->bit_offset) & ((1 << segment_len) - 1); + state->bit_offset += segment_len; + } + } + + // have a valid segment; time to assemble the byte + if (state->endianness & BYTE_BIG_ENDIAN) { + out = out << segment_len | segment; + } else { // BYTE_LITTLE_ENDIAN + out |= segment << offset; + offset += segment_len; + } + count -= segment_len; + } + return out; +} diff --git a/src/hammer.h b/src/hammer.h index bbacb13d416b7b3ed85d09ffec5a6a05f1967833..d6c73eeba73a435ce5439e5c0596809da8be6204 100644 --- a/src/hammer.h +++ b/src/hammer.h @@ -15,6 +15,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#ifndef HAMMER_HAMMER__H +#define HAMMER_HAMMER__H #include <glib.h> #include <stdint.h> @@ -33,11 +35,16 @@ * at which it's been applied are memoized. * */ +#define BYTE_BIG_ENDIAN 0x1 +#define BIT_BIG_ENDIAN 0x2 + typedef struct parse_state { const uint8_t *input; + GHashTable *cache; size_t index; size_t length; - GHashTable *cache; + char bit_offset; + char endianness; } parse_state_t; typedef struct parse_result { @@ -81,5 +88,4 @@ parser_t* epsilon_p(); parser_t* and(parser_t* p); parser_t* not(parser_t* p); - - +#endif // #ifndef HAMMER_HAMMER__H diff --git a/src/internal.h b/src/internal.h new file mode 100644 index 0000000000000000000000000000000000000000..0657de0a08f269db8f856122f1153604e3dca92b --- /dev/null +++ b/src/internal.h @@ -0,0 +1,7 @@ +#ifndef HAMMER_INTERNAL__H +#define HAMMER_INTERNAL__H +#include "hammer.h" + +long long read_bits(parse_state_t* state, int count); + +#endif // #ifndef HAMMER_INTERNAL__H