1 /* 2 * Utilities 3 */ 4 5 #ifndef DUK_UTIL_H_INCLUDED 6 #define DUK_UTIL_H_INCLUDED 7 8 #define DUK_UTIL_MIN_HASH_PRIME 17 /* must match genhashsizes.py */ 9 10 #define DUK_UTIL_GET_HASH_PROBE_STEP(hash) (duk_util_probe_steps[(hash) & 0x1f]) 11 12 /* 13 * Endian conversion 14 */ 15 16 #if defined(DUK_USE_INTEGER_LE) 17 #define DUK_HTON32(x) DUK_BSWAP32((x)) 18 #define DUK_NTOH32(x) DUK_BSWAP32((x)) 19 #define DUK_HTON16(x) DUK_BSWAP16((x)) 20 #define DUK_NTOH16(x) DUK_BSWAP16((x)) 21 #elif defined(DUK_USE_INTEGER_BE) 22 #define DUK_HTON32(x) (x) 23 #define DUK_NTOH32(x) (x) 24 #define DUK_HTON16(x) (x) 25 #define DUK_NTOH16(x) (x) 26 #else 27 #error internal error, endianness defines broken 28 #endif 29 30 /* 31 * Bitstream decoder 32 */ 33 34 struct duk_bitdecoder_ctx { 35 const duk_uint8_t *data; 36 duk_size_t offset; 37 duk_size_t length; 38 duk_uint32_t currval; 39 duk_small_int_t currbits; 40 }; 41 42 /* 43 * Bitstream encoder 44 */ 45 46 struct duk_bitencoder_ctx { 47 duk_uint8_t *data; 48 duk_size_t offset; 49 duk_size_t length; 50 duk_uint32_t currval; 51 duk_small_int_t currbits; 52 duk_small_int_t truncated; 53 }; 54 55 /* 56 * Raw write/read macros for big endian, unaligned basic values. 57 * Caller ensures there's enough space. The macros update the pointer 58 * argument automatically on resizes. The idiom seems a bit odd, but 59 * leads to compact code. 60 */ 61 62 #define DUK_RAW_WRITE_U8(ptr,val) do { \ 63 *(ptr)++ = (duk_uint8_t) (val); \ 64 } while (0) 65 #define DUK_RAW_WRITE_U16_BE(ptr,val) duk_raw_write_u16_be(&(ptr), (duk_uint16_t) (val)) 66 #define DUK_RAW_WRITE_U32_BE(ptr,val) duk_raw_write_u32_be(&(ptr), (duk_uint32_t) (val)) 67 #define DUK_RAW_WRITE_DOUBLE_BE(ptr,val) duk_raw_write_double_be(&(ptr), (duk_double_t) (val)) 68 #define DUK_RAW_WRITE_XUTF8(ptr,val) do { \ 69 /* 'ptr' is evaluated both as LHS and RHS. */ \ 70 duk_uint8_t *duk__ptr; \ 71 duk_small_int_t duk__len; \ 72 duk__ptr = (duk_uint8_t *) (ptr); \ 73 duk__len = duk_unicode_encode_xutf8((duk_ucodepoint_t) (val), duk__ptr); \ 74 duk__ptr += duk__len; \ 75 (ptr) = duk__ptr; \ 76 } while (0) 77 #define DUK_RAW_WRITE_CESU8(ptr,val) do { \ 78 /* 'ptr' is evaluated both as LHS and RHS. */ \ 79 duk_uint8_t *duk__ptr; \ 80 duk_small_int_t duk__len; \ 81 duk__ptr = (duk_uint8_t *) (ptr); \ 82 duk__len = duk_unicode_encode_cesu8((duk_ucodepoint_t) (val), duk__ptr); \ 83 duk__ptr += duk__len; \ 84 (ptr) = duk__ptr; \ 85 } while (0) 86 87 #define DUK_RAW_READ_U8(ptr) ((duk_uint8_t) (*(ptr)++)) 88 #define DUK_RAW_READ_U16_BE(ptr) duk_raw_read_u16_be(&(ptr)); 89 #define DUK_RAW_READ_U32_BE(ptr) duk_raw_read_u32_be(&(ptr)); 90 #define DUK_RAW_READ_DOUBLE_BE(ptr) duk_raw_read_double_be(&(ptr)); 91 92 /* 93 * Buffer writer (dynamic buffer only) 94 * 95 * Helper for writing to a dynamic buffer with a concept of a "spare" area 96 * to reduce resizes. You can ensure there is enough space beforehand and 97 * then write for a while without further checks, relying on a stable data 98 * pointer. Spare handling is automatic so call sites only indicate how 99 * much data they need right now. 100 * 101 * There are several ways to write using bufwriter. The best approach 102 * depends mainly on how much performance matters over code footprint. 103 * The key issues are (1) ensuring there is space and (2) keeping the 104 * pointers consistent. Fast code should ensure space for multiple writes 105 * with one ensure call. Fastest inner loop code can temporarily borrow 106 * the 'p' pointer but must write it back eventually. 107 * 108 * Be careful to ensure all macro arguments (other than static pointers like 109 * 'thr' and 'bw_ctx') are evaluated exactly once, using temporaries if 110 * necessary (if that's not possible, there should be a note near the macro). 111 * Buffer write arguments often contain arithmetic etc so this is 112 * particularly important here. 113 */ 114 115 /* XXX: Migrate bufwriter and other read/write helpers to its own header? */ 116 117 struct duk_bufwriter_ctx { 118 duk_uint8_t *p; 119 duk_uint8_t *p_base; 120 duk_uint8_t *p_limit; 121 duk_hbuffer_dynamic *buf; 122 }; 123 124 #define DUK_BW_SPARE_ADD 64 125 #define DUK_BW_SPARE_SHIFT 4 /* 2^4 -> 1/16 = 6.25% spare */ 126 127 /* Initialization and finalization (compaction), converting to other types. */ 128 129 #define DUK_BW_INIT_PUSHBUF(thr,bw_ctx,sz) do { \ 130 duk_bw_init_pushbuf((thr), (bw_ctx), (sz)); \ 131 } while (0) 132 #define DUK_BW_INIT_WITHBUF(thr,bw_ctx,buf) do { \ 133 duk_bw_init((thr), (bw_ctx), (buf)); \ 134 } while (0) 135 #define DUK_BW_COMPACT(thr,bw_ctx) do { \ 136 /* Make underlying buffer compact to match DUK_BW_GET_SIZE(). */ \ 137 duk_bw_compact((thr), (bw_ctx)); \ 138 } while (0) 139 #define DUK_BW_PUSH_AS_STRING(thr,bw_ctx) do { \ 140 duk_push_lstring((duk_context *) (thr), \ 141 (const char *) (bw_ctx)->p_base, \ 142 (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \ 143 } while (0) 144 /* Pointers may be NULL for a while when 'buf' size is zero and before any 145 * ENSURE calls have been made. Once an ENSURE has been made, the pointers 146 * are required to be non-NULL so that it's always valid to use memcpy() and 147 * memmove(), even for zero size. 148 */ 149 #define DUK_BW_ASSERT_VALID_EXPR(thr,bw_ctx) \ 150 DUK_ASSERT_EXPR((bw_ctx) != NULL && \ 151 (bw_ctx)->buf != NULL && \ 152 ((DUK_HBUFFER_DYNAMIC_GET_SIZE((bw_ctx)->buf) == 0) || \ 153 ((bw_ctx)->p != NULL && \ 154 (bw_ctx)->p_base != NULL && \ 155 (bw_ctx)->p_limit != NULL && \ 156 (bw_ctx)->p_limit >= (bw_ctx)->p_base && \ 157 (bw_ctx)->p >= (bw_ctx)->p_base && \ 158 (bw_ctx)->p <= (bw_ctx)->p_limit))) 159 #define DUK_BW_ASSERT_VALID(thr,bw_ctx) do { \ 160 DUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)); \ 161 } while (0) 162 163 /* Working with the pointer and current size. */ 164 165 #define DUK_BW_GET_PTR(thr,bw_ctx) \ 166 ((bw_ctx)->p) 167 #define DUK_BW_SET_PTR(thr,bw_ctx,ptr) do { \ 168 (bw_ctx)->p = (ptr); \ 169 } while (0) 170 #define DUK_BW_ADD_PTR(thr,bw_ctx,delta) do { \ 171 (bw_ctx)->p += (delta); \ 172 } while (0) 173 #define DUK_BW_GET_BASEPTR(thr,bw_ctx) \ 174 ((bw_ctx)->p_base) 175 #define DUK_BW_GET_LIMITPTR(thr,bw_ctx) \ 176 ((bw_ctx)->p_limit) 177 #define DUK_BW_GET_SIZE(thr,bw_ctx) \ 178 ((duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)) 179 #define DUK_BW_SET_SIZE(thr,bw_ctx,sz) do { \ 180 DUK_ASSERT((duk_size_t) (sz) <= (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \ 181 (bw_ctx)->p = (bw_ctx)->p_base + (sz); \ 182 } while (0) 183 #define DUK_BW_RESET_SIZE(thr,bw_ctx) do { \ 184 /* Reset to zero size, keep current limit. */ \ 185 (bw_ctx)->p = (bw_ctx)->p_base; \ 186 } while (0) 187 #define DUK_BW_GET_BUFFER(thr,bw_ctx) \ 188 ((bw_ctx)->buf) 189 190 /* Ensuring (reserving) space. */ 191 192 #define DUK_BW_ENSURE(thr,bw_ctx,sz) do { \ 193 duk_size_t duk__sz, duk__space; \ 194 DUK_BW_ASSERT_VALID((thr), (bw_ctx)); \ 195 duk__sz = (sz); \ 196 duk__space = (duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p); \ 197 if (duk__space < duk__sz) { \ 198 (void) duk_bw_resize((thr), (bw_ctx), duk__sz); \ 199 } \ 200 } while (0) 201 /* NOTE: Multiple evaluation of 'ptr' in this macro. */ 202 /* XXX: Rework to use an always-inline function? */ 203 #define DUK_BW_ENSURE_RAW(thr,bw_ctx,sz,ptr) \ 204 (((duk_size_t) ((bw_ctx)->p_limit - (ptr)) >= (sz)) ? \ 205 (ptr) : \ 206 ((bw_ctx)->p = (ptr), duk_bw_resize((thr),(bw_ctx),(sz)))) 207 #define DUK_BW_ENSURE_GETPTR(thr,bw_ctx,sz) \ 208 DUK_BW_ENSURE_RAW((thr), (bw_ctx), (sz), (bw_ctx)->p) 209 #define DUK_BW_ASSERT_SPACE_EXPR(thr,bw_ctx,sz) \ 210 (DUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)), \ 211 DUK_ASSERT_EXPR((duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p) >= (duk_size_t) (sz))) 212 #define DUK_BW_ASSERT_SPACE(thr,bw_ctx,sz) do { \ 213 DUK_BW_ASSERT_SPACE_EXPR((thr), (bw_ctx), (sz)); \ 214 } while (0) 215 216 /* Miscellaneous. */ 217 218 #define DUK_BW_SETPTR_AND_COMPACT(thr,bw_ctx,ptr) do { \ 219 (bw_ctx)->p = (ptr); \ 220 duk_bw_compact((thr), (bw_ctx)); \ 221 } while (0) 222 223 /* Fast write calls which assume you control the spare beforehand. 224 * Multibyte write variants exist and use a temporary write pointer 225 * because byte writes alias with anything: with a stored pointer 226 * explicit pointer load/stores get generated (e.g. gcc -Os). 227 */ 228 229 #define DUK_BW_WRITE_RAW_U8(thr,bw_ctx,val) do { \ 230 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 1); \ 231 *(bw_ctx)->p++ = (duk_uint8_t) (val); \ 232 } while (0) 233 #define DUK_BW_WRITE_RAW_U8_2(thr,bw_ctx,val1,val2) do { \ 234 duk_uint8_t *duk__p; \ 235 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 2); \ 236 duk__p = (bw_ctx)->p; \ 237 *duk__p++ = (duk_uint8_t) (val1); \ 238 *duk__p++ = (duk_uint8_t) (val2); \ 239 (bw_ctx)->p = duk__p; \ 240 } while (0) 241 #define DUK_BW_WRITE_RAW_U8_3(thr,bw_ctx,val1,val2,val3) do { \ 242 duk_uint8_t *duk__p; \ 243 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 3); \ 244 duk__p = (bw_ctx)->p; \ 245 *duk__p++ = (duk_uint8_t) (val1); \ 246 *duk__p++ = (duk_uint8_t) (val2); \ 247 *duk__p++ = (duk_uint8_t) (val3); \ 248 (bw_ctx)->p = duk__p; \ 249 } while (0) 250 #define DUK_BW_WRITE_RAW_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \ 251 duk_uint8_t *duk__p; \ 252 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 4); \ 253 duk__p = (bw_ctx)->p; \ 254 *duk__p++ = (duk_uint8_t) (val1); \ 255 *duk__p++ = (duk_uint8_t) (val2); \ 256 *duk__p++ = (duk_uint8_t) (val3); \ 257 *duk__p++ = (duk_uint8_t) (val4); \ 258 (bw_ctx)->p = duk__p; \ 259 } while (0) 260 #define DUK_BW_WRITE_RAW_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \ 261 duk_uint8_t *duk__p; \ 262 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 5); \ 263 duk__p = (bw_ctx)->p; \ 264 *duk__p++ = (duk_uint8_t) (val1); \ 265 *duk__p++ = (duk_uint8_t) (val2); \ 266 *duk__p++ = (duk_uint8_t) (val3); \ 267 *duk__p++ = (duk_uint8_t) (val4); \ 268 *duk__p++ = (duk_uint8_t) (val5); \ 269 (bw_ctx)->p = duk__p; \ 270 } while (0) 271 #define DUK_BW_WRITE_RAW_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \ 272 duk_uint8_t *duk__p; \ 273 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 6); \ 274 duk__p = (bw_ctx)->p; \ 275 *duk__p++ = (duk_uint8_t) (val1); \ 276 *duk__p++ = (duk_uint8_t) (val2); \ 277 *duk__p++ = (duk_uint8_t) (val3); \ 278 *duk__p++ = (duk_uint8_t) (val4); \ 279 *duk__p++ = (duk_uint8_t) (val5); \ 280 *duk__p++ = (duk_uint8_t) (val6); \ 281 (bw_ctx)->p = duk__p; \ 282 } while (0) 283 #define DUK_BW_WRITE_RAW_XUTF8(thr,bw_ctx,cp) do { \ 284 duk_ucodepoint_t duk__cp; \ 285 duk_small_int_t duk__enc_len; \ 286 duk__cp = (cp); \ 287 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_xutf8_length(duk__cp)); \ 288 duk__enc_len = duk_unicode_encode_xutf8(duk__cp, (bw_ctx)->p); \ 289 (bw_ctx)->p += duk__enc_len; \ 290 } while (0) 291 #define DUK_BW_WRITE_RAW_CESU8(thr,bw_ctx,cp) do { \ 292 duk_ucodepoint_t duk__cp; \ 293 duk_small_int_t duk__enc_len; \ 294 duk__cp = (duk_ucodepoint_t) (cp); \ 295 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_cesu8_length(duk__cp)); \ 296 duk__enc_len = duk_unicode_encode_cesu8(duk__cp, (bw_ctx)->p); \ 297 (bw_ctx)->p += duk__enc_len; \ 298 } while (0) 299 /* XXX: add temporary duk__p pointer here too; sharing */ 300 #define DUK_BW_WRITE_RAW_BYTES(thr,bw_ctx,valptr,valsz) do { \ 301 const void *duk__valptr; \ 302 duk_size_t duk__valsz; \ 303 duk__valptr = (const void *) (valptr); \ 304 duk__valsz = (duk_size_t) (valsz); \ 305 DUK_MEMCPY((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \ 306 (bw_ctx)->p += duk__valsz; \ 307 } while (0) 308 #define DUK_BW_WRITE_RAW_CSTRING(thr,bw_ctx,val) do { \ 309 const duk_uint8_t *duk__val; \ 310 duk_size_t duk__val_len; \ 311 duk__val = (const duk_uint8_t *) (val); \ 312 duk__val_len = DUK_STRLEN((const char *) duk__val); \ 313 DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \ 314 (bw_ctx)->p += duk__val_len; \ 315 } while (0) 316 #define DUK_BW_WRITE_RAW_HSTRING(thr,bw_ctx,val) do { \ 317 duk_size_t duk__val_len; \ 318 duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \ 319 DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \ 320 (bw_ctx)->p += duk__val_len; \ 321 } while (0) 322 #define DUK_BW_WRITE_RAW_HBUFFER(thr,bw_ctx,val) do { \ 323 duk_size_t duk__val_len; \ 324 duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \ 325 DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \ 326 (bw_ctx)->p += duk__val_len; \ 327 } while (0) 328 #define DUK_BW_WRITE_RAW_HBUFFER_FIXED(thr,bw_ctx,val) do { \ 329 duk_size_t duk__val_len; \ 330 duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \ 331 DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \ 332 (bw_ctx)->p += duk__val_len; \ 333 } while (0) 334 #define DUK_BW_WRITE_RAW_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \ 335 duk_size_t duk__val_len; \ 336 duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \ 337 DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \ 338 (bw_ctx)->p += duk__val_len; \ 339 } while (0) 340 341 /* Append bytes from a slice already in the buffer. */ 342 #define DUK_BW_WRITE_RAW_SLICE(thr,bw,dst_off,dst_len) \ 343 duk_bw_write_raw_slice((thr), (bw), (dst_off), (dst_len)) 344 345 /* Insert bytes in the middle of the buffer from an external buffer. */ 346 #define DUK_BW_INSERT_RAW_BYTES(thr,bw,dst_off,buf,len) \ 347 duk_bw_insert_raw_bytes((thr), (bw), (dst_off), (buf), (len)) 348 349 /* Insert bytes in the middle of the buffer from a slice already 350 * in the buffer. Source offset is interpreted "before" the operation. 351 */ 352 #define DUK_BW_INSERT_RAW_SLICE(thr,bw,dst_off,src_off,len) \ 353 duk_bw_insert_raw_slice((thr), (bw), (dst_off), (src_off), (len)) 354 355 /* Insert a reserved area somewhere in the buffer; caller fills it. 356 * Evaluates to a (duk_uint_t *) pointing to the start of the reserved 357 * area for convenience. 358 */ 359 #define DUK_BW_INSERT_RAW_AREA(thr,bw,off,len) \ 360 duk_bw_insert_raw_area((thr), (bw), (off), (len)) 361 362 /* Remove a slice from inside buffer. */ 363 #define DUK_BW_REMOVE_RAW_SLICE(thr,bw,off,len) \ 364 duk_bw_remove_raw_slice((thr), (bw), (off), (len)) 365 366 /* Safe write calls which will ensure space first. */ 367 368 #define DUK_BW_WRITE_ENSURE_U8(thr,bw_ctx,val) do { \ 369 DUK_BW_ENSURE((thr), (bw_ctx), 1); \ 370 DUK_BW_WRITE_RAW_U8((thr), (bw_ctx), (val)); \ 371 } while (0) 372 #define DUK_BW_WRITE_ENSURE_U8_2(thr,bw_ctx,val1,val2) do { \ 373 DUK_BW_ENSURE((thr), (bw_ctx), 2); \ 374 DUK_BW_WRITE_RAW_U8_2((thr), (bw_ctx), (val1), (val2)); \ 375 } while (0) 376 #define DUK_BW_WRITE_ENSURE_U8_3(thr,bw_ctx,val1,val2,val3) do { \ 377 DUK_BW_ENSURE((thr), (bw_ctx), 3); \ 378 DUK_BW_WRITE_RAW_U8_3((thr), (bw_ctx), (val1), (val2), (val3)); \ 379 } while (0) 380 #define DUK_BW_WRITE_ENSURE_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \ 381 DUK_BW_ENSURE((thr), (bw_ctx), 4); \ 382 DUK_BW_WRITE_RAW_U8_4((thr), (bw_ctx), (val1), (val2), (val3), (val4)); \ 383 } while (0) 384 #define DUK_BW_WRITE_ENSURE_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \ 385 DUK_BW_ENSURE((thr), (bw_ctx), 5); \ 386 DUK_BW_WRITE_RAW_U8_5((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5)); \ 387 } while (0) 388 #define DUK_BW_WRITE_ENSURE_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \ 389 DUK_BW_ENSURE((thr), (bw_ctx), 6); \ 390 DUK_BW_WRITE_RAW_U8_6((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5), (val6)); \ 391 } while (0) 392 #define DUK_BW_WRITE_ENSURE_XUTF8(thr,bw_ctx,cp) do { \ 393 DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_XUTF8_LENGTH); \ 394 DUK_BW_WRITE_RAW_XUTF8((thr), (bw_ctx), (cp)); \ 395 } while (0) 396 #define DUK_BW_WRITE_ENSURE_CESU8(thr,bw_ctx,cp) do { \ 397 DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_CESU8_LENGTH); \ 398 DUK_BW_WRITE_RAW_CESU8((thr), (bw_ctx), (cp)); \ 399 } while (0) 400 /* XXX: add temporary duk__p pointer here too; sharing */ 401 #define DUK_BW_WRITE_ENSURE_BYTES(thr,bw_ctx,valptr,valsz) do { \ 402 const void *duk__valptr; \ 403 duk_size_t duk__valsz; \ 404 duk__valptr = (const void *) (valptr); \ 405 duk__valsz = (duk_size_t) (valsz); \ 406 DUK_BW_ENSURE((thr), (bw_ctx), duk__valsz); \ 407 DUK_MEMCPY((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \ 408 (bw_ctx)->p += duk__valsz; \ 409 } while (0) 410 #define DUK_BW_WRITE_ENSURE_CSTRING(thr,bw_ctx,val) do { \ 411 const duk_uint8_t *duk__val; \ 412 duk_size_t duk__val_len; \ 413 duk__val = (const duk_uint8_t *) (val); \ 414 duk__val_len = DUK_STRLEN((const char *) duk__val); \ 415 DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \ 416 DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \ 417 (bw_ctx)->p += duk__val_len; \ 418 } while (0) 419 #define DUK_BW_WRITE_ENSURE_HSTRING(thr,bw_ctx,val) do { \ 420 duk_size_t duk__val_len; \ 421 duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \ 422 DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \ 423 DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \ 424 (bw_ctx)->p += duk__val_len; \ 425 } while (0) 426 #define DUK_BW_WRITE_ENSURE_HBUFFER(thr,bw_ctx,val) do { \ 427 duk_size_t duk__val_len; \ 428 duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \ 429 DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \ 430 DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \ 431 (bw_ctx)->p += duk__val_len; \ 432 } while (0) 433 #define DUK_BW_WRITE_ENSURE_HBUFFER_FIXED(thr,bw_ctx,val) do { \ 434 duk_size_t duk__val_len; \ 435 duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \ 436 DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \ 437 DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \ 438 (bw_ctx)->p += duk__val_len; \ 439 } while (0) 440 #define DUK_BW_WRITE_ENSURE_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \ 441 duk_size_t duk__val_len; \ 442 duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \ 443 DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \ 444 DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \ 445 (bw_ctx)->p += duk__val_len; \ 446 } while (0) 447 448 #define DUK_BW_WRITE_ENSURE_SLICE(thr,bw,dst_off,dst_len) \ 449 duk_bw_write_ensure_slice((thr), (bw), (dst_off), (dst_len)) 450 #define DUK_BW_INSERT_ENSURE_BYTES(thr,bw,dst_off,buf,len) \ 451 duk_bw_insert_ensure_bytes((thr), (bw), (dst_off), (buf), (len)) 452 #define DUK_BW_INSERT_ENSURE_SLICE(thr,bw,dst_off,src_off,len) \ 453 duk_bw_insert_ensure_slice((thr), (bw), (dst_off), (src_off), (len)) 454 #define DUK_BW_INSERT_ENSURE_AREA(thr,bw,off,len) \ 455 /* Evaluates to (duk_uint8_t *) pointing to start of area. */ \ 456 duk_bw_insert_ensure_area((thr), (bw), (off), (len)) 457 #define DUK_BW_REMOVE_ENSURE_SLICE(thr,bw,off,len) \ 458 /* No difference between raw/ensure because the buffer shrinks. */ \ 459 DUK_BW_REMOVE_RAW_SLICE((thr), (bw), (off), (len)) 460 461 /* 462 * Externs and prototypes 463 */ 464 465 #if !defined(DUK_SINGLE_FILE) 466 DUK_INTERNAL_DECL const duk_uint8_t duk_lc_digits[36]; 467 DUK_INTERNAL_DECL const duk_uint8_t duk_uc_nybbles[16]; 468 DUK_INTERNAL_DECL const duk_int8_t duk_hex_dectab[256]; 469 #if defined(DUK_USE_HEX_FASTPATH) 470 DUK_INTERNAL_DECL const duk_int16_t duk_hex_dectab_shift4[256]; 471 DUK_INTERNAL_DECL const duk_uint16_t duk_hex_enctab[256]; 472 #endif 473 #if defined(DUK_USE_BASE64_FASTPATH) 474 DUK_INTERNAL_DECL const duk_uint8_t duk_base64_enctab[64]; 475 DUK_INTERNAL_DECL const duk_int8_t duk_base64_dectab[256]; 476 #endif 477 #endif /* !DUK_SINGLE_FILE */ 478 479 /* Note: assumes that duk_util_probe_steps size is 32 */ 480 #if defined(DUK_USE_HOBJECT_HASH_PART) || defined(DUK_USE_STRTAB_PROBE) 481 #if !defined(DUK_SINGLE_FILE) 482 DUK_INTERNAL_DECL duk_uint8_t duk_util_probe_steps[32]; 483 #endif /* !DUK_SINGLE_FILE */ 484 #endif 485 486 #if defined(DUK_USE_STRHASH_DENSE) 487 DUK_INTERNAL_DECL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed); 488 #endif 489 490 #if defined(DUK_USE_HOBJECT_HASH_PART) || defined(DUK_USE_STRTAB_PROBE) 491 DUK_INTERNAL_DECL duk_uint32_t duk_util_get_hash_prime(duk_uint32_t size); 492 #endif 493 494 DUK_INTERNAL_DECL duk_int32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits); 495 DUK_INTERNAL_DECL duk_small_int_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx); 496 DUK_INTERNAL_DECL duk_int32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value); 497 498 DUK_INTERNAL_DECL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits); 499 DUK_INTERNAL_DECL void duk_be_finish(duk_bitencoder_ctx *ctx); 500 501 DUK_INTERNAL_DECL duk_uint32_t duk_util_tinyrandom_get_bits(duk_hthread *thr, duk_small_int_t n); 502 DUK_INTERNAL_DECL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr); 503 504 DUK_INTERNAL_DECL void duk_bw_init(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_hbuffer_dynamic *h_buf); 505 DUK_INTERNAL_DECL void duk_bw_init_pushbuf(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t buf_size); 506 DUK_INTERNAL_DECL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz); 507 DUK_INTERNAL_DECL void duk_bw_compact(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx); 508 DUK_INTERNAL_DECL void duk_bw_write_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len); 509 DUK_INTERNAL_DECL void duk_bw_write_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len); 510 DUK_INTERNAL_DECL void duk_bw_insert_raw_bytes(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, const duk_uint8_t *buf, duk_size_t len); 511 DUK_INTERNAL_DECL void duk_bw_insert_ensure_bytes(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, const duk_uint8_t *buf, duk_size_t len); 512 DUK_INTERNAL_DECL void duk_bw_insert_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, duk_size_t src_off, duk_size_t len); 513 DUK_INTERNAL_DECL void duk_bw_insert_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, duk_size_t src_off, duk_size_t len); 514 DUK_INTERNAL_DECL duk_uint8_t *duk_bw_insert_raw_area(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len); 515 DUK_INTERNAL_DECL duk_uint8_t *duk_bw_insert_ensure_area(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len); 516 DUK_INTERNAL_DECL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len); 517 /* No duk_bw_remove_ensure_slice(), functionality would be identical. */ 518 519 DUK_INTERNAL_DECL duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p); 520 DUK_INTERNAL_DECL duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p); 521 DUK_INTERNAL_DECL duk_double_t duk_raw_read_double_be(duk_uint8_t **p); 522 DUK_INTERNAL_DECL void duk_raw_write_u16_be(duk_uint8_t **p, duk_uint16_t val); 523 DUK_INTERNAL_DECL void duk_raw_write_u32_be(duk_uint8_t **p, duk_uint32_t val); 524 DUK_INTERNAL_DECL void duk_raw_write_double_be(duk_uint8_t **p, duk_double_t val); 525 526 #if defined(DUK_USE_DEBUGGER_SUPPORT) /* For now only needed by the debugger. */ 527 DUK_INTERNAL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len); 528 #endif 529 530 #endif /* DUK_UTIL_H_INCLUDED */ 531