36 #define EXTERN_APEX 0xFBEE9 40 #define SB_MALLOC_FAILED_ERROR \ 41 v8::Exception::Error(OneByteString(isolate, "\"toString()\" failed")) 43 #define SB_STRING_TOO_LONG_ERROR \ 44 v8::Exception::Error(OneByteString(isolate, "\"toString()\" failed")) 46 #define SB_BUFFER_CREATION_ERROR \ 47 v8::Exception::Error(OneByteString(isolate, "\"toString()\" failed")) 49 #define SB_BUFFER_SIZE_EXCEEDED_ERROR \ 50 v8::Exception::Error(OneByteString(isolate, "\"toString()\" failed")) 54 using v8::HandleScope;
63 template <
typename ResourceType,
typename TypeName>
64 class ExternString:
public ResourceType {
66 ~ExternString()
override {
67 free(const_cast<TypeName*>(data_));
68 isolate()->AdjustAmountOfExternalAllocatedMemory(-byte_length());
71 const TypeName*
data()
const override {
75 size_t length()
const override {
79 int64_t byte_length()
const {
80 return length() *
sizeof(*
data());
83 static MaybeLocal<Value> NewFromCopy(Isolate* isolate,
86 Local<Value>* error) {
88 return String::Empty(isolate);
91 return NewSimpleFromCopy(isolate, data, length, error);
93 TypeName* new_data = node::UncheckedMalloc<TypeName>(length);
94 if (new_data ==
nullptr) {
96 return MaybeLocal<Value>();
98 memcpy(new_data, data, length *
sizeof(*new_data));
107 static MaybeLocal<Value>
New(Isolate* isolate,
110 Local<Value>* error) {
112 return String::Empty(isolate);
115 MaybeLocal<Value> str = NewSimpleFromCopy(isolate, data, length, error);
120 ExternString* h_str =
new ExternString<ResourceType, TypeName>(isolate,
123 MaybeLocal<Value> str = NewExternal(isolate, h_str);
124 isolate->AdjustAmountOfExternalAllocatedMemory(h_str->byte_length());
129 return MaybeLocal<Value>();
132 return str.ToLocalChecked();
135 inline Isolate* isolate()
const {
return isolate_; }
138 ExternString(Isolate* isolate,
const TypeName* data,
size_t length)
139 : isolate_(isolate), data_(data), length_(length) { }
140 static MaybeLocal<Value> NewExternal(Isolate* isolate,
141 ExternString* h_str);
144 static MaybeLocal<Value> NewSimpleFromCopy(Isolate* isolate,
145 const TypeName* data,
147 Local<Value>* error);
150 const TypeName* data_;
155 typedef ExternString<String::ExternalOneByteStringResource,
156 char> ExternOneByteString;
157 typedef ExternString<String::ExternalStringResource,
158 uint16_t> ExternTwoByteString;
162 MaybeLocal<Value> ExternOneByteString::NewExternal(
163 Isolate* isolate, ExternOneByteString* h_str) {
164 return String::NewExternalOneByte(isolate, h_str).FromMaybe(Local<Value>());
169 MaybeLocal<Value> ExternTwoByteString::NewExternal(
170 Isolate* isolate, ExternTwoByteString* h_str) {
171 return String::NewExternalTwoByte(isolate, h_str).FromMaybe(Local<Value>());
175 MaybeLocal<Value> ExternOneByteString::NewSimpleFromCopy(Isolate* isolate,
178 Local<Value>* error) {
179 MaybeLocal<String> str =
180 String::NewFromOneByte(isolate,
181 reinterpret_cast<const uint8_t*>(data),
182 v8::NewStringType::kNormal,
186 return MaybeLocal<Value>();
188 return str.ToLocalChecked();
193 MaybeLocal<Value> ExternTwoByteString::NewSimpleFromCopy(Isolate* isolate,
194 const uint16_t* data,
196 Local<Value>* error) {
197 MaybeLocal<String> str =
198 String::NewFromTwoByte(isolate,
200 v8::NewStringType::kNormal,
204 return MaybeLocal<Value>();
206 return str.ToLocalChecked();
213 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, -2, -1, -1,
214 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
215 -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63,
216 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
217 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
218 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63,
219 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
220 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
221 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
222 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
223 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
224 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
225 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
226 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
227 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
228 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
232 static const int8_t unhex_table[256] =
233 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
234 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
235 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
236 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
237 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
238 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
239 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
240 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
241 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
242 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
243 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
244 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
245 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
246 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
247 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
248 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
251 static inline unsigned unhex(uint8_t x) {
252 return unhex_table[x];
255 template <
typename TypeName>
256 static size_t hex_decode(
char*
buf,
259 const size_t srcLen) {
261 for (i = 0; i < len && i * 2 + 1 < srcLen; ++i) {
262 unsigned a = unhex(src[i * 2 + 0]);
263 unsigned b = unhex(src[i * 2 + 1]);
266 buf[i] = (a << 4) | b;
273 bool StringBytes::GetExternalParts(Local<Value> val,
282 if (!val->IsString())
285 Local<String> str = val.As<String>();
287 if (str->IsExternalOneByte()) {
288 const String::ExternalOneByteStringResource* ext;
289 ext = str->GetExternalOneByteStringResource();
291 *len = ext->length();
294 }
else if (str->IsExternal()) {
295 const String::ExternalStringResource* ext;
296 ext = str->GetExternalStringResource();
297 *data =
reinterpret_cast<const char*
>(ext->data());
298 *len = ext->length() *
sizeof(*ext->data());
306 size_t StringBytes::WriteUCS2(
char* buf,
310 size_t* chars_written) {
311 uint16_t*
const dst =
reinterpret_cast<uint16_t*
>(
buf);
313 size_t max_chars = (buflen /
sizeof(*dst));
315 size_t alignment =
reinterpret_cast<uintptr_t
>(dst) %
sizeof(*dst);
316 if (alignment == 0) {
317 nchars = str->Write(dst, 0, max_chars, flags);
318 *chars_written = nchars;
319 return nchars *
sizeof(*dst);
322 uint16_t* aligned_dst =
323 reinterpret_cast<uint16_t*
>(buf +
sizeof(*dst) - alignment);
324 CHECK_EQ(reinterpret_cast<uintptr_t>(aligned_dst) %
sizeof(*dst), 0);
327 nchars = str->Write(aligned_dst, 0, max_chars - 1, flags);
330 memmove(dst, aligned_dst, nchars *
sizeof(*dst));
334 if (nchars == max_chars - 1 && str->Write(&last, nchars, 1, flags) != 0) {
335 memcpy(buf + nchars *
sizeof(*dst), &last,
sizeof(last));
339 *chars_written = nchars;
340 return nchars *
sizeof(*dst);
344 size_t StringBytes::Write(Isolate* isolate,
349 int* chars_written) {
350 HandleScope scope(isolate);
351 const char* data =
nullptr;
353 const bool is_extern = GetExternalParts(val, &data, &nbytes);
354 const size_t external_nbytes = nbytes;
356 CHECK(val->IsString() ==
true);
357 Local<String> str = val.As<String>();
362 int flags = String::HINT_MANY_WRITES_EXPECTED |
363 String::NO_NULL_TERMINATION |
364 String::REPLACE_INVALID_UTF8;
369 if (is_extern && str->IsOneByte()) {
370 memcpy(buf, data, nbytes);
372 uint8_t*
const dst =
reinterpret_cast<uint8_t*
>(
buf);
373 nbytes = str->WriteOneByte(dst, 0, buflen, flags);
375 if (chars_written !=
nullptr)
376 *chars_written = nbytes;
381 nbytes = str->WriteUtf8(buf, buflen, chars_written, flags);
387 if (is_extern && !str->IsOneByte()) {
388 memcpy(buf, data, nbytes);
389 nchars = nbytes /
sizeof(uint16_t);
391 nbytes = WriteUCS2(buf, buflen, str, flags, &nchars);
393 if (chars_written !=
nullptr)
394 *chars_written = nchars;
401 SwapBytes16(buf, nbytes);
408 nbytes = base64_decode(buf, buflen, data, external_nbytes);
410 String::Value value(str);
411 nbytes = base64_decode(buf, buflen, *value, value.length());
413 if (chars_written !=
nullptr) {
414 *chars_written = nbytes;
420 nbytes = hex_decode(buf, buflen, data, external_nbytes);
422 String::Value value(str);
423 nbytes = hex_decode(buf, buflen, *value, value.length());
425 if (chars_written !=
nullptr) {
426 *chars_written = nbytes;
431 CHECK(0 &&
"unknown encoding");
439 bool StringBytes::IsValidString(Local<String>
string,
441 if (enc ==
HEX && string->Length() % 2 != 0)
451 size_t StringBytes::StorageSize(Isolate* isolate,
453 enum encoding encoding) {
454 HandleScope scope(isolate);
455 size_t data_size = 0;
458 if (is_buffer && (encoding ==
BUFFER || encoding ==
LATIN1)) {
462 Local<String> str = val->ToString(isolate);
467 data_size = str->Length();
475 data_size = 3 * str->Length();
479 data_size = str->Length() *
sizeof(uint16_t);
483 data_size = base64_decoded_size_fast(str->Length());
487 CHECK(str->Length() % 2 == 0 &&
"invalid hex string length");
488 data_size = str->Length() / 2;
492 CHECK(0 &&
"unknown encoding");
500 size_t StringBytes::Size(Isolate* isolate,
502 enum encoding encoding) {
503 HandleScope scope(isolate);
504 size_t data_size = 0;
507 if (is_buffer && (encoding ==
BUFFER || encoding ==
LATIN1))
511 if (GetExternalParts(val, &data, &data_size))
514 Local<String> str = val->ToString(isolate);
519 data_size = str->Length();
524 data_size = str->Utf8Length();
528 data_size = str->Length() *
sizeof(uint16_t);
532 String::Value value(str);
533 data_size = base64_decoded_size(*value, value.length());
538 data_size = str->Length() / 2;
542 CHECK(0 &&
"unknown encoding");
552 static bool contains_non_ascii_slow(
const char* buf,
size_t len) {
553 for (
size_t i = 0; i <
len; ++i) {
561 static bool contains_non_ascii(
const char* src,
size_t len) {
563 return contains_non_ascii_slow(src, len);
566 const unsigned bytes_per_word =
sizeof(uintptr_t);
567 const unsigned align_mask = bytes_per_word - 1;
568 const unsigned unaligned =
reinterpret_cast<uintptr_t
>(src) & align_mask;
571 const unsigned n = bytes_per_word - unaligned;
572 if (contains_non_ascii_slow(src, n))
579 #if defined(_WIN64) || defined(_LP64) 580 const uintptr_t mask = 0x8080808080808080ll;
582 const uintptr_t mask = 0x80808080l;
585 const uintptr_t* srcw =
reinterpret_cast<const uintptr_t*
>(src);
587 for (
size_t i = 0,
n = len / bytes_per_word; i <
n; ++i) {
592 const unsigned remainder = len & align_mask;
594 const size_t offset = len - remainder;
595 if (contains_non_ascii_slow(src + offset, remainder))
603 static void force_ascii_slow(
const char* src,
char* dst,
size_t len) {
604 for (
size_t i = 0; i <
len; ++i) {
605 dst[i] = src[i] & 0x7f;
610 static void force_ascii(
const char* src,
char* dst,
size_t len) {
612 force_ascii_slow(src, dst, len);
616 const unsigned bytes_per_word =
sizeof(uintptr_t);
617 const unsigned align_mask = bytes_per_word - 1;
618 const unsigned src_unalign =
reinterpret_cast<uintptr_t
>(src) & align_mask;
619 const unsigned dst_unalign =
reinterpret_cast<uintptr_t
>(dst) & align_mask;
621 if (src_unalign > 0) {
622 if (src_unalign == dst_unalign) {
623 const unsigned unalign = bytes_per_word - src_unalign;
624 force_ascii_slow(src, dst, unalign);
629 force_ascii_slow(src, dst, len);
634 #if defined(_WIN64) || defined(_LP64) 635 const uintptr_t mask = ~0x8080808080808080ll;
637 const uintptr_t mask = ~0x80808080l;
640 const uintptr_t* srcw =
reinterpret_cast<const uintptr_t*
>(src);
641 uintptr_t* dstw =
reinterpret_cast<uintptr_t*
>(dst);
643 for (
size_t i = 0,
n = len / bytes_per_word; i <
n; ++i) {
644 dstw[i] = srcw[i] & mask;
647 const unsigned remainder = len & align_mask;
649 const size_t offset = len - remainder;
650 force_ascii_slow(src + offset, dst + offset, remainder);
655 static size_t hex_encode(
const char* src,
size_t slen,
char* dst,
size_t dlen) {
657 CHECK(dlen >= slen * 2 &&
658 "not enough space provided for hex encode");
661 for (uint32_t i = 0, k = 0; k < dlen; i += 1, k += 2) {
662 static const char hex[] =
"0123456789abcdef";
663 uint8_t val =
static_cast<uint8_t
>(src[i]);
664 dst[k + 0] = hex[val >> 4];
665 dst[k + 1] = hex[val & 15];
672 #define CHECK_BUFLEN_IN_RANGE(len) \ 674 if ((len) > Buffer::kMaxLength) { \ 675 *error = SB_BUFFER_SIZE_EXCEEDED_ERROR; \ 676 return MaybeLocal<Value>(); \ 684 enum encoding encoding,
685 Local<Value>* error) {
686 CHECK_NE(encoding,
UCS2);
689 *error = Local<Value>();
690 if (!buflen && encoding !=
BUFFER) {
691 return String::Empty(isolate);
694 MaybeLocal<String> val;
700 if (maybe_buf.IsEmpty()) {
702 return MaybeLocal<Value>();
704 return maybe_buf.ToLocalChecked();
708 if (contains_non_ascii(buf, buflen)) {
709 char* out = node::UncheckedMalloc(buflen);
710 if (out ==
nullptr) {
712 return MaybeLocal<Value>();
714 force_ascii(buf, out, buflen);
717 return ExternOneByteString::NewFromCopy(isolate, buf, buflen, error);
721 val = String::NewFromUtf8(isolate,
723 v8::NewStringType::kNormal,
727 return MaybeLocal<Value>();
729 return val.ToLocalChecked();
732 return ExternOneByteString::NewFromCopy(isolate, buf, buflen, error);
735 size_t dlen = base64_encoded_size(buflen);
736 char* dst = node::UncheckedMalloc(dlen);
737 if (dst ==
nullptr) {
739 return MaybeLocal<Value>();
742 size_t written = base64_encode(buf, buflen, dst, dlen);
743 CHECK_EQ(written, dlen);
749 size_t dlen = buflen * 2;
750 char* dst = node::UncheckedMalloc(dlen);
751 if (dst ==
nullptr) {
753 return MaybeLocal<Value>();
755 size_t written = hex_encode(buf, buflen, dst, dlen);
756 CHECK_EQ(written, dlen);
762 CHECK(0 &&
"unknown encoding");
773 Local<Value>* error) {
775 *error = Local<Value>();
781 std::vector<uint16_t> dst;
783 dst.assign(buf, buf + buflen);
784 size_t nbytes = buflen *
sizeof(dst[0]);
785 SwapBytes16(reinterpret_cast<char*>(&dst[0]), nbytes);
789 return ExternTwoByteString::NewFromCopy(isolate, buf, buflen, error);
794 enum encoding encoding,
795 Local<Value>* error) {
796 const size_t len = strlen(buf);
797 MaybeLocal<Value> ret;
798 if (encoding ==
UCS2) {
803 const bool be = IsBigEndian();
806 std::vector<uint16_t> vec(len / 2);
807 for (
size_t i = 0, k = 0; i <
len; i += 2, k += 1) {
808 const uint8_t hi =
static_cast<uint8_t
>(buf[i + 0]);
809 const uint8_t lo =
static_cast<uint8_t
>(buf[i + 1]);
811 static_cast<uint16_t
>(hi) << 8 | lo
812 : static_cast<uint16_t>(lo) << 8 | hi;
815 static_cast< Local<Value>
>(String::Empty(isolate))
bool HasInstance(Local< Value > val)
#define SB_STRING_TOO_LONG_ERROR
union node::cares_wrap::@8::CaresAsyncData::@0 data
const int8_t unbase64_table[256]
size_t Length(Local< Value > val)
char * Data(Local< Value > val)
#define SB_BUFFER_CREATION_ERROR
MaybeLocal< Object > New(Isolate *isolate, Local< String > string, enum encoding enc)
#define SB_MALLOC_FAILED_ERROR
#define CHECK_BUFLEN_IN_RANGE(len)
NODE_DEPRECATED("Use ParseEncoding(isolate, ...)", inline enum encoding ParseEncoding(v8::Local< v8::Value > encoding_v, enum encoding default_encoding=LATIN1) { return ParseEncoding(v8::Isolate::GetCurrent(), encoding_v, default_encoding);}) NODE_EXTERN void FatalException(v8 NODE_DEPRECATED("Use FatalException(isolate, ...)", inline void FatalException(const v8::TryCatch &try_catch) { return FatalException(v8::Isolate::GetCurrent(), try_catch);}) NODE_EXTERN v8 NODE_EXTERN v8::Local< v8::Value > Encode(v8::Isolate *isolate, const uint16_t *buf, size_t len)
MaybeLocal< Object > Copy(Isolate *isolate, const char *data, size_t length)