]> git.proxmox.com Git - ceph.git/blame - ceph/src/civetweb/src/third_party/duktape-1.3.0/src-separate/duk_tval.h
bump version to 12.2.12-pve1
[ceph.git] / ceph / src / civetweb / src / third_party / duktape-1.3.0 / src-separate / duk_tval.h
CommitLineData
7c673cae
FG
1/*
2 * Tagged type definition (duk_tval) and accessor macros.
3 *
4 * Access all fields through the accessor macros, as the representation
5 * is quite tricky.
6 *
7 * There are two packed type alternatives: an 8-byte representation
8 * based on an IEEE double (preferred for compactness), and a 12-byte
9 * representation (portability). The latter is needed also in e.g.
10 * 64-bit environments (it usually pads to 16 bytes per value).
11 *
12 * Selecting the tagged type format involves many trade-offs (memory
13 * use, size and performance of generated code, portability, etc),
14 * see doc/types.rst for a detailed discussion (especially of how the
15 * IEEE double format is used to pack tagged values).
16 *
17 * NB: because macro arguments are often expressions, macros should
18 * avoid evaluating their argument more than once.
19 */
20
21#ifndef DUK_TVAL_H_INCLUDED
22#define DUK_TVAL_H_INCLUDED
23
24/* sanity */
25#if !defined(DUK_USE_DOUBLE_LE) && !defined(DUK_USE_DOUBLE_ME) && !defined(DUK_USE_DOUBLE_BE)
26#error unsupported: cannot determine byte order variant
27#endif
28
29#ifdef DUK_USE_PACKED_TVAL
30/* ======================================================================== */
31
32/*
33 * Packed 8-byte representation
34 */
35
36/* sanity */
37#if !defined(DUK_USE_PACKED_TVAL_POSSIBLE)
38#error packed representation not supported
39#endif
40
41/* use duk_double_union as duk_tval directly */
42typedef union duk_double_union duk_tval;
43
44/* tags */
45#define DUK_TAG_NORMALIZED_NAN 0x7ff8UL /* the NaN variant we use */
46/* avoid tag 0xfff0, no risk of confusion with negative infinity */
47#if defined(DUK_USE_FASTINT)
48#define DUK_TAG_FASTINT 0xfff1UL /* embed: integer value */
49#endif
50#define DUK_TAG_UNDEFINED 0xfff2UL /* embed: 0 or 1 (normal or unused) */
51#define DUK_TAG_NULL 0xfff3UL /* embed: nothing */
52#define DUK_TAG_BOOLEAN 0xfff4UL /* embed: 0 or 1 (false or true) */
53/* DUK_TAG_NUMBER would logically go here, but it has multiple 'tags' */
54#define DUK_TAG_POINTER 0xfff5UL /* embed: void ptr */
55#define DUK_TAG_LIGHTFUNC 0xfff6UL /* embed: func ptr */
56#define DUK_TAG_STRING 0xfff7UL /* embed: duk_hstring ptr */
57#define DUK_TAG_OBJECT 0xfff8UL /* embed: duk_hobject ptr */
58#define DUK_TAG_BUFFER 0xfff9UL /* embed: duk_hbuffer ptr */
59
60/* for convenience */
61#define DUK_XTAG_UNDEFINED_ACTUAL 0xfff20000UL
62#define DUK_XTAG_UNDEFINED_UNUSED 0xfff20001UL
63#define DUK_XTAG_NULL 0xfff30000UL
64#define DUK_XTAG_BOOLEAN_FALSE 0xfff40000UL
65#define DUK_XTAG_BOOLEAN_TRUE 0xfff40001UL
66
67/* two casts to avoid gcc warning: "warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]" */
68#ifdef DUK_USE_64BIT_OPS
69#ifdef DUK_USE_DOUBLE_ME
70#define DUK__TVAL_SET_TAGGEDPOINTER(v,h,tag) do { \
71 (v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 16) | (((duk_uint64_t) (duk_uint32_t) (h)) << 32); \
72 } while (0)
73#else
74#define DUK__TVAL_SET_TAGGEDPOINTER(v,h,tag) do { \
75 (v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 48) | ((duk_uint64_t) (duk_uint32_t) (h)); \
76 } while (0)
77#endif
78#else /* DUK_USE_64BIT_OPS */
79#define DUK__TVAL_SET_TAGGEDPOINTER(v,h,tag) do { \
80 (v)->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) (tag)) << 16; \
81 (v)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (h); \
82 } while (0)
83#endif /* DUK_USE_64BIT_OPS */
84
85#ifdef DUK_USE_64BIT_OPS
86/* Double casting for pointer to avoid gcc warning (cast from pointer to integer of different size) */
87#ifdef DUK_USE_DOUBLE_ME
88#define DUK__TVAL_SET_LIGHTFUNC(v,fp,flags) do { \
89 (v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 16) | \
90 ((duk_uint64_t) (flags)) | \
91 (((duk_uint64_t) (duk_uint32_t) (fp)) << 32); \
92 } while (0)
93#else
94#define DUK__TVAL_SET_LIGHTFUNC(v,fp,flags) do { \
95 (v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 48) | \
96 (((duk_uint64_t) (flags)) << 32) | \
97 ((duk_uint64_t) (duk_uint32_t) (fp)); \
98 } while (0)
99#endif
100#else /* DUK_USE_64BIT_OPS */
101#define DUK__TVAL_SET_LIGHTFUNC(v,fp,flags) do { \
102 (v)->ui[DUK_DBL_IDX_UI0] = (((duk_uint32_t) DUK_TAG_LIGHTFUNC) << 16) | ((duk_uint32_t) (flags)); \
103 (v)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (fp); \
104 } while (0)
105#endif /* DUK_USE_64BIT_OPS */
106
107#if defined(DUK_USE_FASTINT)
108/* Note: masking is done for 'i' to deal with negative numbers correctly */
109#ifdef DUK_USE_DOUBLE_ME
110#define DUK__TVAL_SET_FASTINT(v,i) do { \
111 (v)->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16 | (((duk_uint32_t) ((i) >> 32)) & 0x0000ffffUL); \
112 (v)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \
113 } while (0)
114#define DUK__TVAL_SET_FASTINT_U32(v,i) do { \
115 (v)->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16; \
116 (v)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \
117 } while (0)
118#else
119#define DUK__TVAL_SET_FASTINT(v,i) do { \
120 (v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (((duk_uint64_t) (i)) & 0x0000ffffffffffffULL); \
121 } while (0)
122#define DUK__TVAL_SET_FASTINT_U32(v,i) do { \
123 (v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (duk_uint64_t) (i); \
124 } while (0)
125#endif
126
127#define DUK__TVAL_SET_FASTINT_I32(v,i) do { \
128 duk_int64_t duk__tmp = (duk_int64_t) (i); \
129 DUK_TVAL_SET_FASTINT((v), duk__tmp); \
130 } while (0)
131
132/* XXX: clumsy sign extend and masking of 16 topmost bits */
133#ifdef DUK_USE_DOUBLE_ME
134#define DUK__TVAL_GET_FASTINT(v) (((duk_int64_t) ((((duk_uint64_t) (v)->ui[DUK_DBL_IDX_UI0]) << 32) | ((duk_uint64_t) (v)->ui[DUK_DBL_IDX_UI1]))) << 16 >> 16)
135#else
136#define DUK__TVAL_GET_FASTINT(v) ((((duk_int64_t) (v)->ull[DUK_DBL_IDX_ULL0]) << 16) >> 16)
137#endif
138#define DUK__TVAL_GET_FASTINT_U32(v) ((v)->ui[DUK_DBL_IDX_UI1])
139#define DUK__TVAL_GET_FASTINT_I32(v) ((duk_int32_t) (v)->ui[DUK_DBL_IDX_UI1])
140#endif /* DUK_USE_FASTINT */
141
142#define DUK_TVAL_SET_UNDEFINED_ACTUAL(v) DUK_DBLUNION_SET_HIGH32((v), DUK_XTAG_UNDEFINED_ACTUAL)
143#define DUK_TVAL_SET_UNDEFINED_UNUSED(v) DUK_DBLUNION_SET_HIGH32((v), DUK_XTAG_UNDEFINED_UNUSED)
144
145/* Note: 16-bit initializer suffices (unlike for undefined/boolean) */
146#define DUK_TVAL_SET_NULL(v) do { \
147 (v)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_NULL; \
148 } while (0)
149
150#define DUK_TVAL_SET_BOOLEAN(v,val) DUK_DBLUNION_SET_HIGH32((v), (((duk_uint32_t) DUK_TAG_BOOLEAN) << 16) | ((duk_uint32_t) (val)))
151
152#define DUK_TVAL_SET_NAN(v) DUK_DBLUNION_SET_NAN_FULL((v))
153
154/* Assumes that caller has normalized NaNs, otherwise trouble ahead. */
155#if defined(DUK_USE_FASTINT)
156#define DUK_TVAL_SET_DOUBLE(v,d) do { \
157 duk_double_t duk__dblval; \
158 duk__dblval = (d); \
159 DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \
160 DUK_DBLUNION_SET_DOUBLE((v), duk__dblval); \
161 } while (0)
162#define DUK_TVAL_SET_FASTINT(v,i) DUK__TVAL_SET_FASTINT((v), (i))
163#define DUK_TVAL_SET_FASTINT_I32(v,i) DUK__TVAL_SET_FASTINT_I32((v), (i))
164#define DUK_TVAL_SET_FASTINT_U32(v,i) DUK__TVAL_SET_FASTINT_U32((v), (i))
165#define DUK_TVAL_SET_NUMBER_CHKFAST(v,d) duk_tval_set_number_chkfast((v), (d))
166#define DUK_TVAL_SET_NUMBER(v,d) DUK_TVAL_SET_DOUBLE((v), (d))
167#define DUK_TVAL_CHKFAST_INPLACE(v) do { \
168 duk_tval *duk__tv; \
169 duk_double_t duk__d; \
170 duk__tv = (v); \
171 if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
172 duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
173 DUK_TVAL_SET_NUMBER_CHKFAST(duk__tv, duk__d); \
174 } \
175 } while (0)
176#else
177#define DUK_TVAL_SET_DOUBLE(v,d) do { \
178 duk_double_t duk__dblval; \
179 duk__dblval = (d); \
180 DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \
181 DUK_DBLUNION_SET_DOUBLE((v), duk__dblval); \
182 } while (0)
183#define DUK_TVAL_SET_NUMBER_CHKFAST(v,d) DUK_TVAL_SET_DOUBLE((v), (d))
184#define DUK_TVAL_SET_NUMBER(v,d) DUK_TVAL_SET_DOUBLE((v), (d))
185#define DUK_TVAL_CHKFAST_INPLACE(v) do { } while (0)
186#endif
187
188#define DUK_TVAL_SET_LIGHTFUNC(v,fp,flags) DUK__TVAL_SET_LIGHTFUNC((v), (fp), (flags))
189#define DUK_TVAL_SET_STRING(v,h) DUK__TVAL_SET_TAGGEDPOINTER((v), (h), DUK_TAG_STRING)
190#define DUK_TVAL_SET_OBJECT(v,h) DUK__TVAL_SET_TAGGEDPOINTER((v), (h), DUK_TAG_OBJECT)
191#define DUK_TVAL_SET_BUFFER(v,h) DUK__TVAL_SET_TAGGEDPOINTER((v), (h), DUK_TAG_BUFFER)
192#define DUK_TVAL_SET_POINTER(v,p) DUK__TVAL_SET_TAGGEDPOINTER((v), (p), DUK_TAG_POINTER)
193
194#define DUK_TVAL_SET_TVAL(v,x) do { *(v) = *(x); } while (0)
195
196/* getters */
197#define DUK_TVAL_GET_BOOLEAN(v) ((int) (v)->us[DUK_DBL_IDX_US1])
198#if defined(DUK_USE_FASTINT)
199#define DUK_TVAL_GET_DOUBLE(v) ((v)->d)
200#define DUK_TVAL_GET_FASTINT(v) DUK__TVAL_GET_FASTINT((v))
201#define DUK_TVAL_GET_FASTINT_U32(v) DUK__TVAL_GET_FASTINT_U32((v))
202#define DUK_TVAL_GET_FASTINT_I32(v) DUK__TVAL_GET_FASTINT_I32((v))
203#define DUK_TVAL_GET_NUMBER(v) duk_tval_get_number_packed((v))
204#else
205#define DUK_TVAL_GET_NUMBER(v) ((v)->d)
206#define DUK_TVAL_GET_DOUBLE(v) ((v)->d)
207#endif
208#define DUK_TVAL_GET_LIGHTFUNC(v,out_fp,out_flags) do { \
209 (out_flags) = (v)->ui[DUK_DBL_IDX_UI0] & 0xffffUL; \
210 (out_fp) = (duk_c_function) (v)->ui[DUK_DBL_IDX_UI1]; \
211 } while (0)
212#define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(v) ((duk_c_function) ((v)->ui[DUK_DBL_IDX_UI1]))
213#define DUK_TVAL_GET_LIGHTFUNC_FLAGS(v) (((int) (v)->ui[DUK_DBL_IDX_UI0]) & 0xffffUL)
214#define DUK_TVAL_GET_STRING(v) ((duk_hstring *) (v)->vp[DUK_DBL_IDX_VP1])
215#define DUK_TVAL_GET_OBJECT(v) ((duk_hobject *) (v)->vp[DUK_DBL_IDX_VP1])
216#define DUK_TVAL_GET_BUFFER(v) ((duk_hbuffer *) (v)->vp[DUK_DBL_IDX_VP1])
217#define DUK_TVAL_GET_POINTER(v) ((void *) (v)->vp[DUK_DBL_IDX_VP1])
218#define DUK_TVAL_GET_HEAPHDR(v) ((duk_heaphdr *) (v)->vp[DUK_DBL_IDX_VP1])
219
220/* decoding */
221#define DUK_TVAL_GET_TAG(v) ((duk_small_uint_t) (v)->us[DUK_DBL_IDX_US0])
222
223#define DUK_TVAL_IS_UNDEFINED(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_UNDEFINED)
224#define DUK_TVAL_IS_UNDEFINED_ACTUAL(v) ((v)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_UNDEFINED_ACTUAL)
225#define DUK_TVAL_IS_UNDEFINED_UNUSED(v) ((v)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_UNDEFINED_UNUSED)
226#define DUK_TVAL_IS_NULL(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_NULL)
227#define DUK_TVAL_IS_BOOLEAN(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_BOOLEAN)
228#define DUK_TVAL_IS_BOOLEAN_TRUE(v) ((v)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_TRUE)
229#define DUK_TVAL_IS_BOOLEAN_FALSE(v) ((v)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_FALSE)
230#define DUK_TVAL_IS_LIGHTFUNC(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_LIGHTFUNC)
231#define DUK_TVAL_IS_STRING(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_STRING)
232#define DUK_TVAL_IS_OBJECT(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_OBJECT)
233#define DUK_TVAL_IS_BUFFER(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_BUFFER)
234#define DUK_TVAL_IS_POINTER(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_POINTER)
235#if defined(DUK_USE_FASTINT)
236/* 0xfff0 is -Infinity */
237#define DUK_TVAL_IS_DOUBLE(v) (DUK_TVAL_GET_TAG((v)) <= 0xfff0UL)
238#define DUK_TVAL_IS_FASTINT(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_FASTINT)
239#define DUK_TVAL_IS_NUMBER(v) (DUK_TVAL_GET_TAG((v)) <= 0xfff1UL)
240#else
241#define DUK_TVAL_IS_NUMBER(v) (DUK_TVAL_GET_TAG((v)) <= 0xfff0UL)
242#define DUK_TVAL_IS_DOUBLE(v) DUK_TVAL_IS_NUMBER((v))
243#endif
244
245#define DUK_TVAL_IS_HEAP_ALLOCATED(v) (DUK_TVAL_GET_TAG((v)) >= DUK_TAG_STRING)
246
247#if defined(DUK_USE_FASTINT)
248DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_packed(duk_tval *tv);
249#endif
250
251#else /* DUK_USE_PACKED_TVAL */
252/* ======================================================================== */
253
254/*
255 * Portable 12-byte representation
256 */
257
258/* Note: not initializing all bytes is normally not an issue: Duktape won't
259 * read or use the uninitialized bytes so valgrind won't issue warnings.
260 * In some special cases a harmless valgrind warning may be issued though.
261 * For example, the DumpHeap debugger command writes out a compiled function's
262 * 'data' area as is, including any uninitialized bytes, which causes a
263 * valgrind warning.
264 */
265
266typedef struct duk_tval_struct duk_tval;
267
268struct duk_tval_struct {
269 duk_small_uint_t t;
270 duk_small_uint_t v_extra;
271 union {
272 duk_double_t d;
273 duk_small_int_t i;
274#if defined(DUK_USE_FASTINT)
275 duk_int64_t fi; /* if present, forces 16-byte duk_tval */
276#endif
277 void *voidptr;
278 duk_hstring *hstring;
279 duk_hobject *hobject;
280 duk_hcompiledfunction *hcompiledfunction;
281 duk_hnativefunction *hnativefunction;
282 duk_hthread *hthread;
283 duk_hbuffer *hbuffer;
284 duk_heaphdr *heaphdr;
285 duk_c_function lightfunc;
286 } v;
287};
288
289#define DUK__TAG_NUMBER 0 /* not exposed */
290#if defined(DUK_USE_FASTINT)
291#define DUK_TAG_FASTINT 1
292#endif
293#define DUK_TAG_UNDEFINED 2
294#define DUK_TAG_NULL 3
295#define DUK_TAG_BOOLEAN 4
296#define DUK_TAG_POINTER 5
297#define DUK_TAG_LIGHTFUNC 6
298#define DUK_TAG_STRING 7
299#define DUK_TAG_OBJECT 8
300#define DUK_TAG_BUFFER 9
301
302/* DUK__TAG_NUMBER is intentionally first, as it is the default clause in code
303 * to support the 8-byte representation. Further, it is a non-heap-allocated
304 * type so it should come before DUK_TAG_STRING. Finally, it should not break
305 * the tag value ranges covered by case-clauses in a switch-case.
306 */
307
308/* setters */
309#define DUK_TVAL_SET_UNDEFINED_ACTUAL(tv) do { \
310 (tv)->t = DUK_TAG_UNDEFINED; \
311 (tv)->v.i = 0; \
312 } while (0)
313
314#define DUK_TVAL_SET_UNDEFINED_UNUSED(tv) do { \
315 (tv)->t = DUK_TAG_UNDEFINED; \
316 (tv)->v.i = 1; \
317 } while (0)
318
319#define DUK_TVAL_SET_NULL(tv) do { \
320 (tv)->t = DUK_TAG_NULL; \
321 } while (0)
322
323#define DUK_TVAL_SET_BOOLEAN(tv,val) do { \
324 (tv)->t = DUK_TAG_BOOLEAN; \
325 (tv)->v.i = (val); \
326 } while (0)
327
328#if defined(DUK_USE_FASTINT)
329#define DUK_TVAL_SET_DOUBLE(tv,val) do { \
330 (tv)->t = DUK__TAG_NUMBER; \
331 (tv)->v.d = (val); \
332 } while (0)
333#define DUK_TVAL_SET_FASTINT(tv,val) do { \
334 (tv)->t = DUK_TAG_FASTINT; \
335 (tv)->v.fi = (val); \
336 } while (0)
337#define DUK_TVAL_SET_FASTINT_U32(tv,val) do { \
338 (tv)->t = DUK_TAG_FASTINT; \
339 (tv)->v.fi = (duk_int64_t) (val); \
340 } while (0)
341#define DUK_TVAL_SET_FASTINT_I32(tv,val) do { \
342 (tv)->t = DUK_TAG_FASTINT; \
343 (tv)->v.fi = (duk_int64_t) (val); \
344 } while (0)
345#define DUK_TVAL_SET_NUMBER_CHKFAST(tv,d) \
346 duk_tval_set_number_chkfast((tv), (d))
347#define DUK_TVAL_SET_NUMBER(tv,val) \
348 DUK_TVAL_SET_DOUBLE((tv), (val))
349#define DUK_TVAL_CHKFAST_INPLACE(v) do { \
350 duk_tval *duk__tv; \
351 duk_double_t duk__d; \
352 duk__tv = (v); \
353 if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
354 duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
355 DUK_TVAL_SET_NUMBER_CHKFAST(duk__tv, duk__d); \
356 } \
357 } while (0)
358#else
359#define DUK_TVAL_SET_NUMBER(tv,val) do { \
360 (tv)->t = DUK__TAG_NUMBER; \
361 (tv)->v.d = (val); \
362 } while (0)
363#define DUK_TVAL_SET_NUMBER_CHKFAST(tv,d) \
364 DUK_TVAL_SET_NUMBER((tv), (d))
365#define DUK_TVAL_SET_DOUBLE(v,d) \
366 DUK_TVAL_SET_NUMBER((tv), (d))
367#define DUK_TVAL_CHKFAST_INPLACE(v) do { } while (0)
368#endif /* DUK_USE_FASTINT */
369
370#define DUK_TVAL_SET_POINTER(tv,hptr) do { \
371 (tv)->t = DUK_TAG_POINTER; \
372 (tv)->v.voidptr = (hptr); \
373 } while (0)
374
375#define DUK_TVAL_SET_LIGHTFUNC(tv,fp,flags) do { \
376 (tv)->t = DUK_TAG_LIGHTFUNC; \
377 (tv)->v_extra = (flags); \
378 (tv)->v.lightfunc = (duk_c_function) (fp); \
379 } while (0)
380
381#define DUK_TVAL_SET_STRING(tv,hptr) do { \
382 (tv)->t = DUK_TAG_STRING; \
383 (tv)->v.hstring = (hptr); \
384 } while (0)
385
386#define DUK_TVAL_SET_OBJECT(tv,hptr) do { \
387 (tv)->t = DUK_TAG_OBJECT; \
388 (tv)->v.hobject = (hptr); \
389 } while (0)
390
391#define DUK_TVAL_SET_BUFFER(tv,hptr) do { \
392 (tv)->t = DUK_TAG_BUFFER; \
393 (tv)->v.hbuffer = (hptr); \
394 } while (0)
395
396#define DUK_TVAL_SET_NAN(tv) do { \
397 /* in non-packed representation we don't care about which NaN is used */ \
398 (tv)->t = DUK__TAG_NUMBER; \
399 (tv)->v.d = DUK_DOUBLE_NAN; \
400 } while (0)
401
402#define DUK_TVAL_SET_TVAL(v,x) do { *(v) = *(x); } while (0)
403
404/* getters */
405#define DUK_TVAL_GET_BOOLEAN(tv) ((tv)->v.i)
406#if defined(DUK_USE_FASTINT)
407#define DUK_TVAL_GET_DOUBLE(tv) ((tv)->v.d)
408#define DUK_TVAL_GET_FASTINT(tv) ((tv)->v.fi)
409#define DUK_TVAL_GET_FASTINT_U32(tv) ((duk_uint32_t) ((tv)->v.fi))
410#define DUK_TVAL_GET_FASTINT_I32(tv) ((duk_int32_t) ((tv)->v.fi))
411#if 0
412#define DUK_TVAL_GET_NUMBER(tv) (DUK_TVAL_IS_FASTINT((tv)) ? \
413 (duk_double_t) DUK_TVAL_GET_FASTINT((tv)) : \
414 DUK_TVAL_GET_DOUBLE((tv)))
415#define DUK_TVAL_GET_NUMBER(tv) duk_tval_get_number_unpacked((tv))
416#else
417/* This seems reasonable overall. */
418#define DUK_TVAL_GET_NUMBER(tv) (DUK_TVAL_IS_FASTINT((tv)) ? \
419 duk_tval_get_number_unpacked_fastint((tv)) : \
420 DUK_TVAL_GET_DOUBLE((tv)))
421#endif
422#else
423#define DUK_TVAL_GET_NUMBER(tv) ((tv)->v.d)
424#define DUK_TVAL_GET_DOUBLE(tv) ((tv)->v.d)
425#endif /* DUK_USE_FASTINT */
426#define DUK_TVAL_GET_POINTER(tv) ((tv)->v.voidptr)
427#define DUK_TVAL_GET_LIGHTFUNC(tv,out_fp,out_flags) do { \
428 (out_flags) = (duk_uint32_t) (tv)->v_extra; \
429 (out_fp) = (tv)->v.lightfunc; \
430 } while (0)
431#define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv) ((tv)->v.lightfunc)
432#define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv) ((duk_uint32_t) ((tv)->v_extra))
433#define DUK_TVAL_GET_STRING(tv) ((tv)->v.hstring)
434#define DUK_TVAL_GET_OBJECT(tv) ((tv)->v.hobject)
435#define DUK_TVAL_GET_BUFFER(tv) ((tv)->v.hbuffer)
436#define DUK_TVAL_GET_HEAPHDR(tv) ((tv)->v.heaphdr)
437
438/* decoding */
439#define DUK_TVAL_GET_TAG(tv) ((tv)->t)
440#define DUK_TVAL_IS_UNDEFINED(tv) ((tv)->t == DUK_TAG_UNDEFINED)
441#define DUK_TVAL_IS_UNDEFINED_ACTUAL(tv) (((tv)->t == DUK_TAG_UNDEFINED) && ((tv)->v.i == 0))
442#define DUK_TVAL_IS_UNDEFINED_UNUSED(tv) (((tv)->t == DUK_TAG_UNDEFINED) && ((tv)->v.i != 0))
443#define DUK_TVAL_IS_NULL(tv) ((tv)->t == DUK_TAG_NULL)
444#define DUK_TVAL_IS_BOOLEAN(tv) ((tv)->t == DUK_TAG_BOOLEAN)
445#define DUK_TVAL_IS_BOOLEAN_TRUE(tv) (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i != 0))
446#define DUK_TVAL_IS_BOOLEAN_FALSE(tv) (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i == 0))
447#if defined(DUK_USE_FASTINT)
448#define DUK_TVAL_IS_DOUBLE(tv) ((tv)->t == DUK__TAG_NUMBER)
449#define DUK_TVAL_IS_FASTINT(tv) ((tv)->t == DUK_TAG_FASTINT)
450#define DUK_TVAL_IS_NUMBER(tv) ((tv)->t == DUK__TAG_NUMBER || \
451 (tv)->t == DUK_TAG_FASTINT)
452#else
453#define DUK_TVAL_IS_NUMBER(tv) ((tv)->t == DUK__TAG_NUMBER)
454#define DUK_TVAL_IS_DOUBLE(v) DUK_TVAL_IS_NUMBER((v))
455#endif /* DUK_USE_FASTINT */
456#define DUK_TVAL_IS_POINTER(tv) ((tv)->t == DUK_TAG_POINTER)
457#define DUK_TVAL_IS_LIGHTFUNC(tv) ((tv)->t == DUK_TAG_LIGHTFUNC)
458#define DUK_TVAL_IS_STRING(tv) ((tv)->t == DUK_TAG_STRING)
459#define DUK_TVAL_IS_OBJECT(tv) ((tv)->t == DUK_TAG_OBJECT)
460#define DUK_TVAL_IS_BUFFER(tv) ((tv)->t == DUK_TAG_BUFFER)
461
462#define DUK_TVAL_IS_HEAP_ALLOCATED(tv) ((tv)->t >= DUK_TAG_STRING)
463
464#if defined(DUK_USE_FASTINT)
465#if 0
466DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked(duk_tval *tv);
467#endif
468DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv);
469#endif
470
471#endif /* DUK_USE_PACKED_TVAL */
472
473/*
474 * Convenience (independent of representation)
475 */
476
477#define DUK_TVAL_SET_BOOLEAN_TRUE(v) DUK_TVAL_SET_BOOLEAN(v, 1)
478#define DUK_TVAL_SET_BOOLEAN_FALSE(v) DUK_TVAL_SET_BOOLEAN(v, 0)
479
480/* Lightfunc flags packing and unpacking. */
481/* Sign extend: 0x0000##00 -> 0x##000000 -> sign extend to 0xssssss## */
482#define DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags) \
483 ((((duk_int32_t) (lf_flags)) << 16) >> 24)
484#define DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags) \
485 (((lf_flags) >> 4) & 0x0f)
486#define DUK_LFUNC_FLAGS_GET_NARGS(lf_flags) \
487 ((lf_flags) & 0x0f)
488#define DUK_LFUNC_FLAGS_PACK(magic,length,nargs) \
489 (((magic) & 0xff) << 8) | ((length) << 4) | (nargs)
490
491#define DUK_LFUNC_NARGS_VARARGS 0x0f /* varargs marker */
492#define DUK_LFUNC_NARGS_MIN 0x00
493#define DUK_LFUNC_NARGS_MAX 0x0e /* max, excl. varargs marker */
494#define DUK_LFUNC_LENGTH_MIN 0x00
495#define DUK_LFUNC_LENGTH_MAX 0x0f
496#define DUK_LFUNC_MAGIC_MIN (-0x80)
497#define DUK_LFUNC_MAGIC_MAX 0x7f
498
499/* fastint constants etc */
500#if defined(DUK_USE_FASTINT)
501#define DUK_FASTINT_MIN (-0x800000000000LL)
502#define DUK_FASTINT_MAX 0x7fffffffffffLL
503#define DUK_FASTINT_BITS 48
504
505DUK_INTERNAL_DECL void duk_tval_set_number_chkfast(duk_tval *tv, duk_double_t x);
506#endif
507
508#endif /* DUK_TVAL_H_INCLUDED */