Added fast path for bitreader
This commit is contained in:
parent
bc51198354
commit
ddcfa5b1b2
1 changed files with 46 additions and 33 deletions
|
|
@ -12,41 +12,54 @@ long long read_bits(input_stream_t* state, int count, char signed_p) {
|
||||||
long long out = 0;
|
long long out = 0;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
long long msb = (!!signed_p) << (count - 1); // 0 if unsigned, else 1 << (nbits - 1)
|
long long msb = (!!signed_p) << (count - 1); // 0 if unsigned, else 1 << (nbits - 1)
|
||||||
while (count) {
|
if ((state->bit_offset & 0x7) == 0 && (count & 0x7) == 0) {
|
||||||
int segment, segment_len;
|
// fast path
|
||||||
// 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) {
|
if (state->endianness & BYTE_BIG_ENDIAN) {
|
||||||
out = out << segment_len | segment;
|
while (count > 0)
|
||||||
} else { // BYTE_LITTLE_ENDIAN
|
out = (out << 8) | state->input[state->index++];
|
||||||
out |= segment << offset;
|
} else {
|
||||||
offset += segment_len;
|
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
|
return (out ^ msb) - msb; // perform sign extension
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue