2727
2828#include < limits.h>
2929#include < string.h> // memcpy
30+
31+ #include < algorithm>
3032#include < vector>
3133
3234// When creating strings >= this length v8's gc spins up and consumes
@@ -269,39 +271,6 @@ static size_t hex_decode(char* buf,
269271}
270272
271273
272- bool StringBytes::GetExternalParts (Local<Value> val,
273- const char ** data,
274- size_t * len) {
275- if (Buffer::HasInstance (val)) {
276- *data = Buffer::Data (val);
277- *len = Buffer::Length (val);
278- return true ;
279- }
280-
281- if (!val->IsString ())
282- return false ;
283-
284- Local<String> str = val.As <String>();
285-
286- if (str->IsExternalOneByte ()) {
287- const String::ExternalOneByteStringResource* ext;
288- ext = str->GetExternalOneByteStringResource ();
289- *data = ext->data ();
290- *len = ext->length ();
291- return true ;
292-
293- } else if (str->IsExternal ()) {
294- const String::ExternalStringResource* ext;
295- ext = str->GetExternalStringResource ();
296- *data = reinterpret_cast <const char *>(ext->data ());
297- *len = ext->length () * sizeof (*ext->data ());
298- return true ;
299- }
300-
301- return false ;
302- }
303-
304-
305274size_t StringBytes::WriteUCS2 (char * buf,
306275 size_t buflen,
307276 Local<String> str,
@@ -351,32 +320,31 @@ size_t StringBytes::Write(Isolate* isolate,
351320 enum encoding encoding,
352321 int * chars_written) {
353322 HandleScope scope (isolate);
354- const char * data = nullptr ;
355- size_t nbytes = 0 ;
356- const bool is_extern = GetExternalParts (val, &data, &nbytes);
357- const size_t external_nbytes = nbytes;
323+ size_t nbytes;
324+ int nchars;
325+
326+ if (chars_written == nullptr )
327+ chars_written = &nchars;
358328
359329 CHECK (val->IsString () == true );
360330 Local<String> str = val.As <String>();
361331
362- if (nbytes > buflen)
363- nbytes = buflen;
364-
365332 int flags = String::HINT_MANY_WRITES_EXPECTED |
366333 String::NO_NULL_TERMINATION |
367334 String::REPLACE_INVALID_UTF8;
368335
369336 switch (encoding) {
370337 case ASCII:
371338 case LATIN1:
372- if (is_extern && str->IsOneByte ()) {
373- memcpy (buf, data, nbytes);
339+ if (str->IsExternalOneByte ()) {
340+ auto ext = str->GetExternalOneByteStringResource ();
341+ nbytes = std::min (buflen, ext->length ());
342+ memcpy (buf, ext->data (), nbytes);
374343 } else {
375344 uint8_t * const dst = reinterpret_cast <uint8_t *>(buf);
376345 nbytes = str->WriteOneByte (dst, 0 , buflen, flags);
377346 }
378- if (chars_written != nullptr )
379- *chars_written = nbytes;
347+ *chars_written = nbytes;
380348 break ;
381349
382350 case BUFFER:
@@ -387,14 +355,8 @@ size_t StringBytes::Write(Isolate* isolate,
387355 case UCS2: {
388356 size_t nchars;
389357
390- if (is_extern && !str->IsOneByte ()) {
391- memcpy (buf, data, nbytes);
392- nchars = nbytes / sizeof (uint16_t );
393- } else {
394- nbytes = WriteUCS2 (buf, buflen, str, flags, &nchars);
395- }
396- if (chars_written != nullptr )
397- *chars_written = nchars;
358+ nbytes = WriteUCS2 (buf, buflen, str, flags, &nchars);
359+ *chars_written = static_cast <int >(nchars);
398360
399361 // Node's "ucs2" encoding wants LE character data stored in
400362 // the Buffer, so we need to reorder on BE platforms. See
@@ -407,27 +369,25 @@ size_t StringBytes::Write(Isolate* isolate,
407369 }
408370
409371 case BASE64:
410- if (is_extern) {
411- nbytes = base64_decode (buf, buflen, data, external_nbytes);
372+ if (str->IsExternalOneByte ()) {
373+ auto ext = str->GetExternalOneByteStringResource ();
374+ nbytes = base64_decode (buf, buflen, ext->data (), ext->length ());
412375 } else {
413376 String::Value value (str);
414377 nbytes = base64_decode (buf, buflen, *value, value.length ());
415378 }
416- if (chars_written != nullptr ) {
417- *chars_written = nbytes;
418- }
379+ *chars_written = nbytes;
419380 break ;
420381
421382 case HEX:
422- if (is_extern) {
423- nbytes = hex_decode (buf, buflen, data, external_nbytes);
383+ if (str->IsExternalOneByte ()) {
384+ auto ext = str->GetExternalOneByteStringResource ();
385+ nbytes = hex_decode (buf, buflen, ext->data (), ext->length ());
424386 } else {
425387 String::Value value (str);
426388 nbytes = hex_decode (buf, buflen, *value, value.length ());
427389 }
428- if (chars_written != nullptr ) {
429- *chars_written = nbytes;
430- }
390+ *chars_written = nbytes;
431391 break ;
432392
433393 default :
@@ -504,49 +464,34 @@ size_t StringBytes::Size(Isolate* isolate,
504464 Local<Value> val,
505465 enum encoding encoding) {
506466 HandleScope scope (isolate);
507- size_t data_size = 0 ;
508- bool is_buffer = Buffer::HasInstance (val);
509467
510- if (is_buffer && (encoding == BUFFER || encoding == LATIN1))
468+ if (Buffer::HasInstance (val) && (encoding == BUFFER || encoding == LATIN1))
511469 return Buffer::Length (val);
512470
513- const char * data;
514- if (GetExternalParts (val, &data, &data_size))
515- return data_size;
516-
517471 Local<String> str = val->ToString (isolate);
518472
519473 switch (encoding) {
520474 case ASCII:
521475 case LATIN1:
522- data_size = str->Length ();
523- break ;
476+ return str->Length ();
524477
525478 case BUFFER:
526479 case UTF8:
527- data_size = str->Utf8Length ();
528- break ;
480+ return str->Utf8Length ();
529481
530482 case UCS2:
531- data_size = str->Length () * sizeof (uint16_t );
532- break ;
483+ return str->Length () * sizeof (uint16_t );
533484
534485 case BASE64: {
535486 String::Value value (str);
536- data_size = base64_decoded_size (*value, value.length ());
537- break ;
487+ return base64_decoded_size (*value, value.length ());
538488 }
539489
540490 case HEX:
541- data_size = str->Length () / 2 ;
542- break ;
543-
544- default :
545- CHECK (0 && " unknown encoding" );
546- break ;
491+ return str->Length () / 2 ;
547492 }
548493
549- return data_size ;
494+ UNREACHABLE () ;
550495}
551496
552497
0 commit comments