static duk_hstring *duk__alloc_init_hstring(duk_heap *heap, duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) { duk_hstring *res = NULL; duk_uint8_t *data; duk_size_t alloc_size; duk_uarridx_t dummy; /* NUL terminate for convenient C access */ alloc_size = (duk_size_t) (sizeof(duk_hstring) + blen + 1); res = (duk_hstring *) DUK_ALLOC(heap, alloc_size); if (!res) { goto error; } DUK_MEMZERO(res, sizeof(duk_hstring)); #ifdef DUK_USE_EXPLICIT_NULL_INIT DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr); #endif DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, 0); if (duk_js_to_arrayindex_raw_string(str, blen, &dummy)) { DUK_HSTRING_SET_ARRIDX(res); } /* All strings beginning with 0xff are treated as "internal", * even strings interned by the user. This allows user code to * create internal properties too, and makes behavior consistent * in case user code happens to use a string also used by Duktape * (such as string has already been interned and has the 'internal' * flag set). */ if (blen > 0 && str[0] == (duk_uint8_t) 0xff) { DUK_HSTRING_SET_INTERNAL(res); } res->hash = strhash; res->blen = blen; res->clen = (duk_uint32_t) duk_unicode_unvalidated_utf8_length(str, (duk_size_t) blen); /* clen <= blen */ data = (duk_uint8_t *) (res + 1); DUK_MEMCPY(data, str, blen); data[blen] = (duk_uint8_t) 0; DUK_DDD(DUK_DDDPRINT("interned string, hash=0x%08lx, blen=%ld, clen=%ld, has_arridx=%ld", (unsigned long) DUK_HSTRING_GET_HASH(res), (long) DUK_HSTRING_GET_BYTELEN(res), (long) DUK_HSTRING_GET_CHARLEN(res), (long) DUK_HSTRING_HAS_ARRIDX(res) ? 1 : 0)); return res; error: DUK_FREE(heap, res); return NULL; }
static duk_hstring *duk__alloc_init_hstring(duk_heap *heap, duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) { duk_hstring *res = NULL; duk_uint8_t *data; duk_uint32_t alloc_size; duk_uint32_t dummy; /* NUL terminate for convenient C access */ alloc_size = sizeof(duk_hstring) + blen + 1; res = (duk_hstring *) DUK_ALLOC(heap, alloc_size); if (!res) { goto error; } DUK_MEMZERO(res, sizeof(duk_hstring)); #ifdef DUK_USE_EXPLICIT_NULL_INIT DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr); #endif DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, 0); if (duk_js_to_arrayindex_raw_string(str, blen, &dummy)) { DUK_HSTRING_SET_ARRIDX(res); } res->hash = strhash; res->blen = blen; res->clen = (duk_uint32_t) duk_unicode_unvalidated_utf8_length(str, (duk_size_t) blen); /* clen <= blen */ data = (duk_uint8_t *) (res + 1); DUK_MEMCPY(data, str, blen); data[blen] = (duk_uint8_t) 0; DUK_DDD(DUK_DDDPRINT("interned string, hash=0x%08x, blen=%d, clen=%d, arridx=%d", DUK_HSTRING_GET_HASH(res), DUK_HSTRING_GET_BYTELEN(res), DUK_HSTRING_GET_CHARLEN(res), DUK_HSTRING_HAS_ARRIDX(res) ? 1 : 0)); return res; error: DUK_FREE(heap, res); return NULL; }
DUK_LOCAL duk_hstring *duk__alloc_init_hstring(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash, const duk_uint8_t *extdata) { duk_hstring *res = NULL; duk_uint8_t *data; duk_size_t alloc_size; duk_uarridx_t dummy; duk_uint32_t clen; #if defined(DUK_USE_STRLEN16) /* If blen <= 0xffffUL, clen is also guaranteed to be <= 0xffffUL. */ if (blen > 0xffffUL) { DUK_D(DUK_DPRINT("16-bit string blen/clen active and blen over 16 bits, reject intern")); return NULL; } #endif if (extdata) { alloc_size = (duk_size_t) sizeof(duk_hstring_external); res = (duk_hstring *) DUK_ALLOC(heap, alloc_size); if (!res) { goto alloc_error; } DUK_MEMZERO(res, sizeof(duk_hstring_external)); #ifdef DUK_USE_EXPLICIT_NULL_INIT DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr); #endif DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, DUK_HSTRING_FLAG_EXTDATA); ((duk_hstring_external *) res)->extdata = extdata; } else { /* NUL terminate for convenient C access */ alloc_size = (duk_size_t) (sizeof(duk_hstring) + blen + 1); res = (duk_hstring *) DUK_ALLOC(heap, alloc_size); if (!res) { goto alloc_error; } DUK_MEMZERO(res, sizeof(duk_hstring)); #ifdef DUK_USE_EXPLICIT_NULL_INIT DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr); #endif DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, 0); data = (duk_uint8_t *) (res + 1); DUK_MEMCPY(data, str, blen); data[blen] = (duk_uint8_t) 0; } if (duk_js_to_arrayindex_raw_string(str, blen, &dummy)) { DUK_HSTRING_SET_ARRIDX(res); } /* All strings beginning with 0xff are treated as "internal", * even strings interned by the user. This allows user code to * create internal properties too, and makes behavior consistent * in case user code happens to use a string also used by Duktape * (such as string has already been interned and has the 'internal' * flag set). */ if (blen > 0 && str[0] == (duk_uint8_t) 0xff) { DUK_HSTRING_SET_INTERNAL(res); } DUK_HSTRING_SET_HASH(res, strhash); DUK_HSTRING_SET_BYTELEN(res, blen); clen = (duk_uint32_t) duk_unicode_unvalidated_utf8_length(str, (duk_size_t) blen); DUK_ASSERT(clen <= blen); DUK_HSTRING_SET_CHARLEN(res, clen); DUK_DDD(DUK_DDDPRINT("interned string, hash=0x%08lx, blen=%ld, clen=%ld, has_arridx=%ld, has_extdata=%ld", (unsigned long) DUK_HSTRING_GET_HASH(res), (long) DUK_HSTRING_GET_BYTELEN(res), (long) DUK_HSTRING_GET_CHARLEN(res), (long) (DUK_HSTRING_HAS_ARRIDX(res) ? 1 : 0), (long) (DUK_HSTRING_HAS_EXTDATA(res) ? 1 : 0))); return res; alloc_error: DUK_FREE(heap, res); return NULL; }