]> git.proxmox.com Git - ceph.git/blob - ceph/src/civetweb/src/third_party/duktape-1.3.0/src-separate/duk_hbuffer.h
bump version to 12.2.12-pve1
[ceph.git] / ceph / src / civetweb / src / third_party / duktape-1.3.0 / src-separate / duk_hbuffer.h
1 /*
2 * Heap buffer representation.
3 *
4 * Heap allocated user data buffer which is either:
5 *
6 * 1. A fixed size buffer (data follows header statically)
7 * 2. A dynamic size buffer (data pointer follows header)
8 *
9 * The data pointer for a variable size buffer of zero size may be NULL.
10 */
11
12 #ifndef DUK_HBUFFER_H_INCLUDED
13 #define DUK_HBUFFER_H_INCLUDED
14
15 /*
16 * Flags
17 *
18 * Fixed buffer: 0
19 * Dynamic buffer: DUK_HBUFFER_FLAG_DYNAMIC
20 * External buffer: DUK_HBUFFER_FLAG_DYNAMIC | DUK_HBUFFER_FLAG_EXTERNAL
21 */
22
23 #define DUK_HBUFFER_FLAG_DYNAMIC DUK_HEAPHDR_USER_FLAG(0) /* buffer is behind a pointer, dynamic or external */
24 #define DUK_HBUFFER_FLAG_EXTERNAL DUK_HEAPHDR_USER_FLAG(1) /* buffer pointer is to an externally allocated buffer */
25
26 #define DUK_HBUFFER_HAS_DYNAMIC(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
27 #define DUK_HBUFFER_HAS_EXTERNAL(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
28
29 #define DUK_HBUFFER_SET_DYNAMIC(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
30 #define DUK_HBUFFER_SET_EXTERNAL(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
31
32 #define DUK_HBUFFER_CLEAR_DYNAMIC(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
33 #define DUK_HBUFFER_CLEAR_EXTERNAL(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
34
35 /*
36 * Misc defines
37 */
38
39 /* Impose a maximum buffer length for now. Restricted artificially to
40 * ensure resize computations or adding a heap header length won't
41 * overflow size_t and that a signed duk_int_t can hold a buffer
42 * length. The limit should be synchronized with DUK_HSTRING_MAX_BYTELEN.
43 */
44
45 #if defined(DUK_USE_BUFLEN16)
46 #define DUK_HBUFFER_MAX_BYTELEN (0x0000ffffUL)
47 #else
48 /* Intentionally not 0x7fffffffUL; at least JSON code expects that
49 * 2*len + 2 fits in 32 bits.
50 */
51 #define DUK_HBUFFER_MAX_BYTELEN (0x7ffffffeUL)
52 #endif
53
54 /*
55 * Field access
56 */
57
58 /* Get/set the current user visible size, without accounting for a dynamic
59 * buffer's "spare" (= usable size).
60 */
61 #if defined(DUK_USE_BUFLEN16)
62 /* size stored in duk_heaphdr unused flag bits */
63 #define DUK_HBUFFER_GET_SIZE(x) ((x)->hdr.h_flags >> 16)
64 #define DUK_HBUFFER_SET_SIZE(x,v) do { \
65 (x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | ((v) << 16); \
66 } while (0)
67 #define DUK_HBUFFER_ADD_SIZE(x,dv) do { \
68 (x)->hdr.h_flags += ((dv) << 16); \
69 } while (0)
70 #define DUK_HBUFFER_SUB_SIZE(x,dv) do { \
71 (x)->hdr.h_flags -= ((dv) << 16); \
72 } while (0)
73 #else
74 #define DUK_HBUFFER_GET_SIZE(x) (((duk_hbuffer *) (x))->size)
75 #define DUK_HBUFFER_SET_SIZE(x,v) do { \
76 ((duk_hbuffer *) (x))->size = (v); \
77 } while (0)
78 #define DUK_HBUFFER_ADD_SIZE(x,dv) do { \
79 (x)->size += (dv); \
80 } while (0)
81 #define DUK_HBUFFER_SUB_SIZE(x,dv) do { \
82 (x)->size -= (dv); \
83 } while (0)
84 #endif
85
86 #define DUK_HBUFFER_FIXED_GET_SIZE(x) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
87 #define DUK_HBUFFER_FIXED_SET_SIZE(x,v) DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x))
88
89 #define DUK_HBUFFER_DYNAMIC_GET_SIZE(x) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
90 #define DUK_HBUFFER_DYNAMIC_SET_SIZE(x,v) DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))
91 #define DUK_HBUFFER_DYNAMIC_ADD_SIZE(x,dv) DUK_HBUFFER_ADD_SIZE((duk_hbuffer *) (x), (dv))
92 #define DUK_HBUFFER_DYNAMIC_SUB_SIZE(x,dv) DUK_HBUFFER_SUB_SIZE((duk_hbuffer *) (x), (dv))
93
94 #define DUK_HBUFFER_EXTERNAL_GET_SIZE(x) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
95 #define DUK_HBUFFER_EXTERNAL_SET_SIZE(x,v) DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))
96
97 #define DUK_HBUFFER_FIXED_GET_DATA_PTR(heap,x) ((duk_uint8_t *) (((duk_hbuffer_fixed *) (x)) + 1))
98
99 #if defined(DUK_USE_HEAPPTR16)
100 #define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x) \
101 ((void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (x))->h_extra16))
102 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v) do { \
103 ((duk_heaphdr *) (x))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
104 } while (0)
105 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x) do { \
106 ((duk_heaphdr *) (x))->h_extra16 = 0; /* assume 0 <=> NULL */ \
107 } while (0)
108 #else
109 #define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x) ((x)->curr_alloc)
110 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v) do { \
111 (x)->curr_alloc = (void *) (v); \
112 } while (0)
113 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x) do { \
114 (x)->curr_alloc = (void *) NULL; \
115 } while (0)
116 #endif
117
118 /* No pointer compression because pointer is potentially outside of
119 * Duktape heap.
120 */
121 #if defined(DUK_USE_HEAPPTR16)
122 #define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap,x) \
123 ((void *) (x)->curr_alloc)
124 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap,x,v) do { \
125 (x)->curr_alloc = (void *) (v); \
126 } while (0)
127 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap,x) do { \
128 (x)->curr_alloc = (void *) NULL; \
129 } while (0)
130 #else
131 #define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap,x) \
132 ((void *) (x)->curr_alloc)
133 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap,x,v) do { \
134 (x)->curr_alloc = (void *) (v); \
135 } while (0)
136 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap,x) do { \
137 (x)->curr_alloc = (void *) NULL; \
138 } while (0)
139 #endif
140
141 /* Get a pointer to the current buffer contents (matching current allocation
142 * size). May be NULL for zero size dynamic/external buffer.
143 */
144 #if defined(DUK_USE_HEAPPTR16)
145 #define DUK_HBUFFER_GET_DATA_PTR(heap,x) ( \
146 DUK_HBUFFER_HAS_DYNAMIC((x)) ? \
147 ( \
148 DUK_HBUFFER_HAS_EXTERNAL((x)) ? \
149 DUK_HBUFFER_EXTERNAL_GET_DATA_PTR((heap), (duk_hbuffer_external *) (x)) : \
150 DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) \
151 ) : \
152 DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (x)) \
153 )
154 #else
155 /* Without heap pointer compression duk_hbuffer_dynamic and duk_hbuffer_external
156 * have the same layout so checking for fixed vs. dynamic (or external) is enough.
157 */
158 #define DUK_HBUFFER_GET_DATA_PTR(heap,x) ( \
159 DUK_HBUFFER_HAS_DYNAMIC((x)) ? \
160 DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) : \
161 DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (x)) \
162 )
163 #endif
164
165 /*
166 * Structs
167 */
168
169 /* Shared prefix for all buffer types. */
170 struct duk_hbuffer {
171 duk_heaphdr hdr;
172
173 /* It's not strictly necessary to track the current size, but
174 * it is useful for writing robust native code.
175 */
176
177 /* Current size (not counting a dynamic buffer's "spare"). */
178 #if defined(DUK_USE_BUFLEN16)
179 /* Stored in duk_heaphdr unused flags. */
180 #else
181 duk_size_t size;
182 #endif
183
184 /*
185 * Data following the header depends on the DUK_HBUFFER_FLAG_DYNAMIC
186 * flag.
187 *
188 * If the flag is clear (the buffer is a fixed size one), the buffer
189 * data follows the header directly, consisting of 'size' bytes.
190 *
191 * If the flag is set, the actual buffer is allocated separately, and
192 * a few control fields follow the header. Specifically:
193 *
194 * - a "void *" pointing to the current allocation
195 * - a duk_size_t indicating the full allocated size (always >= 'size')
196 *
197 * If DUK_HBUFFER_FLAG_EXTERNAL is set, the buffer has been allocated
198 * by user code, so that Duktape won't be able to resize it and won't
199 * free it. This allows buffers to point to e.g. an externally
200 * allocated structure such as a frame buffer.
201 *
202 * Unlike strings, no terminator byte (NUL) is guaranteed after the
203 * data. This would be convenient, but would pad aligned user buffers
204 * unnecessarily upwards in size. For instance, if user code requested
205 * a 64-byte dynamic buffer, 65 bytes would actually be allocated which
206 * would then potentially round upwards to perhaps 68 or 72 bytes.
207 */
208 };
209
210 /* Fixed buffer; data follows struct, with proper alignment guaranteed by
211 * struct size.
212 */
213 #if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
214 #pragma pack(push, 8)
215 #endif
216 struct duk_hbuffer_fixed {
217 /* A union is used here as a portable struct size / alignment trick:
218 * by adding a 32-bit or a 64-bit (unused) union member, the size of
219 * the struct is effectively forced to be a multiple of 4 or 8 bytes
220 * (respectively) without increasing the size of the struct unless
221 * necessary.
222 */
223 union {
224 struct {
225 duk_heaphdr hdr;
226 #if defined(DUK_USE_BUFLEN16)
227 /* Stored in duk_heaphdr unused flags. */
228 #else
229 duk_size_t size;
230 #endif
231 } s;
232 #if (DUK_USE_ALIGN_BY == 4)
233 duk_uint32_t dummy_for_align4;
234 #elif (DUK_USE_ALIGN_BY == 8)
235 duk_double_t dummy_for_align8;
236 #elif (DUK_USE_ALIGN_BY == 1)
237 /* no extra padding */
238 #else
239 #error invalid DUK_USE_ALIGN_BY
240 #endif
241 } u;
242
243 /*
244 * Data follows the struct header. The struct size is padded by the
245 * compiler based on the struct members. This guarantees that the
246 * buffer data will be aligned-by-4 but not necessarily aligned-by-8.
247 *
248 * On platforms where alignment does not matter, the struct padding
249 * could be removed (if there is any). On platforms where alignment
250 * by 8 is required, the struct size must be forced to be a multiple
251 * of 8 by some means. Without it, some user code may break, and also
252 * Duktape itself breaks (e.g. the compiler stores duk_tvals in a
253 * dynamic buffer).
254 */
255 }
256 #if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_GCC_ATTR)
257 __attribute__ ((aligned (8)))
258 #elif (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_CLANG_ATTR)
259 __attribute__ ((aligned (8)))
260 #endif
261 ;
262 #if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
263 #pragma pack(pop)
264 #endif
265
266 /* Dynamic buffer with 'curr_alloc' pointing to a dynamic area allocated using
267 * heap allocation primitives. Also used for external buffers when low memory
268 * options are not used.
269 */
270 struct duk_hbuffer_dynamic {
271 duk_heaphdr hdr;
272
273 #if defined(DUK_USE_BUFLEN16)
274 /* Stored in duk_heaphdr unused flags. */
275 #else
276 duk_size_t size;
277 #endif
278
279 #if defined(DUK_USE_HEAPPTR16)
280 /* Stored in duk_heaphdr h_extra16. */
281 #else
282 void *curr_alloc; /* may be NULL if alloc_size == 0 */
283 #endif
284
285 /*
286 * Allocation size for 'curr_alloc' is alloc_size. There is no
287 * automatic NUL terminator for buffers (see above for rationale).
288 *
289 * 'curr_alloc' is explicitly allocated with heap allocation
290 * primitives and will thus always have alignment suitable for
291 * e.g. duk_tval and an IEEE double.
292 */
293 };
294
295 /* External buffer with 'curr_alloc' managed by user code and pointing to an
296 * arbitrary address. When heap pointer compression is not used, this struct
297 * has the same layout as duk_hbuffer_dynamic.
298 */
299 struct duk_hbuffer_external {
300 duk_heaphdr hdr;
301
302 #if defined(DUK_USE_BUFLEN16)
303 /* Stored in duk_heaphdr unused flags. */
304 #else
305 duk_size_t size;
306 #endif
307
308 /* Cannot be compressed as a heap pointer because may point to
309 * an arbitrary address.
310 */
311 void *curr_alloc; /* may be NULL if alloc_size == 0 */
312 };
313
314 /*
315 * Prototypes
316 */
317
318 DUK_INTERNAL_DECL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_small_uint_t flags, void **out_bufdata);
319 DUK_INTERNAL_DECL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud); /* indirect allocs */
320
321 /* dynamic buffer ops */
322 DUK_INTERNAL_DECL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size);
323 DUK_INTERNAL_DECL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf);
324
325 #endif /* DUK_HBUFFER_H_INCLUDED */