void duk_hbuffer_remove_slice(duk_hthread *thr, duk_hbuffer_dynamic *buf, size_t offset, size_t length) { char *p; size_t end_offset; DUK_ASSERT(thr != NULL); DUK_ASSERT(buf != NULL); DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf)); DUK_ASSERT(offset >= 0); /* always true */ DUK_ASSERT(offset <= DUK_HBUFFER_GET_SIZE(buf)); /* allow equality */ DUK_ASSERT(length >= 0); /* always true */ DUK_ASSERT(offset + length <= DUK_HBUFFER_GET_SIZE(buf)); /* allow equality */ if (length == 0) { return; } p = (char *) DUK_HBUFFER_DYNAMIC_GET_CURR_DATA_PTR(buf); end_offset = offset + length; if (end_offset < DUK_HBUFFER_GET_SIZE(buf)) { /* not strictly from end of buffer; need to shuffle data */ DUK_MEMMOVE(p + offset, p + end_offset, DUK_HBUFFER_GET_SIZE(buf) - end_offset); /* always > 0 */ } DUK_MEMSET(p + DUK_HBUFFER_GET_SIZE(buf) - length, 0, length); /* always > 0 */ buf->size -= length; /* Note: no shrink check, intentional */ }
void *duk_resize_buffer(duk_context *ctx, duk_idx_t index, duk_size_t new_size) { duk_hthread *thr = (duk_hthread *) ctx; duk_hbuffer_dynamic *h; DUK_ASSERT(ctx != NULL); h = (duk_hbuffer_dynamic *) duk_require_hbuffer(ctx, index); DUK_ASSERT(h != NULL); if (!DUK_HBUFFER_HAS_DYNAMIC(h)) { DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "buffer is not dynamic"); } /* maximum size check is handled by callee */ duk_hbuffer_resize(thr, h, new_size, new_size); /* snug */ return DUK_HBUFFER_DYNAMIC_GET_CURR_DATA_PTR(h); }
void duk_hbuffer_insert_bytes(duk_hthread *thr, duk_hbuffer_dynamic *buf, size_t offset, duk_uint8_t *data, size_t length) { char *p; /* XXX: allow inserts with offset > curr_size? i.e., insert zeroes automatically? */ DUK_ASSERT(thr != NULL); DUK_ASSERT(buf != NULL); DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf)); DUK_ASSERT_DISABLE(offset >= 0); /* unsigned, so always true */ DUK_ASSERT(offset <= DUK_HBUFFER_GET_SIZE(buf)); /* equality is OK (= append) */ DUK_ASSERT(data != NULL); DUK_ASSERT_DISABLE(length >= 0); /* unsigned, so always true */ if (length == 0) { return; } if (DUK_HBUFFER_DYNAMIC_GET_SPARE_SIZE(buf) < length) { duk_hbuffer_resize(thr, buf, DUK_HBUFFER_GET_SIZE(buf), duk__add_spare(DUK_HBUFFER_GET_SIZE(buf) + length)); } DUK_ASSERT(DUK_HBUFFER_DYNAMIC_GET_SPARE_SIZE(buf) >= length); p = (char *) DUK_HBUFFER_DYNAMIC_GET_CURR_DATA_PTR(buf); if (offset < DUK_HBUFFER_GET_SIZE(buf)) { /* not an append */ DUK_ASSERT(DUK_HBUFFER_GET_SIZE(buf) - offset > 0); /* not a zero byte memmove */ DUK_MEMMOVE((void *) (p + offset + length), (void *) (p + offset), DUK_HBUFFER_GET_SIZE(buf) - offset); } DUK_MEMCPY((void *) (p + offset), data, length); buf->size += length; }
void duk_hbuffer_remove_slice(duk_hthread *thr, duk_hbuffer_dynamic *buf, size_t offset, size_t length) { char *p; size_t end_offset; DUK_UNREF(thr); DUK_ASSERT(thr != NULL); DUK_ASSERT(buf != NULL); DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf)); DUK_ASSERT_DISABLE(offset >= 0); /* always true */ DUK_ASSERT(offset <= DUK_HBUFFER_GET_SIZE(buf)); /* allow equality */ DUK_ASSERT_DISABLE(length >= 0); /* always true */ DUK_ASSERT(offset + length <= DUK_HBUFFER_GET_SIZE(buf)); /* allow equality */ if (length == 0) { return; } p = (char *) DUK_HBUFFER_DYNAMIC_GET_CURR_DATA_PTR(buf); end_offset = offset + length; if (end_offset < DUK_HBUFFER_GET_SIZE(buf)) { /* not strictly from end of buffer; need to shuffle data */ DUK_MEMMOVE(p + offset, p + end_offset, DUK_HBUFFER_GET_SIZE(buf) - end_offset); /* always > 0 */ } /* Here we want to zero data even with automatic buffer zeroing * disabled as we depend on this internally too. */ DUK_MEMZERO(p + DUK_HBUFFER_GET_SIZE(buf) - length, length); /* always > 0 */ buf->size -= length; /* Note: no shrink check, intentional */ }
size_t duk_hbuffer_append_xutf8(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_uint32_t codepoint) { duk_uint8_t tmp[DUK_UNICODE_MAX_XUTF8_LENGTH]; size_t len; DUK_ASSERT(thr != NULL); DUK_ASSERT(buf != NULL); DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf)); /* No range assertion for 'codepoint' */ if (codepoint < 0x80 && DUK_HBUFFER_DYNAMIC_GET_SPARE_SIZE(buf) > 0) { /* fast path: ASCII and there is spare */ duk_uint8_t *p = ((duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_CURR_DATA_PTR(buf)) + DUK_HBUFFER_GET_SIZE(buf); *p = (duk_uint8_t) codepoint; buf->size += 1; return 1; } /* FIXME: cp -> duk_codepoint_t */ len = (size_t) duk_unicode_encode_xutf8((duk_ucodepoint_t) codepoint, tmp); duk_hbuffer_insert_bytes(thr, buf, DUK_HBUFFER_GET_SIZE(buf), tmp, len); return len; }
void duk_to_fixed_buffer(duk_context *ctx, duk_idx_t index) { duk_hbuffer_dynamic *h_src; duk_uint8_t *data; duk_size_t size; index = duk_require_normalize_index(ctx, index); h_src = (duk_hbuffer_dynamic *) duk_require_hbuffer(ctx, index); DUK_ASSERT(h_src != NULL); if (!DUK_HBUFFER_HAS_DYNAMIC(h_src)) { return; } size = DUK_HBUFFER_GET_SIZE(h_src); data = (duk_uint8_t *) duk_push_fixed_buffer(ctx, size); if (size > 0U) { DUK_ASSERT(data != NULL); DUK_MEMCPY(data, DUK_HBUFFER_DYNAMIC_GET_CURR_DATA_PTR(h_src), size); } duk_replace(ctx, index); }
size_t duk_hbuffer_append_cesu8(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_uint32_t codepoint) { duk_uint8_t tmp[DUK_UNICODE_MAX_CESU8_LENGTH]; size_t len; DUK_ASSERT(thr != NULL); DUK_ASSERT(buf != NULL); DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf)); DUK_ASSERT(codepoint >= 0 && codepoint <= 0x10ffff); /* if not in this range, results are garbage (but no crash) */ if (codepoint < 0x80 && DUK_HBUFFER_DYNAMIC_GET_SPARE_SIZE(buf) > 0) { /* fast path: ASCII and there is spare */ duk_uint8_t *p = ((duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_CURR_DATA_PTR(buf)) + DUK_HBUFFER_GET_SIZE(buf); *p = (duk_uint8_t) codepoint; buf->size += 1; return 1; } /* FIXME: cp -> duk_codepoint_t */ len = (size_t) duk_unicode_encode_cesu8((duk_ucodepoint_t) codepoint, tmp); duk_hbuffer_insert_bytes(thr, buf, DUK_HBUFFER_GET_SIZE(buf), tmp, len); return len; }
void duk_hbuffer_insert_slice(duk_hthread *thr, duk_hbuffer_dynamic *buf, size_t dst_offset, size_t src_offset, size_t length) { char *p; size_t src_end_offset; /* source end (exclusive) in initial buffer */ size_t len; DUK_ASSERT(thr != NULL); DUK_ASSERT(buf != NULL); DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf)); DUK_ASSERT_DISABLE(dst_offset >= 0); /* always true */ DUK_ASSERT(dst_offset <= DUK_HBUFFER_GET_SIZE(buf)); /* allow equality */ DUK_ASSERT_DISABLE(src_offset >= 0); /* always true */ DUK_ASSERT(src_offset <= DUK_HBUFFER_GET_SIZE(buf)); /* allow equality */ DUK_ASSERT_DISABLE(length >= 0); /* always true */ DUK_ASSERT(src_offset + length <= DUK_HBUFFER_GET_SIZE(buf)); /* allow equality */ if (length == 0) { return; } if (DUK_HBUFFER_DYNAMIC_GET_SPARE_SIZE(buf) < length) { duk_hbuffer_resize(thr, buf, DUK_HBUFFER_GET_SIZE(buf), duk__add_spare(DUK_HBUFFER_GET_SIZE(buf) + length)); } DUK_ASSERT(DUK_HBUFFER_DYNAMIC_GET_SPARE_SIZE(buf) >= length); p = (char *) DUK_HBUFFER_DYNAMIC_GET_CURR_DATA_PTR(buf); /* * src_offset and dst_offset refer to the state of the buffer * before any changes are made. This must be taken into account * when moving data around; in particular, the source data may * "straddle" the dst_offset, so the insert may need to be handled * in two pieces. */ src_end_offset = src_offset + length; /* create a hole for the insert */ len = DUK_HBUFFER_GET_SIZE(buf) - dst_offset; if (len > 0) { DUK_MEMMOVE(p + dst_offset + length, p + dst_offset, len); } if (src_offset < dst_offset) { if (src_end_offset <= dst_offset) { /* entire source is before 'dst_offset' */ DUK_MEMCPY(p + dst_offset, p + src_offset, length); } else { /* part of the source is before 'dst_offset'; straddles */ len = dst_offset - src_offset; DUK_ASSERT(len >= 1 && len < length); DUK_ASSERT(length - len >= 1); DUK_MEMCPY(p + dst_offset, p + src_offset, len); DUK_MEMCPY(p + dst_offset + len, p + src_offset + length + len, /* take above memmove() into account */ length - len); } } else { /* entire source is after 'dst_offset' */ DUK_MEMCPY(p + dst_offset, p + src_offset + length, /* take above memmove() into account */ length); } buf->size += length; }