1 /*
2  *  Utilities
3  */
4 
5 #if !defined(DUK_UTIL_H_INCLUDED)
6 #define DUK_UTIL_H_INCLUDED
7 
8 #if defined(DUK_USE_GET_RANDOM_DOUBLE)
9 #define DUK_UTIL_GET_RANDOM_DOUBLE(thr) DUK_USE_GET_RANDOM_DOUBLE((thr)->heap_udata)
10 #else
11 #define DUK_UTIL_GET_RANDOM_DOUBLE(thr) duk_util_tinyrandom_get_double(thr)
12 #endif
13 
14 /*
15  *  Some useful constants
16  */
17 
18 #define DUK_DOUBLE_2TO32     4294967296.0
19 #define DUK_DOUBLE_2TO31     2147483648.0
20 #define DUK_DOUBLE_LOG2E     1.4426950408889634
21 #define DUK_DOUBLE_LOG10E    0.4342944819032518
22 
23 /*
24  *  Endian conversion
25  */
26 
27 #if defined(DUK_USE_INTEGER_LE)
28 #define DUK_HTON32(x) DUK_BSWAP32((x))
29 #define DUK_NTOH32(x) DUK_BSWAP32((x))
30 #define DUK_HTON16(x) DUK_BSWAP16((x))
31 #define DUK_NTOH16(x) DUK_BSWAP16((x))
32 #elif defined(DUK_USE_INTEGER_BE)
33 #define DUK_HTON32(x) (x)
34 #define DUK_NTOH32(x) (x)
35 #define DUK_HTON16(x) (x)
36 #define DUK_NTOH16(x) (x)
37 #else
38 #error internal error, endianness defines broken
39 #endif
40 
41 /*
42  *  Bitstream decoder
43  */
44 
45 struct duk_bitdecoder_ctx {
46 	const duk_uint8_t *data;
47 	duk_size_t offset;
48 	duk_size_t length;
49 	duk_uint32_t currval;
50 	duk_small_int_t currbits;
51 };
52 
53 #define DUK_BD_BITPACKED_STRING_MAXLEN 256
54 
55 /*
56  *  Bitstream encoder
57  */
58 
59 struct duk_bitencoder_ctx {
60 	duk_uint8_t *data;
61 	duk_size_t offset;
62 	duk_size_t length;
63 	duk_uint32_t currval;
64 	duk_small_int_t currbits;
65 	duk_small_int_t truncated;
66 };
67 
68 /*
69  *  Raw write/read macros for big endian, unaligned basic values.
70  *  Caller ensures there's enough space.  The INC macro variants
71  *  update the pointer argument automatically.
72  */
73 
74 #define DUK_RAW_WRITE_U8(ptr,val)  do { \
75 		*(ptr) = (duk_uint8_t) (val); \
76 	} while (0)
77 #define DUK_RAW_WRITE_U16_BE(ptr,val) duk_raw_write_u16_be((ptr), (duk_uint16_t) (val))
78 #define DUK_RAW_WRITE_U32_BE(ptr,val) duk_raw_write_u32_be((ptr), (duk_uint32_t) (val))
79 #define DUK_RAW_WRITE_FLOAT_BE(ptr,val) duk_raw_write_float_be((ptr), (duk_float_t) (val))
80 #define DUK_RAW_WRITE_DOUBLE_BE(ptr,val) duk_raw_write_double_be((ptr), (duk_double_t) (val))
81 #define DUK_RAW_WRITE_XUTF8(ptr,val) duk_raw_write_xutf8((ptr), (duk_ucodepoint_t) (val))
82 
83 #define DUK_RAW_WRITEINC_U8(ptr,val)  do { \
84 		*(ptr)++ = (duk_uint8_t) (val); \
85 	} while (0)
86 #define DUK_RAW_WRITEINC_U16_BE(ptr,val) duk_raw_writeinc_u16_be(&(ptr), (duk_uint16_t) (val))
87 #define DUK_RAW_WRITEINC_U32_BE(ptr,val) duk_raw_writeinc_u32_be(&(ptr), (duk_uint32_t) (val))
88 #define DUK_RAW_WRITEINC_FLOAT_BE(ptr,val) duk_raw_writeinc_float_be(&(ptr), (duk_float_t) (val))
89 #define DUK_RAW_WRITEINC_DOUBLE_BE(ptr,val) duk_raw_writeinc_double_be(&(ptr), (duk_double_t) (val))
90 #define DUK_RAW_WRITEINC_XUTF8(ptr,val) duk_raw_writeinc_xutf8(&(ptr), (duk_ucodepoint_t) (val))
91 #define DUK_RAW_WRITEINC_CESU8(ptr,val) duk_raw_writeinc_cesu8(&(ptr), (duk_ucodepoint_t) (val))
92 
93 #define DUK_RAW_READ_U8(ptr) ((duk_uint8_t) (*(ptr)))
94 #define DUK_RAW_READ_U16_BE(ptr) duk_raw_read_u16_be((ptr));
95 #define DUK_RAW_READ_U32_BE(ptr) duk_raw_read_u32_be((ptr));
96 #define DUK_RAW_READ_DOUBLE_BE(ptr) duk_raw_read_double_be((ptr));
97 
98 #define DUK_RAW_READINC_U8(ptr) ((duk_uint8_t) (*(ptr)++))
99 #define DUK_RAW_READINC_U16_BE(ptr) duk_raw_readinc_u16_be(&(ptr));
100 #define DUK_RAW_READINC_U32_BE(ptr) duk_raw_readinc_u32_be(&(ptr));
101 #define DUK_RAW_READINC_DOUBLE_BE(ptr) duk_raw_readinc_double_be(&(ptr));
102 
103 /*
104  *  Double and float byte order operations.
105  */
106 
107 DUK_INTERNAL_DECL void duk_dblunion_host_to_little(duk_double_union *u);
108 DUK_INTERNAL_DECL void duk_dblunion_little_to_host(duk_double_union *u);
109 DUK_INTERNAL_DECL void duk_dblunion_host_to_big(duk_double_union *u);
110 DUK_INTERNAL_DECL void duk_dblunion_big_to_host(duk_double_union *u);
111 DUK_INTERNAL_DECL void duk_fltunion_host_to_big(duk_float_union *u);
112 DUK_INTERNAL_DECL void duk_fltunion_big_to_host(duk_float_union *u);
113 
114 /*
115  *  Buffer writer (dynamic buffer only)
116  *
117  *  Helper for writing to a dynamic buffer with a concept of a "slack" area
118  *  to reduce resizes.  You can ensure there is enough space beforehand and
119  *  then write for a while without further checks, relying on a stable data
120  *  pointer.  Slack handling is automatic so call sites only indicate how
121  *  much data they need right now.
122  *
123  *  There are several ways to write using bufwriter.  The best approach
124  *  depends mainly on how much performance matters over code footprint.
125  *  The key issues are (1) ensuring there is space and (2) keeping the
126  *  pointers consistent.  Fast code should ensure space for multiple writes
127  *  with one ensure call.  Fastest inner loop code can temporarily borrow
128  *  the 'p' pointer but must write it back eventually.
129  *
130  *  Be careful to ensure all macro arguments (other than static pointers like
131  *  'thr' and 'bw_ctx') are evaluated exactly once, using temporaries if
132  *  necessary (if that's not possible, there should be a note near the macro).
133  *  Buffer write arguments often contain arithmetic etc so this is
134  *  particularly important here.
135  */
136 
137 /* XXX: Migrate bufwriter and other read/write helpers to its own header? */
138 
139 struct duk_bufwriter_ctx {
140 	duk_uint8_t *p;
141 	duk_uint8_t *p_base;
142 	duk_uint8_t *p_limit;
143 	duk_hbuffer_dynamic *buf;
144 };
145 
146 #if defined(DUK_USE_PREFER_SIZE)
147 #define DUK_BW_SLACK_ADD           64
148 #define DUK_BW_SLACK_SHIFT         4    /* 2^4 -> 1/16 = 6.25% slack */
149 #else
150 #define DUK_BW_SLACK_ADD           64
151 #define DUK_BW_SLACK_SHIFT         2    /* 2^2 -> 1/4 = 25% slack */
152 #endif
153 
154 /* Initialization and finalization (compaction), converting to other types. */
155 
156 #define DUK_BW_INIT_PUSHBUF(thr,bw_ctx,sz) do { \
157 		duk_bw_init_pushbuf((thr), (bw_ctx), (sz)); \
158 	} while (0)
159 #define DUK_BW_INIT_WITHBUF(thr,bw_ctx,buf) do { \
160 		duk_bw_init((thr), (bw_ctx), (buf)); \
161 	} while (0)
162 #define DUK_BW_COMPACT(thr,bw_ctx) do { \
163 		/* Make underlying buffer compact to match DUK_BW_GET_SIZE(). */ \
164 		duk_bw_compact((thr), (bw_ctx)); \
165 	} while (0)
166 #define DUK_BW_PUSH_AS_STRING(thr,bw_ctx) do { \
167 		duk_push_lstring((thr), \
168 		                 (const char *) (bw_ctx)->p_base, \
169 		                 (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \
170 	} while (0)
171 
172 /* Pointers may be NULL for a while when 'buf' size is zero and before any
173  * ENSURE calls have been made.  Once an ENSURE has been made, the pointers
174  * are required to be non-NULL so that it's always valid to use memcpy() and
175  * memmove(), even for zero size.
176  */
177 #if defined(DUK_USE_ASSERTIONS)
178 DUK_INTERNAL_DECL void duk_bw_assert_valid(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx);
179 #define DUK_BW_ASSERT_VALID_EXPR(thr,bw_ctx)  (duk_bw_assert_valid((thr), (bw_ctx)))
180 #define DUK_BW_ASSERT_VALID(thr,bw_ctx)  do { duk_bw_assert_valid((thr), (bw_ctx)); } while (0)
181 #else
182 #define DUK_BW_ASSERT_VALID_EXPR(thr,bw_ctx)  DUK_ASSERT_EXPR(1)
183 #define DUK_BW_ASSERT_VALID(thr,bw_ctx)  do {} while (0)
184 #endif
185 
186 /* Working with the pointer and current size. */
187 
188 #define DUK_BW_GET_PTR(thr,bw_ctx) \
189 	((bw_ctx)->p)
190 #define DUK_BW_SET_PTR(thr,bw_ctx,ptr) do { \
191 		(bw_ctx)->p = (ptr); \
192 	} while (0)
193 #define DUK_BW_ADD_PTR(thr,bw_ctx,delta) do { \
194 		(bw_ctx)->p += (delta); \
195 	} while (0)
196 #define DUK_BW_GET_BASEPTR(thr,bw_ctx) \
197 	((bw_ctx)->p_base)
198 #define DUK_BW_GET_LIMITPTR(thr,bw_ctx) \
199 	((bw_ctx)->p_limit)
200 #define DUK_BW_GET_SIZE(thr,bw_ctx) \
201 	((duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base))
202 #define DUK_BW_SET_SIZE(thr,bw_ctx,sz) do { \
203 		DUK_ASSERT((duk_size_t) (sz) <= (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \
204 		(bw_ctx)->p = (bw_ctx)->p_base + (sz); \
205 	} while (0)
206 #define DUK_BW_RESET_SIZE(thr,bw_ctx) do { \
207 		/* Reset to zero size, keep current limit. */ \
208 		(bw_ctx)->p = (bw_ctx)->p_base; \
209 	} while (0)
210 #define DUK_BW_GET_BUFFER(thr,bw_ctx) \
211 	((bw_ctx)->buf)
212 
213 /* Ensuring (reserving) space. */
214 
215 #define DUK_BW_ENSURE(thr,bw_ctx,sz) do { \
216 		duk_size_t duk__sz, duk__space; \
217 		DUK_BW_ASSERT_VALID((thr), (bw_ctx)); \
218 		duk__sz = (sz); \
219 		duk__space = (duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p); \
220 		if (duk__space < duk__sz) { \
221 			(void) duk_bw_resize((thr), (bw_ctx), duk__sz); \
222 		} \
223 	} while (0)
224 /* NOTE: Multiple evaluation of 'ptr' in this macro. */
225 /* XXX: Rework to use an always-inline function? */
226 #define DUK_BW_ENSURE_RAW(thr,bw_ctx,sz,ptr) \
227 	(((duk_size_t) ((bw_ctx)->p_limit - (ptr)) >= (sz)) ? \
228 	 (ptr) : \
229 	 ((bw_ctx)->p = (ptr), duk_bw_resize((thr),(bw_ctx),(sz))))
230 #define DUK_BW_ENSURE_GETPTR(thr,bw_ctx,sz) \
231 	DUK_BW_ENSURE_RAW((thr), (bw_ctx), (sz), (bw_ctx)->p)
232 #define DUK_BW_ASSERT_SPACE_EXPR(thr,bw_ctx,sz) \
233 	(DUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)), \
234 	 DUK_ASSERT_EXPR((duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p) >= (duk_size_t) (sz)))
235 #define DUK_BW_ASSERT_SPACE(thr,bw_ctx,sz) do { \
236 		DUK_BW_ASSERT_SPACE_EXPR((thr), (bw_ctx), (sz)); \
237 	} while (0)
238 
239 /* Miscellaneous. */
240 
241 #define DUK_BW_SETPTR_AND_COMPACT(thr,bw_ctx,ptr) do { \
242 		(bw_ctx)->p = (ptr); \
243 		duk_bw_compact((thr), (bw_ctx)); \
244 	} while (0)
245 
246 /* Fast write calls which assume you control the slack beforehand.
247  * Multibyte write variants exist and use a temporary write pointer
248  * because byte writes alias with anything: with a stored pointer
249  * explicit pointer load/stores get generated (e.g. gcc -Os).
250  */
251 
252 #define DUK_BW_WRITE_RAW_U8(thr,bw_ctx,val) do { \
253 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 1); \
254 		*(bw_ctx)->p++ = (duk_uint8_t) (val); \
255 	} while (0)
256 #define DUK_BW_WRITE_RAW_U8_2(thr,bw_ctx,val1,val2) do { \
257 		duk_uint8_t *duk__p; \
258 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 2); \
259 		duk__p = (bw_ctx)->p; \
260 		*duk__p++ = (duk_uint8_t) (val1); \
261 		*duk__p++ = (duk_uint8_t) (val2); \
262 		(bw_ctx)->p = duk__p; \
263 	} while (0)
264 #define DUK_BW_WRITE_RAW_U8_3(thr,bw_ctx,val1,val2,val3) do { \
265 		duk_uint8_t *duk__p; \
266 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 3); \
267 		duk__p = (bw_ctx)->p; \
268 		*duk__p++ = (duk_uint8_t) (val1); \
269 		*duk__p++ = (duk_uint8_t) (val2); \
270 		*duk__p++ = (duk_uint8_t) (val3); \
271 		(bw_ctx)->p = duk__p; \
272 	} while (0)
273 #define DUK_BW_WRITE_RAW_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \
274 		duk_uint8_t *duk__p; \
275 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 4); \
276 		duk__p = (bw_ctx)->p; \
277 		*duk__p++ = (duk_uint8_t) (val1); \
278 		*duk__p++ = (duk_uint8_t) (val2); \
279 		*duk__p++ = (duk_uint8_t) (val3); \
280 		*duk__p++ = (duk_uint8_t) (val4); \
281 		(bw_ctx)->p = duk__p; \
282 	} while (0)
283 #define DUK_BW_WRITE_RAW_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \
284 		duk_uint8_t *duk__p; \
285 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 5); \
286 		duk__p = (bw_ctx)->p; \
287 		*duk__p++ = (duk_uint8_t) (val1); \
288 		*duk__p++ = (duk_uint8_t) (val2); \
289 		*duk__p++ = (duk_uint8_t) (val3); \
290 		*duk__p++ = (duk_uint8_t) (val4); \
291 		*duk__p++ = (duk_uint8_t) (val5); \
292 		(bw_ctx)->p = duk__p; \
293 	} while (0)
294 #define DUK_BW_WRITE_RAW_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \
295 		duk_uint8_t *duk__p; \
296 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 6); \
297 		duk__p = (bw_ctx)->p; \
298 		*duk__p++ = (duk_uint8_t) (val1); \
299 		*duk__p++ = (duk_uint8_t) (val2); \
300 		*duk__p++ = (duk_uint8_t) (val3); \
301 		*duk__p++ = (duk_uint8_t) (val4); \
302 		*duk__p++ = (duk_uint8_t) (val5); \
303 		*duk__p++ = (duk_uint8_t) (val6); \
304 		(bw_ctx)->p = duk__p; \
305 	} while (0)
306 #define DUK_BW_WRITE_RAW_XUTF8(thr,bw_ctx,cp) do { \
307 		duk_ucodepoint_t duk__cp; \
308 		duk_small_int_t duk__enc_len; \
309 		duk__cp = (duk_ucodepoint_t) (cp); \
310 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_xutf8_length(duk__cp)); \
311 		duk__enc_len = duk_unicode_encode_xutf8(duk__cp, (bw_ctx)->p); \
312 		(bw_ctx)->p += duk__enc_len; \
313 	} while (0)
314 #define DUK_BW_WRITE_RAW_CESU8(thr,bw_ctx,cp) do { \
315 		duk_ucodepoint_t duk__cp; \
316 		duk_small_int_t duk__enc_len; \
317 		duk__cp = (duk_ucodepoint_t) (cp); \
318 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_cesu8_length(duk__cp)); \
319 		duk__enc_len = duk_unicode_encode_cesu8(duk__cp, (bw_ctx)->p); \
320 		(bw_ctx)->p += duk__enc_len; \
321 	} while (0)
322 /* XXX: add temporary duk__p pointer here too; sharing */
323 /* XXX: avoid unsafe variants */
324 #define DUK_BW_WRITE_RAW_BYTES(thr,bw_ctx,valptr,valsz) do { \
325 		const void *duk__valptr; \
326 		duk_size_t duk__valsz; \
327 		duk__valptr = (const void *) (valptr); \
328 		duk__valsz = (duk_size_t) (valsz); \
329 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \
330 		(bw_ctx)->p += duk__valsz; \
331 	} while (0)
332 #define DUK_BW_WRITE_RAW_CSTRING(thr,bw_ctx,val) do { \
333 		const duk_uint8_t *duk__val; \
334 		duk_size_t duk__val_len; \
335 		duk__val = (const duk_uint8_t *) (val); \
336 		duk__val_len = DUK_STRLEN((const char *) duk__val); \
337 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \
338 		(bw_ctx)->p += duk__val_len; \
339 	} while (0)
340 #define DUK_BW_WRITE_RAW_HSTRING(thr,bw_ctx,val) do { \
341 		duk_size_t duk__val_len; \
342 		duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \
343 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \
344 		(bw_ctx)->p += duk__val_len; \
345 	} while (0)
346 #define DUK_BW_WRITE_RAW_HBUFFER(thr,bw_ctx,val) do { \
347 		duk_size_t duk__val_len; \
348 		duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \
349 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
350 		(bw_ctx)->p += duk__val_len; \
351 	} while (0)
352 #define DUK_BW_WRITE_RAW_HBUFFER_FIXED(thr,bw_ctx,val) do { \
353 		duk_size_t duk__val_len; \
354 		duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \
355 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
356 		(bw_ctx)->p += duk__val_len; \
357 	} while (0)
358 #define DUK_BW_WRITE_RAW_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \
359 		duk_size_t duk__val_len; \
360 		duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \
361 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
362 		(bw_ctx)->p += duk__val_len; \
363 	} while (0)
364 
365 /* Append bytes from a slice already in the buffer. */
366 #define DUK_BW_WRITE_RAW_SLICE(thr,bw,dst_off,dst_len) \
367 	duk_bw_write_raw_slice((thr), (bw), (dst_off), (dst_len))
368 
369 /* Insert bytes in the middle of the buffer from an external buffer. */
370 #define DUK_BW_INSERT_RAW_BYTES(thr,bw,dst_off,buf,len) \
371 	duk_bw_insert_raw_bytes((thr), (bw), (dst_off), (buf), (len))
372 
373 /* Insert bytes in the middle of the buffer from a slice already
374  * in the buffer.  Source offset is interpreted "before" the operation.
375  */
376 #define DUK_BW_INSERT_RAW_SLICE(thr,bw,dst_off,src_off,len) \
377 	duk_bw_insert_raw_slice((thr), (bw), (dst_off), (src_off), (len))
378 
379 /* Insert a reserved area somewhere in the buffer; caller fills it.
380  * Evaluates to a (duk_uint_t *) pointing to the start of the reserved
381  * area for convenience.
382  */
383 #define DUK_BW_INSERT_RAW_AREA(thr,bw,off,len) \
384 	duk_bw_insert_raw_area((thr), (bw), (off), (len))
385 
386 /* Remove a slice from inside buffer. */
387 #define DUK_BW_REMOVE_RAW_SLICE(thr,bw,off,len) \
388 	duk_bw_remove_raw_slice((thr), (bw), (off), (len))
389 
390 /* Safe write calls which will ensure space first. */
391 
392 #define DUK_BW_WRITE_ENSURE_U8(thr,bw_ctx,val) do { \
393 		DUK_BW_ENSURE((thr), (bw_ctx), 1); \
394 		DUK_BW_WRITE_RAW_U8((thr), (bw_ctx), (val)); \
395 	} while (0)
396 #define DUK_BW_WRITE_ENSURE_U8_2(thr,bw_ctx,val1,val2) do { \
397 		DUK_BW_ENSURE((thr), (bw_ctx), 2); \
398 		DUK_BW_WRITE_RAW_U8_2((thr), (bw_ctx), (val1), (val2)); \
399 	} while (0)
400 #define DUK_BW_WRITE_ENSURE_U8_3(thr,bw_ctx,val1,val2,val3) do { \
401 		DUK_BW_ENSURE((thr), (bw_ctx), 3); \
402 		DUK_BW_WRITE_RAW_U8_3((thr), (bw_ctx), (val1), (val2), (val3)); \
403 	} while (0)
404 #define DUK_BW_WRITE_ENSURE_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \
405 		DUK_BW_ENSURE((thr), (bw_ctx), 4); \
406 		DUK_BW_WRITE_RAW_U8_4((thr), (bw_ctx), (val1), (val2), (val3), (val4)); \
407 	} while (0)
408 #define DUK_BW_WRITE_ENSURE_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \
409 		DUK_BW_ENSURE((thr), (bw_ctx), 5); \
410 		DUK_BW_WRITE_RAW_U8_5((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5)); \
411 	} while (0)
412 #define DUK_BW_WRITE_ENSURE_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \
413 		DUK_BW_ENSURE((thr), (bw_ctx), 6); \
414 		DUK_BW_WRITE_RAW_U8_6((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5), (val6)); \
415 	} while (0)
416 #define DUK_BW_WRITE_ENSURE_XUTF8(thr,bw_ctx,cp) do { \
417 		DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_XUTF8_LENGTH); \
418 		DUK_BW_WRITE_RAW_XUTF8((thr), (bw_ctx), (cp)); \
419 	} while (0)
420 #define DUK_BW_WRITE_ENSURE_CESU8(thr,bw_ctx,cp) do { \
421 		DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_CESU8_LENGTH); \
422 		DUK_BW_WRITE_RAW_CESU8((thr), (bw_ctx), (cp)); \
423 	} while (0)
424 /* XXX: add temporary duk__p pointer here too; sharing */
425 /* XXX: avoid unsafe */
426 #define DUK_BW_WRITE_ENSURE_BYTES(thr,bw_ctx,valptr,valsz) do { \
427 		const void *duk__valptr; \
428 		duk_size_t duk__valsz; \
429 		duk__valptr = (const void *) (valptr); \
430 		duk__valsz = (duk_size_t) (valsz); \
431 		DUK_BW_ENSURE((thr), (bw_ctx), duk__valsz); \
432 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \
433 		(bw_ctx)->p += duk__valsz; \
434 	} while (0)
435 #define DUK_BW_WRITE_ENSURE_CSTRING(thr,bw_ctx,val) do { \
436 		const duk_uint8_t *duk__val; \
437 		duk_size_t duk__val_len; \
438 		duk__val = (const duk_uint8_t *) (val); \
439 		duk__val_len = DUK_STRLEN((const char *) duk__val); \
440 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
441 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \
442 		(bw_ctx)->p += duk__val_len; \
443 	} while (0)
444 #define DUK_BW_WRITE_ENSURE_HSTRING(thr,bw_ctx,val) do { \
445 		duk_size_t duk__val_len; \
446 		duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \
447 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
448 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \
449 		(bw_ctx)->p += duk__val_len; \
450 	} while (0)
451 #define DUK_BW_WRITE_ENSURE_HBUFFER(thr,bw_ctx,val) do { \
452 		duk_size_t duk__val_len; \
453 		duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \
454 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
455 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
456 		(bw_ctx)->p += duk__val_len; \
457 	} while (0)
458 #define DUK_BW_WRITE_ENSURE_HBUFFER_FIXED(thr,bw_ctx,val) do { \
459 		duk_size_t duk__val_len; \
460 		duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \
461 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
462 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
463 		(bw_ctx)->p += duk__val_len; \
464 	} while (0)
465 #define DUK_BW_WRITE_ENSURE_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \
466 		duk_size_t duk__val_len; \
467 		duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \
468 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
469 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
470 		(bw_ctx)->p += duk__val_len; \
471 	} while (0)
472 
473 #define DUK_BW_WRITE_ENSURE_SLICE(thr,bw,dst_off,dst_len) \
474 	duk_bw_write_ensure_slice((thr), (bw), (dst_off), (dst_len))
475 #define DUK_BW_INSERT_ENSURE_BYTES(thr,bw,dst_off,buf,len) \
476 	duk_bw_insert_ensure_bytes((thr), (bw), (dst_off), (buf), (len))
477 #define DUK_BW_INSERT_ENSURE_SLICE(thr,bw,dst_off,src_off,len) \
478 	duk_bw_insert_ensure_slice((thr), (bw), (dst_off), (src_off), (len))
479 #define DUK_BW_INSERT_ENSURE_AREA(thr,bw,off,len) \
480 	/* Evaluates to (duk_uint8_t *) pointing to start of area. */ \
481 	duk_bw_insert_ensure_area((thr), (bw), (off), (len))
482 #define DUK_BW_REMOVE_ENSURE_SLICE(thr,bw,off,len) \
483 	/* No difference between raw/ensure because the buffer shrinks. */ \
484 	DUK_BW_REMOVE_RAW_SLICE((thr), (bw), (off), (len))
485 
486 /*
487  *  Externs and prototypes
488  */
489 
490 #if !defined(DUK_SINGLE_FILE)
491 DUK_INTERNAL_DECL const duk_uint8_t duk_lc_digits[36];
492 DUK_INTERNAL_DECL const duk_uint8_t duk_uc_nybbles[16];
493 DUK_INTERNAL_DECL const duk_int8_t duk_hex_dectab[256];
494 #if defined(DUK_USE_HEX_FASTPATH)
495 DUK_INTERNAL_DECL const duk_int16_t duk_hex_dectab_shift4[256];
496 DUK_INTERNAL_DECL const duk_uint16_t duk_hex_enctab[256];
497 #endif
498 #endif  /* !DUK_SINGLE_FILE */
499 
500 /* Note: assumes that duk_util_probe_steps size is 32 */
501 #if defined(DUK_USE_HOBJECT_HASH_PART)
502 #if !defined(DUK_SINGLE_FILE)
503 DUK_INTERNAL_DECL duk_uint8_t duk_util_probe_steps[32];
504 #endif  /* !DUK_SINGLE_FILE */
505 #endif
506 
507 #if defined(DUK_USE_STRHASH_DENSE)
508 DUK_INTERNAL_DECL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed);
509 #endif
510 
511 DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits);
512 DUK_INTERNAL_DECL duk_small_uint_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx);
513 DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_uint32_t def_value);
514 DUK_INTERNAL_DECL duk_int32_t duk_bd_decode_flagged_signed(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value);
515 DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode_varuint(duk_bitdecoder_ctx *ctx);
516 DUK_INTERNAL_DECL duk_small_uint_t duk_bd_decode_bitpacked_string(duk_bitdecoder_ctx *bd, duk_uint8_t *out);
517 
518 DUK_INTERNAL_DECL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits);
519 DUK_INTERNAL_DECL void duk_be_finish(duk_bitencoder_ctx *ctx);
520 
521 #if !defined(DUK_USE_GET_RANDOM_DOUBLE)
522 DUK_INTERNAL_DECL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr);
523 DUK_INTERNAL_DECL void duk_util_tinyrandom_prepare_seed(duk_hthread *thr);
524 #endif
525 
526 DUK_INTERNAL_DECL void duk_bw_init(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_hbuffer_dynamic *h_buf);
527 DUK_INTERNAL_DECL void duk_bw_init_pushbuf(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t buf_size);
528 DUK_INTERNAL_DECL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz);
529 DUK_INTERNAL_DECL void duk_bw_compact(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx);
530 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);
531 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);
532 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);
533 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);
534 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);
535 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);
536 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);
537 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);
538 DUK_INTERNAL_DECL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len);
539 /* No duk_bw_remove_ensure_slice(), functionality would be identical. */
540 
541 DUK_INTERNAL_DECL duk_uint16_t duk_raw_read_u16_be(const duk_uint8_t *p);
542 DUK_INTERNAL_DECL duk_uint32_t duk_raw_read_u32_be(const duk_uint8_t *p);
543 DUK_INTERNAL_DECL duk_float_t duk_raw_read_float_be(const duk_uint8_t *p);
544 DUK_INTERNAL_DECL duk_double_t duk_raw_read_double_be(const duk_uint8_t *p);
545 DUK_INTERNAL_DECL duk_uint16_t duk_raw_readinc_u16_be(const duk_uint8_t **p);
546 DUK_INTERNAL_DECL duk_uint32_t duk_raw_readinc_u32_be(const duk_uint8_t **p);
547 DUK_INTERNAL_DECL duk_float_t duk_raw_readinc_float_be(const duk_uint8_t **p);
548 DUK_INTERNAL_DECL duk_double_t duk_raw_readinc_double_be(const duk_uint8_t **p);
549 DUK_INTERNAL_DECL void duk_raw_write_u16_be(duk_uint8_t *p, duk_uint16_t val);
550 DUK_INTERNAL_DECL void duk_raw_write_u32_be(duk_uint8_t *p, duk_uint32_t val);
551 DUK_INTERNAL_DECL void duk_raw_write_float_be(duk_uint8_t *p, duk_float_t val);
552 DUK_INTERNAL_DECL void duk_raw_write_double_be(duk_uint8_t *p, duk_double_t val);
553 DUK_INTERNAL_DECL duk_small_int_t duk_raw_write_xutf8(duk_uint8_t *p, duk_ucodepoint_t val);
554 DUK_INTERNAL_DECL duk_small_int_t duk_raw_write_cesu8(duk_uint8_t *p, duk_ucodepoint_t val);
555 DUK_INTERNAL_DECL void duk_raw_writeinc_u16_be(duk_uint8_t **p, duk_uint16_t val);
556 DUK_INTERNAL_DECL void duk_raw_writeinc_u32_be(duk_uint8_t **p, duk_uint32_t val);
557 DUK_INTERNAL_DECL void duk_raw_writeinc_float_be(duk_uint8_t **p, duk_float_t val);
558 DUK_INTERNAL_DECL void duk_raw_writeinc_double_be(duk_uint8_t **p, duk_double_t val);
559 DUK_INTERNAL_DECL void duk_raw_writeinc_xutf8(duk_uint8_t **p, duk_ucodepoint_t val);
560 DUK_INTERNAL_DECL void duk_raw_writeinc_cesu8(duk_uint8_t **p, duk_ucodepoint_t val);
561 
562 #if defined(DUK_USE_DEBUGGER_SUPPORT)  /* For now only needed by the debugger. */
563 DUK_INTERNAL_DECL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len);
564 #endif
565 
566 /* memcpy(), memmove() etc wrappers.  The plain variants like duk_memcpy()
567  * assume C99+ and 'src' and 'dst' pointers must be non-NULL even when the
568  * operation size is zero.  The unsafe variants like duk_memcpy_safe() deal
569  * with the zero size case explicitly, and allow NULL pointers in that case
570  * (which is undefined behavior in C99+).  For the majority of actual targets
571  * a NULL pointer with a zero length is fine in practice.  These wrappers are
572  * macros to force inlining; because there are hundreds of call sites, even a
573  * few extra bytes per call site adds up to ~1kB footprint.
574  */
575 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
576 #define duk_memcpy(dst,src,len)  do { \
577 		void *duk__dst = (dst); \
578 		const void *duk__src = (src); \
579 		duk_size_t duk__len = (len); \
580 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
581 		DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
582 		(void) DUK_MEMCPY(duk__dst, duk__src, (size_t) duk__len); \
583 	} while (0)
584 #define duk_memcpy_unsafe(dst,src,len)  duk_memcpy((dst), (src), (len))
585 #define duk_memmove(dst,src,len)  do { \
586 		void *duk__dst = (dst); \
587 		const void *duk__src = (src); \
588 		duk_size_t duk__len = (len); \
589 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
590 		DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
591 		(void) DUK_MEMMOVE(duk__dst, duk__src, (size_t) duk__len); \
592 	} while (0)
593 #define duk_memmove_unsafe(dst,src,len)  duk_memmove((dst), (src), (len))
594 #define duk_memset(dst,val,len)  do { \
595 		void *duk__dst = (dst); \
596 		duk_small_int_t duk__val = (val); \
597 		duk_size_t duk__len = (len); \
598 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
599 		(void) DUK_MEMSET(duk__dst, duk__val, (size_t) duk__len); \
600 	} while (0)
601 #define duk_memset_unsafe(dst,val,len)  duk_memset((dst), (val), (len))
602 #define duk_memzero(dst,len)  do { \
603 		void *duk__dst = (dst); \
604 		duk_size_t duk__len = (len); \
605 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
606 		(void) DUK_MEMZERO(duk__dst, (size_t) duk__len); \
607 	} while (0)
608 #define duk_memzero_unsafe(dst,len)  duk_memzero((dst), (len))
609 #else  /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
610 #define duk_memcpy(dst,src,len)  do { \
611 		void *duk__dst = (dst); \
612 		const void *duk__src = (src); \
613 		duk_size_t duk__len = (len); \
614 		DUK_ASSERT(duk__dst != NULL); \
615 		DUK_ASSERT(duk__src != NULL); \
616 		(void) DUK_MEMCPY(duk__dst, duk__src, (size_t) duk__len); \
617 	} while (0)
618 #define duk_memcpy_unsafe(dst,src,len)  do { \
619 		void *duk__dst = (dst); \
620 		const void *duk__src = (src); \
621 		duk_size_t duk__len = (len); \
622 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
623 		DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
624 		if (DUK_LIKELY(duk__len > 0U)) { \
625 			DUK_ASSERT(duk__dst != NULL); \
626 			DUK_ASSERT(duk__src != NULL); \
627 			(void) DUK_MEMCPY(duk__dst, duk__src, (size_t) duk__len); \
628 		} \
629 	} while (0)
630 #define duk_memmove(dst,src,len)  do { \
631 		void *duk__dst = (dst); \
632 		const void *duk__src = (src); \
633 		duk_size_t duk__len = (len); \
634 		DUK_ASSERT(duk__dst != NULL); \
635 		DUK_ASSERT(duk__src != NULL); \
636 		(void) DUK_MEMMOVE(duk__dst, duk__src, (size_t) duk__len); \
637 	} while (0)
638 #define duk_memmove_unsafe(dst,src,len)  do { \
639 		void *duk__dst = (dst); \
640 		const void *duk__src = (src); \
641 		duk_size_t duk__len = (len); \
642 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
643 		DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
644 		if (DUK_LIKELY(duk__len > 0U)) { \
645 			DUK_ASSERT(duk__dst != NULL); \
646 			DUK_ASSERT(duk__src != NULL); \
647 			(void) DUK_MEMMOVE(duk__dst, duk__src, (size_t) duk__len); \
648 		} \
649 	} while (0)
650 #define duk_memset(dst,val,len)  do { \
651 		void *duk__dst = (dst); \
652 		duk_small_int_t duk__val = (val); \
653 		duk_size_t duk__len = (len); \
654 		DUK_ASSERT(duk__dst != NULL); \
655 		(void) DUK_MEMSET(duk__dst, duk__val, (size_t) duk__len); \
656 	} while (0)
657 #define duk_memset_unsafe(dst,val,len)  do { \
658 		void *duk__dst = (dst); \
659 		duk_small_int_t duk__val = (val); \
660 		duk_size_t duk__len = (len); \
661 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
662 		if (DUK_LIKELY(duk__len > 0U)) { \
663 			DUK_ASSERT(duk__dst != NULL); \
664 			(void) DUK_MEMSET(duk__dst, duk__val, (size_t) duk__len); \
665 		} \
666 	} while (0)
667 #define duk_memzero(dst,len)  do { \
668 		void *duk__dst = (dst); \
669 		duk_size_t duk__len = (len); \
670 		DUK_ASSERT(duk__dst != NULL); \
671 		(void) DUK_MEMZERO(duk__dst, (size_t) duk__len); \
672 	} while (0)
673 #define duk_memzero_unsafe(dst,len)  do { \
674 		void *duk__dst = (dst); \
675 		duk_size_t duk__len = (len); \
676 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
677 		if (DUK_LIKELY(duk__len > 0U)) { \
678 			DUK_ASSERT(duk__dst != NULL); \
679 			(void) DUK_MEMZERO(duk__dst, (size_t) duk__len); \
680 		} \
681 	} while (0)
682 #endif  /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
683 
684 DUK_INTERNAL_DECL duk_small_int_t duk_memcmp(const void *s1, const void *s2, duk_size_t len);
685 DUK_INTERNAL_DECL duk_small_int_t duk_memcmp_unsafe(const void *s1, const void *s2, duk_size_t len);
686 
687 DUK_INTERNAL_DECL duk_bool_t duk_is_whole_get_int32_nonegzero(duk_double_t x, duk_int32_t *ival);
688 DUK_INTERNAL_DECL duk_bool_t duk_is_whole_get_int32(duk_double_t x, duk_int32_t *ival);
689 DUK_INTERNAL_DECL duk_bool_t duk_double_is_anyinf(duk_double_t x);
690 DUK_INTERNAL_DECL duk_bool_t duk_double_is_posinf(duk_double_t x);
691 DUK_INTERNAL_DECL duk_bool_t duk_double_is_neginf(duk_double_t x);
692 DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan(duk_double_t x);
693 DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_or_zero(duk_double_t x);
694 DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_or_inf(duk_double_t x);
695 DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_zero_inf(duk_double_t x);
696 DUK_INTERNAL_DECL duk_small_uint_t duk_double_signbit(duk_double_t x);
697 DUK_INTERNAL_DECL duk_double_t duk_double_trunc_towards_zero(duk_double_t x);
698 DUK_INTERNAL_DECL duk_bool_t duk_double_same_sign(duk_double_t x, duk_double_t y);
699 DUK_INTERNAL_DECL duk_double_t duk_double_fmin(duk_double_t x, duk_double_t y);
700 DUK_INTERNAL_DECL duk_double_t duk_double_fmax(duk_double_t x, duk_double_t y);
701 DUK_INTERNAL_DECL duk_bool_t duk_double_is_finite(duk_double_t x);
702 DUK_INTERNAL_DECL duk_bool_t duk_double_is_integer(duk_double_t x);
703 DUK_INTERNAL_DECL duk_bool_t duk_double_is_safe_integer(duk_double_t x);
704 
705 DUK_INTERNAL_DECL duk_double_t duk_double_div(duk_double_t x, duk_double_t y);
706 DUK_INTERNAL_DECL duk_int_t duk_double_to_int_t(duk_double_t x);
707 DUK_INTERNAL_DECL duk_uint_t duk_double_to_uint_t(duk_double_t x);
708 DUK_INTERNAL_DECL duk_int32_t duk_double_to_int32_t(duk_double_t x);
709 DUK_INTERNAL_DECL duk_uint32_t duk_double_to_uint32_t(duk_double_t x);
710 DUK_INTERNAL_DECL duk_float_t duk_double_to_float_t(duk_double_t x);
711 DUK_INTERNAL_DECL duk_bool_t duk_double_equals(duk_double_t x, duk_double_t y);
712 DUK_INTERNAL_DECL duk_bool_t duk_float_equals(duk_float_t x, duk_float_t y);
713 
714 /*
715  *  Miscellaneous
716  */
717 
718 /* Example: x     = 0x10 = 0b00010000
719  *          x - 1 = 0x0f = 0b00001111
720  *          x & (x - 1) == 0
721  *
722  *          x     = 0x07 = 0b00000111
723  *          x - 1 = 0x06 = 0b00000110
724  *          x & (x - 1) != 0
725  *
726  * However, incorrectly true for x == 0 so check for that explicitly.
727  */
728 #define DUK_IS_POWER_OF_TWO(x) \
729 	((x) != 0U && ((x) & ((x) - 1U)) == 0U)
730 
731 #endif  /* DUK_UTIL_H_INCLUDED */
732