Merge pull request #4 from thequux/master

All sorts of makefile hacks, plus a new fastpath for the bitreader
This commit is contained in:
Meredith L. Patterson 2012-04-30 19:40:39 -07:00
commit 530eed8df3
8 changed files with 172 additions and 46 deletions

View file

@ -1,14 +1,18 @@
-include ../common.mk
OUTPUTS := bitreader.o \
hammer.o \
libhammer.a \
test_suite
TOPLEVEL := ../
include ../common.mk
all: libhammer.a test_suite
test_suite: test_suite.o libhammer.a
$(CC) -o $@ $^ $(LDFLAGS)
$(call hush, "Linking $@") $(CC) -o $@ $^ $(LDFLAGS)
libhammer.a: bitreader.o hammer.o

View file

@ -12,41 +12,54 @@ long long read_bits(input_stream_t* state, int count, char signed_p) {
long long out = 0;
int offset = 0;
long long msb = (!!signed_p) << (count - 1); // 0 if unsigned, else 1 << (nbits - 1)
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->bit_offset & 0x7) == 0 && (count & 0x7) == 0) {
// fast path
if (state->endianness & BYTE_BIG_ENDIAN) {
out = out << segment_len | segment;
} else { // BYTE_LITTLE_ENDIAN
out |= segment << offset;
offset += segment_len;
while (count > 0)
out = (out << 8) | state->input[state->index++];
} else {
while (count > 0) {
count -= 8;
out |= state->input[state->index++] << count;
}
}
} else {
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;
}
count -= segment_len;
}
return (out ^ msb) - msb; // perform sign extension
}
@ -55,7 +68,7 @@ long long read_bits(input_stream_t* state, int count, char signed_p) {
#define MK_INPUT_STREAM(buf,len,endianness_) \
{ \
.input = buf, \
.input = (uint8_t*)buf, \
.length = len, \
.index = 0, \
.bit_offset = (((endianness_) & BIT_BIG_ENDIAN) ? 8 : 0), \

View file

@ -122,7 +122,7 @@ const parser_t* token(const uint8_t *str, const size_t len) {
}
static parse_result_t* parse_ch(void* env, parse_state_t *state) {
uint8_t c = (uint8_t)env;
uint8_t c = (uint8_t)GPOINTER_TO_UINT(env);
uint8_t r = (uint8_t)read_bits(&state->input_stream, 8, false);
if (c == r) {
parsed_token_t *tok = g_new(parsed_token_t, 1);
@ -135,7 +135,7 @@ static parse_result_t* parse_ch(void* env, parse_state_t *state) {
const parser_t* ch(const uint8_t c) {
parser_t *ret = g_new(parser_t, 1);
ret->fn = parse_ch; ret->env = (void*)c;
ret->fn = parse_ch; ret->env = GUINT_TO_POINTER(c);
return (const parser_t*)ret;
}