5 #include "duk_internal.h"
7 /* Decode 'bits' bits from the input stream (bits must be 1...24).
8 * When reading past bitstream end, zeroes are shifted in. The result
9 * is signed to match duk_bd_decode_flagged.
11 DUK_INTERNAL duk_int32_t
duk_bd_decode(duk_bitdecoder_ctx
*ctx
, duk_small_int_t bits
) {
12 duk_small_int_t shift
;
16 /* Note: cannot read more than 24 bits without possibly shifting top bits out.
17 * Fixable, but adds complexity.
19 DUK_ASSERT(bits
>= 1 && bits
<= 24);
21 while (ctx
->currbits
< bits
) {
23 DUK_DDD(DUK_DDDPRINT("decode_bits: shift more data (bits=%ld, currbits=%ld)",
24 (long) bits
, (long) ctx
->currbits
));
27 if (ctx
->offset
< ctx
->length
) {
28 /* If ctx->offset >= ctx->length, we "shift zeroes in"
29 * instead of croaking.
31 ctx
->currval
|= ctx
->data
[ctx
->offset
++];
36 DUK_DDD(DUK_DDDPRINT("decode_bits: bits=%ld, currbits=%ld, currval=0x%08lx",
37 (long) bits
, (long) ctx
->currbits
, (unsigned long) ctx
->currval
));
40 /* Extract 'top' bits of currval; note that the extracted bits do not need
41 * to be cleared, we just ignore them on next round.
43 shift
= ctx
->currbits
- bits
;
44 mask
= (1 << bits
) - 1;
45 tmp
= (ctx
->currval
>> shift
) & mask
;
46 ctx
->currbits
= shift
; /* remaining */
49 DUK_DDD(DUK_DDDPRINT("decode_bits: %ld bits -> 0x%08lx (%ld), currbits=%ld, currval=0x%08lx",
50 (long) bits
, (unsigned long) tmp
, (long) tmp
, (long) ctx
->currbits
, (unsigned long) ctx
->currval
));
56 DUK_INTERNAL duk_small_int_t
duk_bd_decode_flag(duk_bitdecoder_ctx
*ctx
) {
57 return (duk_small_int_t
) duk_bd_decode(ctx
, 1);
60 /* Decode a one-bit flag, and if set, decode a value of 'bits', otherwise return
61 * default value. Return value is signed so that negative marker value can be
62 * used by caller as a "not present" value.
64 DUK_INTERNAL duk_int32_t
duk_bd_decode_flagged(duk_bitdecoder_ctx
*ctx
, duk_small_int_t bits
, duk_int32_t def_value
) {
65 if (duk_bd_decode_flag(ctx
)) {
66 return (duk_int32_t
) duk_bd_decode(ctx
, bits
);