]> git.proxmox.com Git - ceph.git/blob - ceph/src/civetweb/src/third_party/duktape-1.3.0/src-separate/duk_hbuffer_ops.c
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / civetweb / src / third_party / duktape-1.3.0 / src-separate / duk_hbuffer_ops.c
1 /*
2 * duk_hbuffer operations such as resizing and inserting/appending data to
3 * a dynamic buffer.
4 *
5 * Append operations append to the end of the buffer and they are relatively
6 * efficient: the buffer is grown with a "spare" part relative to the buffer
7 * size to minimize reallocations. Insert operations need to move existing
8 * data forward in the buffer with memmove() and are not very efficient.
9 * They are used e.g. by the regexp compiler to "backpatch" regexp bytecode.
10 */
11
12 #include "duk_internal.h"
13
14 /*
15 * Resizing
16 */
17
18 DUK_INTERNAL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size) {
19 void *res;
20 duk_size_t prev_size;
21
22 DUK_ASSERT(thr != NULL);
23 DUK_ASSERT(buf != NULL);
24 DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
25 DUK_ASSERT(!DUK_HBUFFER_HAS_EXTERNAL(buf));
26
27 /*
28 * Maximum size check
29 */
30
31 if (new_size > DUK_HBUFFER_MAX_BYTELEN) {
32 DUK_ERROR(thr, DUK_ERR_RANGE_ERROR, "buffer too long");
33 }
34
35 /*
36 * Note: use indirect realloc variant just in case mark-and-sweep
37 * (finalizers) might resize this same buffer during garbage
38 * collection.
39 */
40
41 res = DUK_REALLOC_INDIRECT(thr->heap, duk_hbuffer_get_dynalloc_ptr, (void *) buf, new_size);
42 if (res != NULL || new_size == 0) {
43 /* 'res' may be NULL if new allocation size is 0. */
44
45 DUK_DDD(DUK_DDDPRINT("resized dynamic buffer %p:%ld -> %p:%ld",
46 (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, buf),
47 (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(buf),
48 (void *) res,
49 (long) new_size));
50
51 /*
52 * The entire allocated buffer area, regardless of actual used
53 * size, is kept zeroed in resizes for simplicity. If the buffer
54 * is grown, zero the new part.
55 */
56
57 prev_size = DUK_HBUFFER_DYNAMIC_GET_SIZE(buf);
58 if (new_size > prev_size) {
59 DUK_ASSERT(new_size - prev_size > 0);
60 #ifdef DUK_USE_ZERO_BUFFER_DATA
61 DUK_MEMZERO((void *) ((char *) res + prev_size),
62 (duk_size_t) (new_size - prev_size));
63 #endif
64 }
65
66 DUK_HBUFFER_DYNAMIC_SET_SIZE(buf, new_size);
67 DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(thr->heap, buf, res);
68 } else {
69 DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, "buffer resize failed: %ld to %ld",
70 (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(buf),
71 (long) new_size);
72 }
73
74 DUK_ASSERT(res != NULL || new_size == 0);
75 }
76
77 DUK_INTERNAL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf) {
78 DUK_ASSERT(thr != NULL);
79 DUK_ASSERT(buf != NULL);
80 DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
81 DUK_ASSERT(!DUK_HBUFFER_HAS_EXTERNAL(buf));
82
83 duk_hbuffer_resize(thr, buf, 0);
84 }