2 * Heap string representation.
4 * Strings are byte sequences ordinarily stored in extended UTF-8 format,
5 * allowing values larger than the official UTF-8 range (used internally)
6 * and also allowing UTF-8 encoding of surrogate pairs (CESU-8 format).
7 * Strings may also be invalid UTF-8 altogether which is the case e.g. with
8 * strings used as internal property names and raw buffers converted to
9 * strings. In such cases the 'clen' field contains an inaccurate value.
11 * Ecmascript requires support for 32-bit long strings. However, since each
12 * 16-bit codepoint can take 3 bytes in CESU-8, this representation can only
13 * support about 1.4G codepoint long strings in extreme cases. This is not
14 * really a practical issue.
17 #ifndef DUK_HSTRING_H_INCLUDED
18 #define DUK_HSTRING_H_INCLUDED
20 /* Impose a maximum string length for now. Restricted artificially to
21 * ensure adding a heap header length won't overflow size_t. The limit
22 * should be synchronized with DUK_HBUFFER_MAX_BYTELEN.
24 * E5.1 makes provisions to support strings longer than 4G characters.
25 * This limit should be eliminated on 64-bit platforms (and increased
26 * closer to maximum support on 32-bit platforms).
29 #if defined(DUK_USE_STRLEN16)
30 #define DUK_HSTRING_MAX_BYTELEN (0x0000ffffUL)
32 #define DUK_HSTRING_MAX_BYTELEN (0x7fffffffUL)
35 /* XXX: could add flags for "is valid CESU-8" (Ecmascript compatible strings),
36 * "is valid UTF-8", "is valid extended UTF-8" (internal strings are not,
37 * regexp bytecode is), and "contains non-BMP characters". These are not
41 #define DUK_HSTRING_FLAG_ARRIDX DUK_HEAPHDR_USER_FLAG(0) /* string is a valid array index */
42 #define DUK_HSTRING_FLAG_INTERNAL DUK_HEAPHDR_USER_FLAG(1) /* string is internal */
43 #define DUK_HSTRING_FLAG_RESERVED_WORD DUK_HEAPHDR_USER_FLAG(2) /* string is a reserved word (non-strict) */
44 #define DUK_HSTRING_FLAG_STRICT_RESERVED_WORD DUK_HEAPHDR_USER_FLAG(3) /* string is a reserved word (strict) */
45 #define DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS DUK_HEAPHDR_USER_FLAG(4) /* string is 'eval' or 'arguments' */
46 #define DUK_HSTRING_FLAG_EXTDATA DUK_HEAPHDR_USER_FLAG(5) /* string data is external (duk_hstring_external) */
48 #define DUK_HSTRING_HAS_ARRIDX(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
49 #define DUK_HSTRING_HAS_INTERNAL(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_INTERNAL)
50 #define DUK_HSTRING_HAS_RESERVED_WORD(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
51 #define DUK_HSTRING_HAS_STRICT_RESERVED_WORD(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
52 #define DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
53 #define DUK_HSTRING_HAS_EXTDATA(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
55 #define DUK_HSTRING_SET_ARRIDX(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
56 #define DUK_HSTRING_SET_INTERNAL(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_INTERNAL)
57 #define DUK_HSTRING_SET_RESERVED_WORD(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
58 #define DUK_HSTRING_SET_STRICT_RESERVED_WORD(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
59 #define DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
60 #define DUK_HSTRING_SET_EXTDATA(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
62 #define DUK_HSTRING_CLEAR_ARRIDX(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
63 #define DUK_HSTRING_CLEAR_INTERNAL(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_INTERNAL)
64 #define DUK_HSTRING_CLEAR_RESERVED_WORD(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
65 #define DUK_HSTRING_CLEAR_STRICT_RESERVED_WORD(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
66 #define DUK_HSTRING_CLEAR_EVAL_OR_ARGUMENTS(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
67 #define DUK_HSTRING_CLEAR_EXTDATA(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
69 #define DUK_HSTRING_IS_ASCII(x) (DUK_HSTRING_GET_BYTELEN((x)) == DUK_HSTRING_GET_CHARLEN((x)))
70 #define DUK_HSTRING_IS_EMPTY(x) (DUK_HSTRING_GET_BYTELEN((x)) == 0)
72 #if defined(DUK_USE_STRHASH16)
73 #define DUK_HSTRING_GET_HASH(x) ((x)->hdr.h_flags >> 16)
74 #define DUK_HSTRING_SET_HASH(x,v) do { \
75 (x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | ((v) << 16); \
78 #define DUK_HSTRING_GET_HASH(x) ((x)->hash)
79 #define DUK_HSTRING_SET_HASH(x,v) do { \
84 #if defined(DUK_USE_STRLEN16)
85 #define DUK_HSTRING_GET_BYTELEN(x) ((x)->blen16)
86 #define DUK_HSTRING_SET_BYTELEN(x,v) do { \
89 #define DUK_HSTRING_GET_CHARLEN(x) ((x)->clen16)
90 #define DUK_HSTRING_SET_CHARLEN(x,v) do { \
94 #define DUK_HSTRING_GET_BYTELEN(x) ((x)->blen)
95 #define DUK_HSTRING_SET_BYTELEN(x,v) do { \
98 #define DUK_HSTRING_GET_CHARLEN(x) ((x)->clen)
99 #define DUK_HSTRING_SET_CHARLEN(x,v) do { \
104 #if defined(DUK_USE_HSTRING_EXTDATA)
105 #define DUK_HSTRING_GET_EXTDATA(x) \
107 #define DUK_HSTRING_GET_DATA(x) \
108 (DUK_HSTRING_HAS_EXTDATA((x)) ? \
109 DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) (x)) : ((const duk_uint8_t *) ((x) + 1)))
111 #define DUK_HSTRING_GET_DATA(x) \
112 ((const duk_uint8_t *) ((x) + 1))
115 #define DUK_HSTRING_GET_DATA_END(x) \
116 (DUK_HSTRING_GET_DATA((x)) + (x)->blen)
118 /* marker value; in E5 2^32-1 is not a valid array index (2^32-2 is highest valid) */
119 #define DUK_HSTRING_NO_ARRAY_INDEX (0xffffffffUL)
121 /* get array index related to string (or return DUK_HSTRING_NO_ARRAY_INDEX);
122 * avoids helper call if string has no array index value.
124 #define DUK_HSTRING_GET_ARRIDX_FAST(h) \
125 (DUK_HSTRING_HAS_ARRIDX((h)) ? duk_js_to_arrayindex_string_helper((h)) : DUK_HSTRING_NO_ARRAY_INDEX)
127 /* slower but more compact variant */
128 #define DUK_HSTRING_GET_ARRIDX_SLOW(h) \
129 (duk_js_to_arrayindex_string_helper((h)))
136 /* Smaller heaphdr than for other objects, because strings are held
137 * in string intern table which requires no link pointers. Much of
138 * the 32-bit flags field is unused by flags, so we can stuff a 16-bit
141 duk_heaphdr_string hdr
;
143 /* Note: we could try to stuff a partial hash (e.g. 16 bits) into the
144 * shared heap header. Good hashing needs more hash bits though.
148 #if defined(DUK_USE_STRHASH16)
149 /* If 16-bit hash is in use, stuff it into duk_heaphdr_string flags. */
154 /* length in bytes (not counting NUL term) */
155 #if defined(DUK_USE_STRLEN16)
161 /* length in codepoints (must be E5 compatible) */
162 #if defined(DUK_USE_STRLEN16)
169 * String value of 'blen+1' bytes follows (+1 for NUL termination
170 * convenience for C API). No alignment needs to be guaranteed
171 * for strings, but fields above should guarantee alignment-by-4
172 * (but not alignment-by-8).
176 /* The external string struct is defined even when the feature is inactive. */
177 struct duk_hstring_external
{
181 * For an external string, the NUL-terminated string data is stored
182 * externally. The user must guarantee that data behind this pointer
183 * doesn't change while it's used.
186 const duk_uint8_t
*extdata
;
193 DUK_INTERNAL_DECL duk_ucodepoint_t
duk_hstring_char_code_at_raw(duk_hthread
*thr
, duk_hstring
*h
, duk_uint_t pos
);
195 #endif /* DUK_HSTRING_H_INCLUDED */