2 * This software is part of the SBCL system. See the README file for
5 * This software is derived from the CMU CL system, which was
6 * written at Carnegie Mellon University and released into the
7 * public domain. The software is in the public domain and is
8 * provided with absolutely no warranty. See the COPYING and CREDITS
9 * files for more information.
12 #include "gc-assert.h"
14 #include "genesis/number-types.h"
16 // Read a variable-length encoded 32-bit integer from SOURCE and
19 // If OFFSET is not NULL, start decoding at OFFSET bytes from SOURCE
20 // and increment the value pointed to by OFFSET by the length of the
21 // encoded representation.
23 // Keep in sync with {READ,WRITE}-VAR-INTEGER in
24 // src/code/debug-var-io.lisp
25 int read_var_integer(unsigned char *source
, int *offset
) {
26 unsigned char *ptr
= source
+ (offset
? *offset
: 0);
32 result
|= (octet
& 0x7f) << k
;
33 if (!(octet
& 0x80)) {
38 *offset
+= (ptr
- source
);
43 void varint_unpacker_init(struct varint_unpacker
* unpacker
, lispobj integer
)
45 if (fixnump(integer
)) {
46 unpacker
->word
= fixnum_value(integer
);
47 unpacker
->limit
= N_WORD_BYTES
;
48 unpacker
->data
= (char*)&unpacker
->word
;
50 gc_assert(lowtag_of(integer
) == OTHER_POINTER_LOWTAG
51 && widetag_of(native_pointer(integer
)) == BIGNUM_WIDETAG
);
52 struct bignum
* bignum
= (struct bignum
*)(integer
- OTHER_POINTER_LOWTAG
);
54 unpacker
->limit
= HeaderValue(bignum
->header
) * N_WORD_BYTES
;
55 unpacker
->data
= (char*)bignum
->digits
;
60 // Fetch the next varint from 'unpacker' into 'result'.
61 // Because there is no length prefix on the number of varints encoded,
62 // spurious trailing zeros might be observed. The data consumer can
63 // circumvent that by storing a count as the first value in the series.
64 // Return 1 for success, 0 for EOF.
65 int varint_unpack(struct varint_unpacker
* unpacker
, int* result
)
67 if (unpacker
->index
>= unpacker
->limit
) return 0;
71 #ifdef LISP_FEATURE_LITTLE_ENDIAN
72 int byte
= unpacker
->data
[unpacker
->index
];
74 // bignums are little-endian in word order,
75 // but machine-native within each word.
76 // We could pack bytes MSB-to-LSB in the bigdigits,
77 // but that seems less intuitive on the Lisp side.
78 int word_index
= unpacker
->index
/ N_WORD_BYTES
;
79 int byte_index
= unpacker
->index
% N_WORD_BYTES
;
80 int byte
= (((uword_t
*)unpacker
->data
)[word_index
] >> (byte_index
* 8)) & 0xFF;
83 accumulator
|= (byte
& 0x7F) << shift
;
84 if (!(byte
& 0x80)) break;
85 gc_assert(unpacker
->index
< unpacker
->limit
);
88 *result
= accumulator
;
92 void skip_data_stream(struct varint_unpacker
* unpacker
)
94 // Read elements until seeing a 0
96 while (varint_unpack(unpacker
, &val
) && val
!= 0) { }