Remove excessive copyright/license boilerplate
[platform/upstream/nodejs.git] / src / string_bytes.cc
1 #include "string_bytes.h"
2
3 #include "node.h"
4 #include "node_buffer.h"
5 #include "v8.h"
6
7 #include <limits.h>
8 #include <string.h>  // memcpy
9
10 // When creating strings >= this length v8's gc spins up and consumes
11 // most of the execution time. For these cases it's more performant to
12 // use external string resources.
13 #define EXTERN_APEX 0xFBEE9
14
15 namespace node {
16
17 using v8::EscapableHandleScope;
18 using v8::Handle;
19 using v8::HandleScope;
20 using v8::Isolate;
21 using v8::Local;
22 using v8::String;
23 using v8::Value;
24
25
26 template <typename ResourceType, typename TypeName>
27 class ExternString: public ResourceType {
28   public:
29     ~ExternString() override {
30       delete[] data_;
31       int64_t change_in_bytes = -static_cast<int64_t>(length_);
32       isolate()->AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
33     }
34
35     const TypeName* data() const {
36       return data_;
37     }
38
39     size_t length() const {
40       return length_;
41     }
42
43     static Local<String> NewFromCopy(Isolate* isolate,
44                                      const TypeName* data,
45                                      size_t length) {
46       EscapableHandleScope scope(isolate);
47
48       if (length == 0)
49         return scope.Escape(String::Empty(isolate));
50
51       TypeName* new_data = new TypeName[length];
52       memcpy(new_data, data, length * sizeof(*new_data));
53
54       return scope.Escape(ExternString<ResourceType, TypeName>::New(isolate,
55                                                                     new_data,
56                                                                     length));
57     }
58
59     // uses "data" for external resource, and will be free'd on gc
60     static Local<String> New(Isolate* isolate,
61                              const TypeName* data,
62                              size_t length) {
63       EscapableHandleScope scope(isolate);
64
65       if (length == 0)
66         return scope.Escape(String::Empty(isolate));
67
68       ExternString* h_str = new ExternString<ResourceType, TypeName>(isolate,
69                                                                      data,
70                                                                      length);
71       Local<String> str = String::NewExternal(isolate, h_str);
72       isolate->AdjustAmountOfExternalAllocatedMemory(length);
73
74       return scope.Escape(str);
75     }
76
77     inline Isolate* isolate() const { return isolate_; }
78
79   private:
80     ExternString(Isolate* isolate, const TypeName* data, size_t length)
81       : isolate_(isolate), data_(data), length_(length) { }
82     Isolate* isolate_;
83     const TypeName* data_;
84     size_t length_;
85 };
86
87
88 typedef ExternString<String::ExternalOneByteStringResource,
89                      char> ExternOneByteString;
90 typedef ExternString<String::ExternalStringResource,
91                      uint16_t> ExternTwoByteString;
92
93
94 //// Base 64 ////
95
96 #define base64_encoded_size(size) ((size + 2 - ((size + 2) % 3)) / 3 * 4)
97
98
99 // Doesn't check for padding at the end.  Can be 1-2 bytes over.
100 static inline size_t base64_decoded_size_fast(size_t size) {
101   size_t remainder = size % 4;
102
103   size = (size / 4) * 3;
104   if (remainder) {
105     if (size == 0 && remainder == 1) {
106       // special case: 1-byte input cannot be decoded
107       size = 0;
108     } else {
109       // non-padded input, add 1 or 2 extra bytes
110       size += 1 + (remainder == 3);
111     }
112   }
113
114   return size;
115 }
116
117 template <typename TypeName>
118 size_t base64_decoded_size(const TypeName* src, size_t size) {
119   if (size == 0)
120     return 0;
121
122   if (src[size - 1] == '=')
123     size--;
124   if (size > 0 && src[size - 1] == '=')
125     size--;
126
127   return base64_decoded_size_fast(size);
128 }
129
130
131 // supports regular and URL-safe base64
132 static const int unbase64_table[] =
133   { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, -2, -1, -1,
134     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
135     -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63,
136     52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
137     -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
138     15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63,
139     -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
140     41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
141     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
142     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
143     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
144     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
145     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
146     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
147     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
148     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
149   };
150 #define unbase64(x) unbase64_table[(uint8_t)(x)]
151
152
153 template <typename TypeName>
154 size_t base64_decode(char* buf,
155                      size_t len,
156                      const TypeName* src,
157                      const size_t srcLen) {
158   char a, b, c, d;
159   char* dst = buf;
160   char* dstEnd = buf + len;
161   const TypeName* srcEnd = src + srcLen;
162
163   while (src < srcEnd && dst < dstEnd) {
164     int remaining = srcEnd - src;
165
166     while (unbase64(*src) < 0 && src < srcEnd)
167       src++, remaining--;
168     if (remaining == 0 || *src == '=')
169       break;
170     a = unbase64(*src++);
171
172     while (unbase64(*src) < 0 && src < srcEnd)
173       src++, remaining--;
174     if (remaining <= 1 || *src == '=')
175       break;
176     b = unbase64(*src++);
177
178     *dst++ = (a << 2) | ((b & 0x30) >> 4);
179     if (dst == dstEnd)
180       break;
181
182     while (unbase64(*src) < 0 && src < srcEnd)
183       src++, remaining--;
184     if (remaining <= 2 || *src == '=')
185       break;
186     c = unbase64(*src++);
187
188     *dst++ = ((b & 0x0F) << 4) | ((c & 0x3C) >> 2);
189     if (dst == dstEnd)
190       break;
191
192     while (unbase64(*src) < 0 && src < srcEnd)
193       src++, remaining--;
194     if (remaining <= 3 || *src == '=')
195       break;
196     d = unbase64(*src++);
197
198     *dst++ = ((c & 0x03) << 6) | (d & 0x3F);
199   }
200
201   return dst - buf;
202 }
203
204
205 //// HEX ////
206
207 template <typename TypeName>
208 unsigned hex2bin(TypeName c) {
209   if (c >= '0' && c <= '9')
210     return c - '0';
211   if (c >= 'A' && c <= 'F')
212     return 10 + (c - 'A');
213   if (c >= 'a' && c <= 'f')
214     return 10 + (c - 'a');
215   return static_cast<unsigned>(-1);
216 }
217
218
219 template <typename TypeName>
220 size_t hex_decode(char* buf,
221                   size_t len,
222                   const TypeName* src,
223                   const size_t srcLen) {
224   size_t i;
225   for (i = 0; i < len && i * 2 + 1 < srcLen; ++i) {
226     unsigned a = hex2bin(src[i * 2 + 0]);
227     unsigned b = hex2bin(src[i * 2 + 1]);
228     if (!~a || !~b)
229       return i;
230     buf[i] = a * 16 + b;
231   }
232
233   return i;
234 }
235
236
237 bool StringBytes::GetExternalParts(Isolate* isolate,
238                                    Handle<Value> val,
239                                    const char** data,
240                                    size_t* len) {
241   if (Buffer::HasInstance(val)) {
242     *data = Buffer::Data(val);
243     *len = Buffer::Length(val);
244     return true;
245   }
246
247   if (!val->IsString())
248     return false;
249
250   Local<String> str = val.As<String>();
251
252   if (str->IsExternalOneByte()) {
253     const String::ExternalOneByteStringResource* ext;
254     ext = str->GetExternalOneByteStringResource();
255     *data = ext->data();
256     *len = ext->length();
257     return true;
258
259   } else if (str->IsExternal()) {
260     const String::ExternalStringResource* ext;
261     ext = str->GetExternalStringResource();
262     *data = reinterpret_cast<const char*>(ext->data());
263     *len = ext->length();
264     return true;
265   }
266
267   return false;
268 }
269
270
271 size_t StringBytes::Write(Isolate* isolate,
272                           char* buf,
273                           size_t buflen,
274                           Handle<Value> val,
275                           enum encoding encoding,
276                           int* chars_written) {
277   HandleScope scope(isolate);
278   const char* data = nullptr;
279   size_t len = 0;
280   bool is_extern = GetExternalParts(isolate, val, &data, &len);
281   size_t extlen = len;
282
283   CHECK(val->IsString() == true);
284   Local<String> str = val.As<String>();
285   len = len < buflen ? len : buflen;
286
287   int flags = String::NO_NULL_TERMINATION |
288               String::HINT_MANY_WRITES_EXPECTED;
289
290   switch (encoding) {
291     case ASCII:
292     case BINARY:
293     case BUFFER:
294       if (is_extern)
295         memcpy(buf, data, len);
296       else
297         len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf),
298                                 0,
299                                 buflen,
300                                 flags);
301       if (chars_written != nullptr)
302         *chars_written = len;
303       break;
304
305     case UTF8:
306       if (is_extern)
307         // TODO(tjfontaine) should this validate invalid surrogate pairs as
308         // well?
309         memcpy(buf, data, len);
310       else
311         len = str->WriteUtf8(buf, buflen, chars_written, WRITE_UTF8_FLAGS);
312       break;
313
314     case UCS2:
315       if (is_extern)
316         memcpy(buf, data, len * 2);
317       else
318         len = str->Write(reinterpret_cast<uint16_t*>(buf), 0, buflen, flags);
319       if (IsBigEndian()) {
320         // Node's "ucs2" encoding wants LE character data stored in
321         // the Buffer, so we need to reorder on BE platforms.  See
322         // http://nodejs.org/api/buffer.html regarding Node's "ucs2"
323         // encoding specification
324         uint16_t* buf16 = reinterpret_cast<uint16_t*>(buf);
325         for (size_t i = 0; i < len; i++) {
326           buf16[i] = (buf16[i] << 8) | (buf16[i] >> 8);
327         }
328       }
329       if (chars_written != nullptr)
330         *chars_written = len;
331       len = len * sizeof(uint16_t);
332       break;
333
334     case BASE64:
335       if (is_extern) {
336         len = base64_decode(buf, buflen, data, extlen);
337       } else {
338         String::Value value(str);
339         len = base64_decode(buf, buflen, *value, value.length());
340       }
341       if (chars_written != nullptr) {
342         *chars_written = len;
343       }
344       break;
345
346     case HEX:
347       if (is_extern) {
348         len = hex_decode(buf, buflen, data, extlen);
349       } else {
350         String::Value value(str);
351         len = hex_decode(buf, buflen, *value, value.length());
352       }
353       if (chars_written != nullptr) {
354         *chars_written = len * 2;
355       }
356       break;
357
358     default:
359       CHECK(0 && "unknown encoding");
360       break;
361   }
362
363   return len;
364 }
365
366
367 bool StringBytes::IsValidString(Isolate* isolate,
368                                 Handle<String> string,
369                                 enum encoding enc) {
370   if (enc == HEX && string->Length() % 2 != 0)
371     return false;
372   // TODO(bnoordhuis) Add BASE64 check?
373   return true;
374 }
375
376
377 // Quick and dirty size calculation
378 // Will always be at least big enough, but may have some extra
379 // UTF8 can be as much as 3x the size, Base64 can have 1-2 extra bytes
380 size_t StringBytes::StorageSize(Isolate* isolate,
381                                 Handle<Value> val,
382                                 enum encoding encoding) {
383   HandleScope scope(isolate);
384   size_t data_size = 0;
385   bool is_buffer = Buffer::HasInstance(val);
386
387   if (is_buffer && (encoding == BUFFER || encoding == BINARY)) {
388     return Buffer::Length(val);
389   }
390
391   Local<String> str = val->ToString(isolate);
392
393   switch (encoding) {
394     case BINARY:
395     case BUFFER:
396     case ASCII:
397       data_size = str->Length();
398       break;
399
400     case UTF8:
401       // A single UCS2 codepoint never takes up more than 3 utf8 bytes.
402       // It is an exercise for the caller to decide when a string is
403       // long enough to justify calling Size() instead of StorageSize()
404       data_size = 3 * str->Length();
405       break;
406
407     case UCS2:
408       data_size = str->Length() * sizeof(uint16_t);
409       break;
410
411     case BASE64:
412       data_size = base64_decoded_size_fast(str->Length());
413       break;
414
415     case HEX:
416       CHECK(str->Length() % 2 == 0 && "invalid hex string length");
417       data_size = str->Length() / 2;
418       break;
419
420     default:
421       CHECK(0 && "unknown encoding");
422       break;
423   }
424
425   return data_size;
426 }
427
428
429 size_t StringBytes::Size(Isolate* isolate,
430                          Handle<Value> val,
431                          enum encoding encoding) {
432   HandleScope scope(isolate);
433   size_t data_size = 0;
434   bool is_buffer = Buffer::HasInstance(val);
435
436   if (is_buffer && (encoding == BUFFER || encoding == BINARY))
437     return Buffer::Length(val);
438
439   const char* data;
440   if (GetExternalParts(isolate, val, &data, &data_size))
441     return data_size;
442
443   Local<String> str = val->ToString(isolate);
444
445   switch (encoding) {
446     case BINARY:
447     case BUFFER:
448     case ASCII:
449       data_size = str->Length();
450       break;
451
452     case UTF8:
453       data_size = str->Utf8Length();
454       break;
455
456     case UCS2:
457       data_size = str->Length() * sizeof(uint16_t);
458       break;
459
460     case BASE64: {
461       String::Value value(str);
462       data_size = base64_decoded_size(*value, value.length());
463       break;
464     }
465
466     case HEX:
467       data_size = str->Length() / 2;
468       break;
469
470     default:
471       CHECK(0 && "unknown encoding");
472       break;
473   }
474
475   return data_size;
476 }
477
478
479
480
481 static bool contains_non_ascii_slow(const char* buf, size_t len) {
482   for (size_t i = 0; i < len; ++i) {
483     if (buf[i] & 0x80)
484       return true;
485   }
486   return false;
487 }
488
489
490 static bool contains_non_ascii(const char* src, size_t len) {
491   if (len < 16) {
492     return contains_non_ascii_slow(src, len);
493   }
494
495   const unsigned bytes_per_word = sizeof(uintptr_t);
496   const unsigned align_mask = bytes_per_word - 1;
497   const unsigned unaligned = reinterpret_cast<uintptr_t>(src) & align_mask;
498
499   if (unaligned > 0) {
500     const unsigned n = bytes_per_word - unaligned;
501     if (contains_non_ascii_slow(src, n))
502       return true;
503     src += n;
504     len -= n;
505   }
506
507
508 #if defined(_WIN64) || defined(_LP64)
509   const uintptr_t mask = 0x8080808080808080ll;
510 #else
511   const uintptr_t mask = 0x80808080l;
512 #endif
513
514   const uintptr_t* srcw = reinterpret_cast<const uintptr_t*>(src);
515
516   for (size_t i = 0, n = len / bytes_per_word; i < n; ++i) {
517     if (srcw[i] & mask)
518       return true;
519   }
520
521   const unsigned remainder = len & align_mask;
522   if (remainder > 0) {
523     const size_t offset = len - remainder;
524     if (contains_non_ascii_slow(src + offset, remainder))
525       return true;
526   }
527
528   return false;
529 }
530
531
532 static void force_ascii_slow(const char* src, char* dst, size_t len) {
533   for (size_t i = 0; i < len; ++i) {
534     dst[i] = src[i] & 0x7f;
535   }
536 }
537
538
539 static void force_ascii(const char* src, char* dst, size_t len) {
540   if (len < 16) {
541     force_ascii_slow(src, dst, len);
542     return;
543   }
544
545   const unsigned bytes_per_word = sizeof(uintptr_t);
546   const unsigned align_mask = bytes_per_word - 1;
547   const unsigned src_unalign = reinterpret_cast<uintptr_t>(src) & align_mask;
548   const unsigned dst_unalign = reinterpret_cast<uintptr_t>(dst) & align_mask;
549
550   if (src_unalign > 0) {
551     if (src_unalign == dst_unalign) {
552       const unsigned unalign = bytes_per_word - src_unalign;
553       force_ascii_slow(src, dst, unalign);
554       src += unalign;
555       dst += unalign;
556       len -= src_unalign;
557     } else {
558       force_ascii_slow(src, dst, len);
559       return;
560     }
561   }
562
563 #if defined(_WIN64) || defined(_LP64)
564   const uintptr_t mask = ~0x8080808080808080ll;
565 #else
566   const uintptr_t mask = ~0x80808080l;
567 #endif
568
569   const uintptr_t* srcw = reinterpret_cast<const uintptr_t*>(src);
570   uintptr_t* dstw = reinterpret_cast<uintptr_t*>(dst);
571
572   for (size_t i = 0, n = len / bytes_per_word; i < n; ++i) {
573     dstw[i] = srcw[i] & mask;
574   }
575
576   const unsigned remainder = len & align_mask;
577   if (remainder > 0) {
578     const size_t offset = len - remainder;
579     force_ascii_slow(src + offset, dst + offset, remainder);
580   }
581 }
582
583
584 static size_t base64_encode(const char* src,
585                             size_t slen,
586                             char* dst,
587                             size_t dlen) {
588   // We know how much we'll write, just make sure that there's space.
589   CHECK(dlen >= base64_encoded_size(slen) &&
590         "not enough space provided for base64 encode");
591
592   dlen = base64_encoded_size(slen);
593
594   unsigned a;
595   unsigned b;
596   unsigned c;
597   unsigned i;
598   unsigned k;
599   unsigned n;
600
601   static const char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
602                               "abcdefghijklmnopqrstuvwxyz"
603                               "0123456789+/";
604
605   i = 0;
606   k = 0;
607   n = slen / 3 * 3;
608
609   while (i < n) {
610     a = src[i + 0] & 0xff;
611     b = src[i + 1] & 0xff;
612     c = src[i + 2] & 0xff;
613
614     dst[k + 0] = table[a >> 2];
615     dst[k + 1] = table[((a & 3) << 4) | (b >> 4)];
616     dst[k + 2] = table[((b & 0x0f) << 2) | (c >> 6)];
617     dst[k + 3] = table[c & 0x3f];
618
619     i += 3;
620     k += 4;
621   }
622
623   if (n != slen) {
624     switch (slen - n) {
625       case 1:
626         a = src[i + 0] & 0xff;
627         dst[k + 0] = table[a >> 2];
628         dst[k + 1] = table[(a & 3) << 4];
629         dst[k + 2] = '=';
630         dst[k + 3] = '=';
631         break;
632
633       case 2:
634         a = src[i + 0] & 0xff;
635         b = src[i + 1] & 0xff;
636         dst[k + 0] = table[a >> 2];
637         dst[k + 1] = table[((a & 3) << 4) | (b >> 4)];
638         dst[k + 2] = table[(b & 0x0f) << 2];
639         dst[k + 3] = '=';
640         break;
641     }
642   }
643
644   return dlen;
645 }
646
647
648 static size_t hex_encode(const char* src, size_t slen, char* dst, size_t dlen) {
649   // We know how much we'll write, just make sure that there's space.
650   CHECK(dlen >= slen * 2 &&
651       "not enough space provided for hex encode");
652
653   dlen = slen * 2;
654   for (uint32_t i = 0, k = 0; k < dlen; i += 1, k += 2) {
655     static const char hex[] = "0123456789abcdef";
656     uint8_t val = static_cast<uint8_t>(src[i]);
657     dst[k + 0] = hex[val >> 4];
658     dst[k + 1] = hex[val & 15];
659   }
660
661   return dlen;
662 }
663
664
665
666 Local<Value> StringBytes::Encode(Isolate* isolate,
667                                  const char* buf,
668                                  size_t buflen,
669                                  enum encoding encoding) {
670   EscapableHandleScope scope(isolate);
671
672   CHECK_NE(encoding, UCS2);
673   CHECK_LE(buflen, Buffer::kMaxLength);
674   if (!buflen && encoding != BUFFER)
675     return scope.Escape(String::Empty(isolate));
676
677   Local<String> val;
678   switch (encoding) {
679     case BUFFER:
680       return scope.Escape(Buffer::New(buf, buflen));
681
682     case ASCII:
683       if (contains_non_ascii(buf, buflen)) {
684         char* out = new char[buflen];
685         force_ascii(buf, out, buflen);
686         if (buflen < EXTERN_APEX) {
687           val = OneByteString(isolate, out, buflen);
688           delete[] out;
689         } else {
690           val = ExternOneByteString::New(isolate, out, buflen);
691         }
692       } else {
693         if (buflen < EXTERN_APEX)
694           val = OneByteString(isolate, buf, buflen);
695         else
696           val = ExternOneByteString::NewFromCopy(isolate, buf, buflen);
697       }
698       break;
699
700     case UTF8:
701       val = String::NewFromUtf8(isolate,
702                                 buf,
703                                 String::kNormalString,
704                                 buflen);
705       break;
706
707     case BINARY:
708       if (buflen < EXTERN_APEX)
709         val = OneByteString(isolate, buf, buflen);
710       else
711         val = ExternOneByteString::NewFromCopy(isolate, buf, buflen);
712       break;
713
714     case BASE64: {
715       size_t dlen = base64_encoded_size(buflen);
716       char* dst = new char[dlen];
717
718       size_t written = base64_encode(buf, buflen, dst, dlen);
719       CHECK_EQ(written, dlen);
720
721       if (dlen < EXTERN_APEX) {
722         val = OneByteString(isolate, dst, dlen);
723         delete[] dst;
724       } else {
725         val = ExternOneByteString::New(isolate, dst, dlen);
726       }
727       break;
728     }
729
730     case HEX: {
731       size_t dlen = buflen * 2;
732       char* dst = new char[dlen];
733       size_t written = hex_encode(buf, buflen, dst, dlen);
734       CHECK_EQ(written, dlen);
735
736       if (dlen < EXTERN_APEX) {
737         val = OneByteString(isolate, dst, dlen);
738         delete[] dst;
739       } else {
740         val = ExternOneByteString::New(isolate, dst, dlen);
741       }
742       break;
743     }
744
745     default:
746       CHECK(0 && "unknown encoding");
747       break;
748   }
749
750   return scope.Escape(val);
751 }
752
753
754 Local<Value> StringBytes::Encode(Isolate* isolate,
755                                  const uint16_t* buf,
756                                  size_t buflen) {
757   const uint16_t* src = buf;
758
759   Local<String> val;
760   if (buflen < EXTERN_APEX) {
761     val = String::NewFromTwoByte(isolate,
762                                  src,
763                                  String::kNormalString,
764                                  buflen);
765   } else {
766     val = ExternTwoByteString::NewFromCopy(isolate, src, buflen);
767   }
768
769   if (src != buf)
770     delete[] src;
771
772   return val;
773 }
774
775 }  // namespace node