mirror of https://github.com/svaarala/duktape.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
70 lines
2.2 KiB
70 lines
2.2 KiB
/*
|
|
* Bitstream decoder.
|
|
*/
|
|
|
|
#include "duk_internal.h"
|
|
|
|
/* Decode 'bits' bits from the input stream (bits must be 1...24).
|
|
* When reading past bitstream end, zeroes are shifted in. The result
|
|
* is signed to match duk_bd_decode_flagged.
|
|
*/
|
|
DUK_INTERNAL duk_int32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits) {
|
|
duk_small_int_t shift;
|
|
duk_uint32_t mask;
|
|
duk_uint32_t tmp;
|
|
|
|
/* Note: cannot read more than 24 bits without possibly shifting top bits out.
|
|
* Fixable, but adds complexity.
|
|
*/
|
|
DUK_ASSERT(bits >= 1 && bits <= 24);
|
|
|
|
while (ctx->currbits < bits) {
|
|
#if 0
|
|
DUK_DDD(DUK_DDDPRINT("decode_bits: shift more data (bits=%ld, currbits=%ld)",
|
|
(long) bits, (long) ctx->currbits));
|
|
#endif
|
|
ctx->currval <<= 8;
|
|
if (ctx->offset < ctx->length) {
|
|
/* If ctx->offset >= ctx->length, we "shift zeroes in"
|
|
* instead of croaking.
|
|
*/
|
|
ctx->currval |= ctx->data[ctx->offset++];
|
|
}
|
|
ctx->currbits += 8;
|
|
}
|
|
#if 0
|
|
DUK_DDD(DUK_DDDPRINT("decode_bits: bits=%ld, currbits=%ld, currval=0x%08lx",
|
|
(long) bits, (long) ctx->currbits, (unsigned long) ctx->currval));
|
|
#endif
|
|
|
|
/* Extract 'top' bits of currval; note that the extracted bits do not need
|
|
* to be cleared, we just ignore them on next round.
|
|
*/
|
|
shift = ctx->currbits - bits;
|
|
mask = (1 << bits) - 1;
|
|
tmp = (ctx->currval >> shift) & mask;
|
|
ctx->currbits = shift; /* remaining */
|
|
|
|
#if 0
|
|
DUK_DDD(DUK_DDDPRINT("decode_bits: %ld bits -> 0x%08lx (%ld), currbits=%ld, currval=0x%08lx",
|
|
(long) bits, (unsigned long) tmp, (long) tmp, (long) ctx->currbits, (unsigned long) ctx->currval));
|
|
#endif
|
|
|
|
return tmp;
|
|
}
|
|
|
|
DUK_INTERNAL duk_small_int_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx) {
|
|
return (duk_small_int_t) duk_bd_decode(ctx, 1);
|
|
}
|
|
|
|
/* Decode a one-bit flag, and if set, decode a value of 'bits', otherwise return
|
|
* default value. Return value is signed so that negative marker value can be
|
|
* used by caller as a "not present" value.
|
|
*/
|
|
DUK_INTERNAL duk_int32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value) {
|
|
if (duk_bd_decode_flag(ctx)) {
|
|
return (duk_int32_t) duk_bd_decode(ctx, bits);
|
|
} else {
|
|
return def_value;
|
|
}
|
|
}
|
|
|