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 */
}
Example #2
0
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);
}
Example #3
0
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;
}
Example #4
0
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 */
}
Example #5
0
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;
}
Example #6
0
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;
}
Example #8
0
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;
}