2 * duk_hbuffer operations such as resizing and inserting/appending data to
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.
12 #include "duk_internal.h"
18 DUK_INTERNAL
void duk_hbuffer_resize(duk_hthread
*thr
, duk_hbuffer_dynamic
*buf
, duk_size_t new_size
) {
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
));
31 if (new_size
> DUK_HBUFFER_MAX_BYTELEN
) {
32 DUK_ERROR(thr
, DUK_ERR_RANGE_ERROR
, "buffer too long");
36 * Note: use indirect realloc variant just in case mark-and-sweep
37 * (finalizers) might resize this same buffer during garbage
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. */
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
),
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.
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
));
66 DUK_HBUFFER_DYNAMIC_SET_SIZE(buf
, new_size
);
67 DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(thr
->heap
, buf
, res
);
69 DUK_ERROR(thr
, DUK_ERR_ALLOC_ERROR
, "buffer resize failed: %ld to %ld",
70 (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(buf
),
74 DUK_ASSERT(res
!= NULL
|| new_size
== 0);
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
));
83 duk_hbuffer_resize(thr
, buf
, 0);