V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
conversions.cc
1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/conversions.h"
6 
7 #include <limits.h>
8 #include <stdarg.h>
9 #include <cmath>
10 
11 #include "src/allocation.h"
12 #include "src/assert-scope.h"
13 #include "src/char-predicates-inl.h"
14 #include "src/dtoa.h"
15 #include "src/handles.h"
16 #include "src/heap/factory.h"
17 #include "src/objects-inl.h"
18 #include "src/objects/bigint.h"
19 #include "src/strtod.h"
20 #include "src/utils.h"
21 
22 #if defined(_STLP_VENDOR_CSTD)
23 // STLPort doesn't import fpclassify into the std namespace.
24 #define FPCLASSIFY_NAMESPACE
25 #else
26 #define FPCLASSIFY_NAMESPACE std
27 #endif
28 
29 namespace v8 {
30 namespace internal {
31 
32 inline double JunkStringValue() {
33  return bit_cast<double, uint64_t>(kQuietNaNMask);
34 }
35 
36 inline double SignedZero(bool negative) {
37  return negative ? uint64_to_double(Double::kSignMask) : 0.0;
38 }
39 
40 inline bool isDigit(int x, int radix) {
41  return (x >= '0' && x <= '9' && x < '0' + radix) ||
42  (radix > 10 && x >= 'a' && x < 'a' + radix - 10) ||
43  (radix > 10 && x >= 'A' && x < 'A' + radix - 10);
44 }
45 
46 inline bool isBinaryDigit(int x) { return x == '0' || x == '1'; }
47 
48 template <class Iterator, class EndMark>
49 bool SubStringEquals(Iterator* current, EndMark end, const char* substring) {
50  DCHECK(**current == *substring);
51  for (substring++; *substring != '\0'; substring++) {
52  ++*current;
53  if (*current == end || **current != *substring) return false;
54  }
55  ++*current;
56  return true;
57 }
58 
59 // Returns true if a nonspace character has been found and false if the
60 // end was been reached before finding a nonspace character.
61 template <class Iterator, class EndMark>
62 inline bool AdvanceToNonspace(Iterator* current, EndMark end) {
63  while (*current != end) {
64  if (!IsWhiteSpaceOrLineTerminator(**current)) return true;
65  ++*current;
66  }
67  return false;
68 }
69 
70 // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
71 template <int radix_log_2, class Iterator, class EndMark>
72 double InternalStringToIntDouble(Iterator current, EndMark end, bool negative,
73  bool allow_trailing_junk) {
74  DCHECK(current != end);
75 
76  // Skip leading 0s.
77  while (*current == '0') {
78  ++current;
79  if (current == end) return SignedZero(negative);
80  }
81 
82  int64_t number = 0;
83  int exponent = 0;
84  const int radix = (1 << radix_log_2);
85 
86  int lim_0 = '0' + (radix < 10 ? radix : 10);
87  int lim_a = 'a' + (radix - 10);
88  int lim_A = 'A' + (radix - 10);
89 
90  do {
91  int digit;
92  if (*current >= '0' && *current < lim_0) {
93  digit = static_cast<char>(*current) - '0';
94  } else if (*current >= 'a' && *current < lim_a) {
95  digit = static_cast<char>(*current) - 'a' + 10;
96  } else if (*current >= 'A' && *current < lim_A) {
97  digit = static_cast<char>(*current) - 'A' + 10;
98  } else {
99  if (allow_trailing_junk || !AdvanceToNonspace(&current, end)) {
100  break;
101  } else {
102  return JunkStringValue();
103  }
104  }
105 
106  number = number * radix + digit;
107  int overflow = static_cast<int>(number >> 53);
108  if (overflow != 0) {
109  // Overflow occurred. Need to determine which direction to round the
110  // result.
111  int overflow_bits_count = 1;
112  while (overflow > 1) {
113  overflow_bits_count++;
114  overflow >>= 1;
115  }
116 
117  int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
118  int dropped_bits = static_cast<int>(number) & dropped_bits_mask;
119  number >>= overflow_bits_count;
120  exponent = overflow_bits_count;
121 
122  bool zero_tail = true;
123  while (true) {
124  ++current;
125  if (current == end || !isDigit(*current, radix)) break;
126  zero_tail = zero_tail && *current == '0';
127  exponent += radix_log_2;
128  }
129 
130  if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
131  return JunkStringValue();
132  }
133 
134  int middle_value = (1 << (overflow_bits_count - 1));
135  if (dropped_bits > middle_value) {
136  number++; // Rounding up.
137  } else if (dropped_bits == middle_value) {
138  // Rounding to even to consistency with decimals: half-way case rounds
139  // up if significant part is odd and down otherwise.
140  if ((number & 1) != 0 || !zero_tail) {
141  number++; // Rounding up.
142  }
143  }
144 
145  // Rounding up may cause overflow.
146  if ((number & (static_cast<int64_t>(1) << 53)) != 0) {
147  exponent++;
148  number >>= 1;
149  }
150  break;
151  }
152  ++current;
153  } while (current != end);
154 
155  DCHECK(number < ((int64_t)1 << 53));
156  DCHECK(static_cast<int64_t>(static_cast<double>(number)) == number);
157 
158  if (exponent == 0) {
159  if (negative) {
160  if (number == 0) return -0.0;
161  number = -number;
162  }
163  return static_cast<double>(number);
164  }
165 
166  DCHECK_NE(number, 0);
167  return std::ldexp(static_cast<double>(negative ? -number : number), exponent);
168 }
169 
170 // ES6 18.2.5 parseInt(string, radix) (with NumberParseIntHelper subclass);
171 // and BigInt parsing cases from https://tc39.github.io/proposal-bigint/
172 // (with StringToBigIntHelper subclass).
174  public:
175  StringToIntHelper(Isolate* isolate, Handle<String> subject, int radix)
176  : isolate_(isolate), subject_(subject), radix_(radix) {
177  DCHECK(subject->IsFlat());
178  }
179 
180  // Used for the StringToBigInt operation.
181  StringToIntHelper(Isolate* isolate, Handle<String> subject)
182  : isolate_(isolate), subject_(subject) {
183  DCHECK(subject->IsFlat());
184  }
185 
186  // Used for parsing BigInt literals, where the input is a Zone-allocated
187  // buffer of one-byte digits, along with an optional radix prefix.
188  StringToIntHelper(Isolate* isolate, const uint8_t* subject, int length)
189  : isolate_(isolate), raw_one_byte_subject_(subject), length_(length) {}
190  virtual ~StringToIntHelper() = default;
191 
192  protected:
193  // Subclasses must implement these:
194  virtual void AllocateResult() = 0;
195  virtual void ResultMultiplyAdd(uint32_t multiplier, uint32_t part) = 0;
196 
197  // Subclasses must call this to do all the work.
198  void ParseInt();
199 
200  // Subclasses may override this.
201  virtual void HandleSpecialCases() {}
202 
203  // Subclass constructors should call these for configuration before calling
204  // ParseInt().
205  void set_allow_binary_and_octal_prefixes() {
206  allow_binary_and_octal_prefixes_ = true;
207  }
208  void set_disallow_trailing_junk() { allow_trailing_junk_ = false; }
209 
210  bool IsOneByte() const {
211  return raw_one_byte_subject_ != nullptr ||
212  subject_->IsOneByteRepresentationUnderneath();
213  }
214 
215  Vector<const uint8_t> GetOneByteVector() {
216  if (raw_one_byte_subject_ != nullptr) {
217  return Vector<const uint8_t>(raw_one_byte_subject_, length_);
218  }
219  return subject_->GetFlatContent().ToOneByteVector();
220  }
221 
222  Vector<const uc16> GetTwoByteVector() {
223  return subject_->GetFlatContent().ToUC16Vector();
224  }
225 
226  // Subclasses get access to internal state:
227  enum State { kRunning, kError, kJunk, kEmpty, kZero, kDone };
228 
229  enum class Sign { kNegative, kPositive, kNone };
230 
231  Isolate* isolate() { return isolate_; }
232  int radix() { return radix_; }
233  int cursor() { return cursor_; }
234  int length() { return length_; }
235  bool negative() { return sign_ == Sign::kNegative; }
236  Sign sign() { return sign_; }
237  State state() { return state_; }
238  void set_state(State state) { state_ = state; }
239 
240  private:
241  template <class Char>
242  void DetectRadixInternal(Char current, int length);
243  template <class Char>
244  void ParseInternal(Char start);
245 
246  Isolate* isolate_;
247  Handle<String> subject_;
248  const uint8_t* raw_one_byte_subject_ = nullptr;
249  int radix_ = 0;
250  int cursor_ = 0;
251  int length_ = 0;
252  Sign sign_ = Sign::kNone;
253  bool leading_zero_ = false;
254  bool allow_binary_and_octal_prefixes_ = false;
255  bool allow_trailing_junk_ = true;
256  State state_ = kRunning;
257 };
258 
259 void StringToIntHelper::ParseInt() {
260  {
262  if (IsOneByte()) {
263  Vector<const uint8_t> vector = GetOneByteVector();
264  DetectRadixInternal(vector.start(), vector.length());
265  } else {
266  Vector<const uc16> vector = GetTwoByteVector();
267  DetectRadixInternal(vector.start(), vector.length());
268  }
269  }
270  if (state_ != kRunning) return;
271  AllocateResult();
272  HandleSpecialCases();
273  if (state_ != kRunning) return;
274  {
275  DisallowHeapAllocation no_gc;
276  if (IsOneByte()) {
277  Vector<const uint8_t> vector = GetOneByteVector();
278  DCHECK_EQ(length_, vector.length());
279  ParseInternal(vector.start());
280  } else {
281  Vector<const uc16> vector = GetTwoByteVector();
282  DCHECK_EQ(length_, vector.length());
283  ParseInternal(vector.start());
284  }
285  }
286  DCHECK_NE(state_, kRunning);
287 }
288 
289 template <class Char>
290 void StringToIntHelper::DetectRadixInternal(Char current, int length) {
291  Char start = current;
292  length_ = length;
293  Char end = start + length;
294 
295  if (!AdvanceToNonspace(&current, end)) {
296  return set_state(kEmpty);
297  }
298 
299  if (*current == '+') {
300  // Ignore leading sign; skip following spaces.
301  ++current;
302  if (current == end) {
303  return set_state(kJunk);
304  }
305  sign_ = Sign::kPositive;
306  } else if (*current == '-') {
307  ++current;
308  if (current == end) {
309  return set_state(kJunk);
310  }
311  sign_ = Sign::kNegative;
312  }
313 
314  if (radix_ == 0) {
315  // Radix detection.
316  radix_ = 10;
317  if (*current == '0') {
318  ++current;
319  if (current == end) return set_state(kZero);
320  if (*current == 'x' || *current == 'X') {
321  radix_ = 16;
322  ++current;
323  if (current == end) return set_state(kJunk);
324  } else if (allow_binary_and_octal_prefixes_ &&
325  (*current == 'o' || *current == 'O')) {
326  radix_ = 8;
327  ++current;
328  if (current == end) return set_state(kJunk);
329  } else if (allow_binary_and_octal_prefixes_ &&
330  (*current == 'b' || *current == 'B')) {
331  radix_ = 2;
332  ++current;
333  if (current == end) return set_state(kJunk);
334  } else {
335  leading_zero_ = true;
336  }
337  }
338  } else if (radix_ == 16) {
339  if (*current == '0') {
340  // Allow "0x" prefix.
341  ++current;
342  if (current == end) return set_state(kZero);
343  if (*current == 'x' || *current == 'X') {
344  ++current;
345  if (current == end) return set_state(kJunk);
346  } else {
347  leading_zero_ = true;
348  }
349  }
350  }
351  // Skip leading zeros.
352  while (*current == '0') {
353  leading_zero_ = true;
354  ++current;
355  if (current == end) return set_state(kZero);
356  }
357 
358  if (!leading_zero_ && !isDigit(*current, radix_)) {
359  return set_state(kJunk);
360  }
361 
362  DCHECK(radix_ >= 2 && radix_ <= 36);
363  STATIC_ASSERT(String::kMaxLength <= INT_MAX);
364  cursor_ = static_cast<int>(current - start);
365 }
366 
367 template <class Char>
368 void StringToIntHelper::ParseInternal(Char start) {
369  Char current = start + cursor_;
370  Char end = start + length_;
371 
372  // The following code causes accumulating rounding error for numbers greater
373  // than ~2^56. It's explicitly allowed in the spec: "if R is not 2, 4, 8, 10,
374  // 16, or 32, then mathInt may be an implementation-dependent approximation to
375  // the mathematical integer value" (15.1.2.2).
376 
377  int lim_0 = '0' + (radix_ < 10 ? radix_ : 10);
378  int lim_a = 'a' + (radix_ - 10);
379  int lim_A = 'A' + (radix_ - 10);
380 
381  // NOTE: The code for computing the value may seem a bit complex at
382  // first glance. It is structured to use 32-bit multiply-and-add
383  // loops as long as possible to avoid losing precision.
384 
385  bool done = false;
386  do {
387  // Parse the longest part of the string starting at {current}
388  // possible while keeping the multiplier, and thus the part
389  // itself, within 32 bits.
390  uint32_t part = 0, multiplier = 1;
391  while (true) {
392  uint32_t d;
393  if (*current >= '0' && *current < lim_0) {
394  d = *current - '0';
395  } else if (*current >= 'a' && *current < lim_a) {
396  d = *current - 'a' + 10;
397  } else if (*current >= 'A' && *current < lim_A) {
398  d = *current - 'A' + 10;
399  } else {
400  done = true;
401  break;
402  }
403 
404  // Update the value of the part as long as the multiplier fits
405  // in 32 bits. When we can't guarantee that the next iteration
406  // will not overflow the multiplier, we stop parsing the part
407  // by leaving the loop.
408  const uint32_t kMaximumMultiplier = 0xFFFFFFFFU / 36;
409  uint32_t m = multiplier * static_cast<uint32_t>(radix_);
410  if (m > kMaximumMultiplier) break;
411  part = part * radix_ + d;
412  multiplier = m;
413  DCHECK(multiplier > part);
414 
415  ++current;
416  if (current == end) {
417  done = true;
418  break;
419  }
420  }
421 
422  // Update the value and skip the part in the string.
423  ResultMultiplyAdd(multiplier, part);
424  } while (!done);
425 
426  if (!allow_trailing_junk_ && AdvanceToNonspace(&current, end)) {
427  return set_state(kJunk);
428  }
429 
430  return set_state(kDone);
431 }
432 
434  public:
435  NumberParseIntHelper(Isolate* isolate, Handle<String> string, int radix)
436  : StringToIntHelper(isolate, string, radix) {}
437 
438  double GetResult() {
439  ParseInt();
440  switch (state()) {
441  case kJunk:
442  case kEmpty:
443  return JunkStringValue();
444  case kZero:
445  return SignedZero(negative());
446  case kDone:
447  return negative() ? -result_ : result_;
448  case kError:
449  case kRunning:
450  break;
451  }
452  UNREACHABLE();
453  }
454 
455  protected:
456  void AllocateResult() override {}
457  void ResultMultiplyAdd(uint32_t multiplier, uint32_t part) override {
458  result_ = result_ * multiplier + part;
459  }
460 
461  private:
462  void HandleSpecialCases() override {
463  bool is_power_of_two = base::bits::IsPowerOfTwo(radix());
464  if (!is_power_of_two && radix() != 10) return;
466  if (IsOneByte()) {
467  Vector<const uint8_t> vector = GetOneByteVector();
468  DCHECK_EQ(length(), vector.length());
469  result_ = is_power_of_two ? HandlePowerOfTwoCase(vector.start())
470  : HandleBaseTenCase(vector.start());
471  } else {
472  Vector<const uc16> vector = GetTwoByteVector();
473  DCHECK_EQ(length(), vector.length());
474  result_ = is_power_of_two ? HandlePowerOfTwoCase(vector.start())
475  : HandleBaseTenCase(vector.start());
476  }
477  set_state(kDone);
478  }
479 
480  template <class Char>
481  double HandlePowerOfTwoCase(Char start) {
482  Char current = start + cursor();
483  Char end = start + length();
484  const bool allow_trailing_junk = true;
485  // GetResult() will take care of the sign bit, so ignore it for now.
486  const bool negative = false;
487  switch (radix()) {
488  case 2:
489  return InternalStringToIntDouble<1>(current, end, negative,
490  allow_trailing_junk);
491  case 4:
492  return InternalStringToIntDouble<2>(current, end, negative,
493  allow_trailing_junk);
494  case 8:
495  return InternalStringToIntDouble<3>(current, end, negative,
496  allow_trailing_junk);
497 
498  case 16:
499  return InternalStringToIntDouble<4>(current, end, negative,
500  allow_trailing_junk);
501 
502  case 32:
503  return InternalStringToIntDouble<5>(current, end, negative,
504  allow_trailing_junk);
505  default:
506  UNREACHABLE();
507  }
508  }
509 
510  template <class Char>
511  double HandleBaseTenCase(Char start) {
512  // Parsing with strtod.
513  Char current = start + cursor();
514  Char end = start + length();
515  const int kMaxSignificantDigits = 309; // Doubles are less than 1.8e308.
516  // The buffer may contain up to kMaxSignificantDigits + 1 digits and a zero
517  // end.
518  const int kBufferSize = kMaxSignificantDigits + 2;
519  char buffer[kBufferSize];
520  int buffer_pos = 0;
521  while (*current >= '0' && *current <= '9') {
522  if (buffer_pos <= kMaxSignificantDigits) {
523  // If the number has more than kMaxSignificantDigits it will be parsed
524  // as infinity.
525  DCHECK_LT(buffer_pos, kBufferSize);
526  buffer[buffer_pos++] = static_cast<char>(*current);
527  }
528  ++current;
529  if (current == end) break;
530  }
531 
532  SLOW_DCHECK(buffer_pos < kBufferSize);
533  buffer[buffer_pos] = '\0';
534  Vector<const char> buffer_vector(buffer, buffer_pos);
535  return Strtod(buffer_vector, 0);
536  }
537 
538  double result_ = 0;
539 };
540 
541 // Converts a string to a double value. Assumes the Iterator supports
542 // the following operations:
543 // 1. current == end (other ops are not allowed), current != end.
544 // 2. *current - gets the current character in the sequence.
545 // 3. ++current (advances the position).
546 template <class Iterator, class EndMark>
547 double InternalStringToDouble(Iterator current, EndMark end, int flags,
548  double empty_string_val) {
549  // To make sure that iterator dereferencing is valid the following
550  // convention is used:
551  // 1. Each '++current' statement is followed by check for equality to 'end'.
552  // 2. If AdvanceToNonspace returned false then current == end.
553  // 3. If 'current' becomes be equal to 'end' the function returns or goes to
554  // 'parsing_done'.
555  // 4. 'current' is not dereferenced after the 'parsing_done' label.
556  // 5. Code before 'parsing_done' may rely on 'current != end'.
557  if (!AdvanceToNonspace(&current, end)) {
558  return empty_string_val;
559  }
560 
561  const bool allow_trailing_junk = (flags & ALLOW_TRAILING_JUNK) != 0;
562 
563  // Maximum number of significant digits in decimal representation.
564  // The longest possible double in decimal representation is
565  // (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074
566  // (768 digits). If we parse a number whose first digits are equal to a
567  // mean of 2 adjacent doubles (that could have up to 769 digits) the result
568  // must be rounded to the bigger one unless the tail consists of zeros, so
569  // we don't need to preserve all the digits.
570  const int kMaxSignificantDigits = 772;
571 
572  // The longest form of simplified number is: "-<significant digits>'.1eXXX\0".
573  const int kBufferSize = kMaxSignificantDigits + 10;
574  char buffer[kBufferSize]; // NOLINT: size is known at compile time.
575  int buffer_pos = 0;
576 
577  // Exponent will be adjusted if insignificant digits of the integer part
578  // or insignificant leading zeros of the fractional part are dropped.
579  int exponent = 0;
580  int significant_digits = 0;
581  int insignificant_digits = 0;
582  bool nonzero_digit_dropped = false;
583 
584  enum Sign { NONE, NEGATIVE, POSITIVE };
585 
586  Sign sign = NONE;
587 
588  if (*current == '+') {
589  // Ignore leading sign.
590  ++current;
591  if (current == end) return JunkStringValue();
592  sign = POSITIVE;
593  } else if (*current == '-') {
594  ++current;
595  if (current == end) return JunkStringValue();
596  sign = NEGATIVE;
597  }
598 
599  static const char kInfinityString[] = "Infinity";
600  if (*current == kInfinityString[0]) {
601  if (!SubStringEquals(&current, end, kInfinityString)) {
602  return JunkStringValue();
603  }
604 
605  if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
606  return JunkStringValue();
607  }
608 
609  DCHECK_EQ(buffer_pos, 0);
610  return (sign == NEGATIVE) ? -V8_INFINITY : V8_INFINITY;
611  }
612 
613  bool leading_zero = false;
614  if (*current == '0') {
615  ++current;
616  if (current == end) return SignedZero(sign == NEGATIVE);
617 
618  leading_zero = true;
619 
620  // It could be hexadecimal value.
621  if ((flags & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {
622  ++current;
623  if (current == end || !isDigit(*current, 16) || sign != NONE) {
624  return JunkStringValue(); // "0x".
625  }
626 
627  return InternalStringToIntDouble<4>(current, end, false,
628  allow_trailing_junk);
629 
630  // It could be an explicit octal value.
631  } else if ((flags & ALLOW_OCTAL) && (*current == 'o' || *current == 'O')) {
632  ++current;
633  if (current == end || !isDigit(*current, 8) || sign != NONE) {
634  return JunkStringValue(); // "0o".
635  }
636 
637  return InternalStringToIntDouble<3>(current, end, false,
638  allow_trailing_junk);
639 
640  // It could be a binary value.
641  } else if ((flags & ALLOW_BINARY) && (*current == 'b' || *current == 'B')) {
642  ++current;
643  if (current == end || !isBinaryDigit(*current) || sign != NONE) {
644  return JunkStringValue(); // "0b".
645  }
646 
647  return InternalStringToIntDouble<1>(current, end, false,
648  allow_trailing_junk);
649  }
650 
651  // Ignore leading zeros in the integer part.
652  while (*current == '0') {
653  ++current;
654  if (current == end) return SignedZero(sign == NEGATIVE);
655  }
656  }
657 
658  bool octal = leading_zero && (flags & ALLOW_IMPLICIT_OCTAL) != 0;
659 
660  // Copy significant digits of the integer part (if any) to the buffer.
661  while (*current >= '0' && *current <= '9') {
662  if (significant_digits < kMaxSignificantDigits) {
663  DCHECK_LT(buffer_pos, kBufferSize);
664  buffer[buffer_pos++] = static_cast<char>(*current);
665  significant_digits++;
666  // Will later check if it's an octal in the buffer.
667  } else {
668  insignificant_digits++; // Move the digit into the exponential part.
669  nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
670  }
671  octal = octal && *current < '8';
672  ++current;
673  if (current == end) goto parsing_done;
674  }
675 
676  if (significant_digits == 0) {
677  octal = false;
678  }
679 
680  if (*current == '.') {
681  if (octal && !allow_trailing_junk) return JunkStringValue();
682  if (octal) goto parsing_done;
683 
684  ++current;
685  if (current == end) {
686  if (significant_digits == 0 && !leading_zero) {
687  return JunkStringValue();
688  } else {
689  goto parsing_done;
690  }
691  }
692 
693  if (significant_digits == 0) {
694  // octal = false;
695  // Integer part consists of 0 or is absent. Significant digits start after
696  // leading zeros (if any).
697  while (*current == '0') {
698  ++current;
699  if (current == end) return SignedZero(sign == NEGATIVE);
700  exponent--; // Move this 0 into the exponent.
701  }
702  }
703 
704  // There is a fractional part. We don't emit a '.', but adjust the exponent
705  // instead.
706  while (*current >= '0' && *current <= '9') {
707  if (significant_digits < kMaxSignificantDigits) {
708  DCHECK_LT(buffer_pos, kBufferSize);
709  buffer[buffer_pos++] = static_cast<char>(*current);
710  significant_digits++;
711  exponent--;
712  } else {
713  // Ignore insignificant digits in the fractional part.
714  nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
715  }
716  ++current;
717  if (current == end) goto parsing_done;
718  }
719  }
720 
721  if (!leading_zero && exponent == 0 && significant_digits == 0) {
722  // If leading_zeros is true then the string contains zeros.
723  // If exponent < 0 then string was [+-]\.0*...
724  // If significant_digits != 0 the string is not equal to 0.
725  // Otherwise there are no digits in the string.
726  return JunkStringValue();
727  }
728 
729  // Parse exponential part.
730  if (*current == 'e' || *current == 'E') {
731  if (octal) return JunkStringValue();
732  ++current;
733  if (current == end) {
734  if (allow_trailing_junk) {
735  goto parsing_done;
736  } else {
737  return JunkStringValue();
738  }
739  }
740  char sign = '+';
741  if (*current == '+' || *current == '-') {
742  sign = static_cast<char>(*current);
743  ++current;
744  if (current == end) {
745  if (allow_trailing_junk) {
746  goto parsing_done;
747  } else {
748  return JunkStringValue();
749  }
750  }
751  }
752 
753  if (current == end || *current < '0' || *current > '9') {
754  if (allow_trailing_junk) {
755  goto parsing_done;
756  } else {
757  return JunkStringValue();
758  }
759  }
760 
761  const int max_exponent = INT_MAX / 2;
762  DCHECK(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
763  int num = 0;
764  do {
765  // Check overflow.
766  int digit = *current - '0';
767  if (num >= max_exponent / 10 &&
768  !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
769  num = max_exponent;
770  } else {
771  num = num * 10 + digit;
772  }
773  ++current;
774  } while (current != end && *current >= '0' && *current <= '9');
775 
776  exponent += (sign == '-' ? -num : num);
777  }
778 
779  if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
780  return JunkStringValue();
781  }
782 
783 parsing_done:
784  exponent += insignificant_digits;
785 
786  if (octal) {
787  return InternalStringToIntDouble<3>(buffer, buffer + buffer_pos,
788  sign == NEGATIVE, allow_trailing_junk);
789  }
790 
791  if (nonzero_digit_dropped) {
792  buffer[buffer_pos++] = '1';
793  exponent--;
794  }
795 
796  SLOW_DCHECK(buffer_pos < kBufferSize);
797  buffer[buffer_pos] = '\0';
798 
799  double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
800  return (sign == NEGATIVE) ? -converted : converted;
801 }
802 
803 double StringToDouble(const char* str, int flags, double empty_string_val) {
804  // We cast to const uint8_t* here to avoid instantiating the
805  // InternalStringToDouble() template for const char* as well.
806  const uint8_t* start = reinterpret_cast<const uint8_t*>(str);
807  const uint8_t* end = start + StrLength(str);
808  return InternalStringToDouble(start, end, flags, empty_string_val);
809 }
810 
811 double StringToDouble(Vector<const uint8_t> str, int flags,
812  double empty_string_val) {
813  // We cast to const uint8_t* here to avoid instantiating the
814  // InternalStringToDouble() template for const char* as well.
815  const uint8_t* start = reinterpret_cast<const uint8_t*>(str.start());
816  const uint8_t* end = start + str.length();
817  return InternalStringToDouble(start, end, flags, empty_string_val);
818 }
819 
820 double StringToDouble(Vector<const uc16> str, int flags,
821  double empty_string_val) {
822  const uc16* end = str.start() + str.length();
823  return InternalStringToDouble(str.start(), end, flags, empty_string_val);
824 }
825 
826 double StringToInt(Isolate* isolate, Handle<String> string, int radix) {
827  NumberParseIntHelper helper(isolate, string, radix);
828  return helper.GetResult();
829 }
830 
832  public:
833  enum class Behavior { kStringToBigInt, kLiteral };
834 
835  // Used for StringToBigInt operation (BigInt constructor and == operator).
837  : StringToIntHelper(isolate, string),
838  behavior_(Behavior::kStringToBigInt) {
839  set_allow_binary_and_octal_prefixes();
840  set_disallow_trailing_junk();
841  }
842 
843  // Used for parsing BigInt literals, where the input is a buffer of
844  // one-byte ASCII digits, along with an optional radix prefix.
845  StringToBigIntHelper(Isolate* isolate, const uint8_t* string, int length)
846  : StringToIntHelper(isolate, string, length),
847  behavior_(Behavior::kLiteral) {
848  set_allow_binary_and_octal_prefixes();
849  }
850 
851  MaybeHandle<BigInt> GetResult() {
852  ParseInt();
853  if (behavior_ == Behavior::kStringToBigInt && sign() != Sign::kNone &&
854  radix() != 10) {
855  return MaybeHandle<BigInt>();
856  }
857  if (state() == kEmpty) {
858  if (behavior_ == Behavior::kStringToBigInt) {
859  set_state(kZero);
860  } else {
861  UNREACHABLE();
862  }
863  }
864  switch (state()) {
865  case kJunk:
866  if (should_throw() == kThrowOnError) {
867  THROW_NEW_ERROR(isolate(),
868  NewSyntaxError(MessageTemplate::kBigIntInvalidString),
869  BigInt);
870  } else {
871  DCHECK_EQ(should_throw(), kDontThrow);
872  return MaybeHandle<BigInt>();
873  }
874  case kZero:
875  return BigInt::Zero(isolate());
876  case kError:
877  DCHECK_EQ(should_throw() == kThrowOnError,
878  isolate()->has_pending_exception());
879  return MaybeHandle<BigInt>();
880  case kDone:
881  return BigInt::Finalize(result_, negative());
882  case kEmpty:
883  case kRunning:
884  break;
885  }
886  UNREACHABLE();
887  }
888 
889  protected:
890  void AllocateResult() override {
891  // We have to allocate a BigInt that's big enough to fit the result.
892  // Conseratively assume that all remaining digits are significant.
893  // Optimization opportunity: Would it makes sense to scan for trailing
894  // junk before allocating the result?
895  int charcount = length() - cursor();
896  // For literals, we pretenure the allocated BigInt, since it's about
897  // to be stored in the interpreter's constants array.
898  PretenureFlag pretenure =
899  behavior_ == Behavior::kLiteral ? TENURED : NOT_TENURED;
900  MaybeHandle<FreshlyAllocatedBigInt> maybe = BigInt::AllocateFor(
901  isolate(), radix(), charcount, should_throw(), pretenure);
902  if (!maybe.ToHandle(&result_)) {
903  set_state(kError);
904  }
905  }
906 
907  void ResultMultiplyAdd(uint32_t multiplier, uint32_t part) override {
908  BigInt::InplaceMultiplyAdd(result_, static_cast<uintptr_t>(multiplier),
909  static_cast<uintptr_t>(part));
910  }
911 
912  private:
913  ShouldThrow should_throw() const { return kDontThrow; }
914 
916  Behavior behavior_;
917 };
918 
919 MaybeHandle<BigInt> StringToBigInt(Isolate* isolate, Handle<String> string) {
920  string = String::Flatten(isolate, string);
921  StringToBigIntHelper helper(isolate, string);
922  return helper.GetResult();
923 }
924 
925 MaybeHandle<BigInt> BigIntLiteral(Isolate* isolate, const char* string) {
926  StringToBigIntHelper helper(isolate, reinterpret_cast<const uint8_t*>(string),
927  static_cast<int>(strlen(string)));
928  return helper.GetResult();
929 }
930 
931 const char* DoubleToCString(double v, Vector<char> buffer) {
932  switch (FPCLASSIFY_NAMESPACE::fpclassify(v)) {
933  case FP_NAN: return "NaN";
934  case FP_INFINITE: return (v < 0.0 ? "-Infinity" : "Infinity");
935  case FP_ZERO: return "0";
936  default: {
937  SimpleStringBuilder builder(buffer.start(), buffer.length());
938  int decimal_point;
939  int sign;
940  const int kV8DtoaBufferCapacity = kBase10MaximalLength + 1;
941  char decimal_rep[kV8DtoaBufferCapacity];
942  int length;
943 
944  DoubleToAscii(v, DTOA_SHORTEST, 0,
945  Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
946  &sign, &length, &decimal_point);
947 
948  if (sign) builder.AddCharacter('-');
949 
950  if (length <= decimal_point && decimal_point <= 21) {
951  // ECMA-262 section 9.8.1 step 6.
952  builder.AddString(decimal_rep);
953  builder.AddPadding('0', decimal_point - length);
954 
955  } else if (0 < decimal_point && decimal_point <= 21) {
956  // ECMA-262 section 9.8.1 step 7.
957  builder.AddSubstring(decimal_rep, decimal_point);
958  builder.AddCharacter('.');
959  builder.AddString(decimal_rep + decimal_point);
960 
961  } else if (decimal_point <= 0 && decimal_point > -6) {
962  // ECMA-262 section 9.8.1 step 8.
963  builder.AddString("0.");
964  builder.AddPadding('0', -decimal_point);
965  builder.AddString(decimal_rep);
966 
967  } else {
968  // ECMA-262 section 9.8.1 step 9 and 10 combined.
969  builder.AddCharacter(decimal_rep[0]);
970  if (length != 1) {
971  builder.AddCharacter('.');
972  builder.AddString(decimal_rep + 1);
973  }
974  builder.AddCharacter('e');
975  builder.AddCharacter((decimal_point >= 0) ? '+' : '-');
976  int exponent = decimal_point - 1;
977  if (exponent < 0) exponent = -exponent;
978  builder.AddDecimalInteger(exponent);
979  }
980  return builder.Finalize();
981  }
982  }
983 }
984 
985 
986 const char* IntToCString(int n, Vector<char> buffer) {
987  bool negative = false;
988  if (n < 0) {
989  // We must not negate the most negative int.
990  if (n == kMinInt) return DoubleToCString(n, buffer);
991  negative = true;
992  n = -n;
993  }
994  // Build the string backwards from the least significant digit.
995  int i = buffer.length();
996  buffer[--i] = '\0';
997  do {
998  buffer[--i] = '0' + (n % 10);
999  n /= 10;
1000  } while (n);
1001  if (negative) buffer[--i] = '-';
1002  return buffer.start() + i;
1003 }
1004 
1005 
1006 char* DoubleToFixedCString(double value, int f) {
1007  const int kMaxDigitsBeforePoint = 21;
1008  const double kFirstNonFixed = 1e21;
1009  DCHECK_GE(f, 0);
1010  DCHECK_LE(f, kMaxFractionDigits);
1011 
1012  bool negative = false;
1013  double abs_value = value;
1014  if (value < 0) {
1015  abs_value = -value;
1016  negative = true;
1017  }
1018 
1019  // If abs_value has more than kMaxDigitsBeforePoint digits before the point
1020  // use the non-fixed conversion routine.
1021  if (abs_value >= kFirstNonFixed) {
1022  char arr[kMaxFractionDigits];
1023  Vector<char> buffer(arr, arraysize(arr));
1024  return StrDup(DoubleToCString(value, buffer));
1025  }
1026 
1027  // Find a sufficiently precise decimal representation of n.
1028  int decimal_point;
1029  int sign;
1030  // Add space for the '\0' byte.
1031  const int kDecimalRepCapacity =
1032  kMaxDigitsBeforePoint + kMaxFractionDigits + 1;
1033  char decimal_rep[kDecimalRepCapacity];
1034  int decimal_rep_length;
1035  DoubleToAscii(value, DTOA_FIXED, f,
1036  Vector<char>(decimal_rep, kDecimalRepCapacity),
1037  &sign, &decimal_rep_length, &decimal_point);
1038 
1039  // Create a representation that is padded with zeros if needed.
1040  int zero_prefix_length = 0;
1041  int zero_postfix_length = 0;
1042 
1043  if (decimal_point <= 0) {
1044  zero_prefix_length = -decimal_point + 1;
1045  decimal_point = 1;
1046  }
1047 
1048  if (zero_prefix_length + decimal_rep_length < decimal_point + f) {
1049  zero_postfix_length = decimal_point + f - decimal_rep_length -
1050  zero_prefix_length;
1051  }
1052 
1053  unsigned rep_length =
1054  zero_prefix_length + decimal_rep_length + zero_postfix_length;
1055  SimpleStringBuilder rep_builder(rep_length + 1);
1056  rep_builder.AddPadding('0', zero_prefix_length);
1057  rep_builder.AddString(decimal_rep);
1058  rep_builder.AddPadding('0', zero_postfix_length);
1059  char* rep = rep_builder.Finalize();
1060 
1061  // Create the result string by appending a minus and putting in a
1062  // decimal point if needed.
1063  unsigned result_size = decimal_point + f + 2;
1064  SimpleStringBuilder builder(result_size + 1);
1065  if (negative) builder.AddCharacter('-');
1066  builder.AddSubstring(rep, decimal_point);
1067  if (f > 0) {
1068  builder.AddCharacter('.');
1069  builder.AddSubstring(rep + decimal_point, f);
1070  }
1071  DeleteArray(rep);
1072  return builder.Finalize();
1073 }
1074 
1075 
1076 static char* CreateExponentialRepresentation(char* decimal_rep,
1077  int exponent,
1078  bool negative,
1079  int significant_digits) {
1080  bool negative_exponent = false;
1081  if (exponent < 0) {
1082  negative_exponent = true;
1083  exponent = -exponent;
1084  }
1085 
1086  // Leave room in the result for appending a minus, for a period, the
1087  // letter 'e', a minus or a plus depending on the exponent, and a
1088  // three digit exponent.
1089  unsigned result_size = significant_digits + 7;
1090  SimpleStringBuilder builder(result_size + 1);
1091 
1092  if (negative) builder.AddCharacter('-');
1093  builder.AddCharacter(decimal_rep[0]);
1094  if (significant_digits != 1) {
1095  builder.AddCharacter('.');
1096  builder.AddString(decimal_rep + 1);
1097  int rep_length = StrLength(decimal_rep);
1098  builder.AddPadding('0', significant_digits - rep_length);
1099  }
1100 
1101  builder.AddCharacter('e');
1102  builder.AddCharacter(negative_exponent ? '-' : '+');
1103  builder.AddDecimalInteger(exponent);
1104  return builder.Finalize();
1105 }
1106 
1107 
1108 char* DoubleToExponentialCString(double value, int f) {
1109  // f might be -1 to signal that f was undefined in JavaScript.
1110  DCHECK(f >= -1 && f <= kMaxFractionDigits);
1111 
1112  bool negative = false;
1113  if (value < 0) {
1114  value = -value;
1115  negative = true;
1116  }
1117 
1118  // Find a sufficiently precise decimal representation of n.
1119  int decimal_point;
1120  int sign;
1121  // f corresponds to the digits after the point. There is always one digit
1122  // before the point. The number of requested_digits equals hence f + 1.
1123  // And we have to add one character for the null-terminator.
1124  const int kV8DtoaBufferCapacity = kMaxFractionDigits + 1 + 1;
1125  // Make sure that the buffer is big enough, even if we fall back to the
1126  // shortest representation (which happens when f equals -1).
1127  DCHECK_LE(kBase10MaximalLength, kMaxFractionDigits + 1);
1128  char decimal_rep[kV8DtoaBufferCapacity];
1129  int decimal_rep_length;
1130 
1131  if (f == -1) {
1132  DoubleToAscii(value, DTOA_SHORTEST, 0,
1133  Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
1134  &sign, &decimal_rep_length, &decimal_point);
1135  f = decimal_rep_length - 1;
1136  } else {
1137  DoubleToAscii(value, DTOA_PRECISION, f + 1,
1138  Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
1139  &sign, &decimal_rep_length, &decimal_point);
1140  }
1141  DCHECK_GT(decimal_rep_length, 0);
1142  DCHECK(decimal_rep_length <= f + 1);
1143 
1144  int exponent = decimal_point - 1;
1145  char* result =
1146  CreateExponentialRepresentation(decimal_rep, exponent, negative, f+1);
1147 
1148  return result;
1149 }
1150 
1151 
1152 char* DoubleToPrecisionCString(double value, int p) {
1153  const int kMinimalDigits = 1;
1154  DCHECK(p >= kMinimalDigits && p <= kMaxFractionDigits);
1155  USE(kMinimalDigits);
1156 
1157  bool negative = false;
1158  if (value < 0) {
1159  value = -value;
1160  negative = true;
1161  }
1162 
1163  // Find a sufficiently precise decimal representation of n.
1164  int decimal_point;
1165  int sign;
1166  // Add one for the terminating null character.
1167  const int kV8DtoaBufferCapacity = kMaxFractionDigits + 1;
1168  char decimal_rep[kV8DtoaBufferCapacity];
1169  int decimal_rep_length;
1170 
1171  DoubleToAscii(value, DTOA_PRECISION, p,
1172  Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
1173  &sign, &decimal_rep_length, &decimal_point);
1174  DCHECK(decimal_rep_length <= p);
1175 
1176  int exponent = decimal_point - 1;
1177 
1178  char* result = nullptr;
1179 
1180  if (exponent < -6 || exponent >= p) {
1181  result =
1182  CreateExponentialRepresentation(decimal_rep, exponent, negative, p);
1183  } else {
1184  // Use fixed notation.
1185  //
1186  // Leave room in the result for appending a minus, a period and in
1187  // the case where decimal_point is not positive for a zero in
1188  // front of the period.
1189  unsigned result_size = (decimal_point <= 0)
1190  ? -decimal_point + p + 3
1191  : p + 2;
1192  SimpleStringBuilder builder(result_size + 1);
1193  if (negative) builder.AddCharacter('-');
1194  if (decimal_point <= 0) {
1195  builder.AddString("0.");
1196  builder.AddPadding('0', -decimal_point);
1197  builder.AddString(decimal_rep);
1198  builder.AddPadding('0', p - decimal_rep_length);
1199  } else {
1200  const int m = Min(decimal_rep_length, decimal_point);
1201  builder.AddSubstring(decimal_rep, m);
1202  builder.AddPadding('0', decimal_point - decimal_rep_length);
1203  if (decimal_point < p) {
1204  builder.AddCharacter('.');
1205  const int extra = negative ? 2 : 1;
1206  if (decimal_rep_length > decimal_point) {
1207  const int len = StrLength(decimal_rep + decimal_point);
1208  const int n = Min(len, p - (builder.position() - extra));
1209  builder.AddSubstring(decimal_rep + decimal_point, n);
1210  }
1211  builder.AddPadding('0', extra + (p - builder.position()));
1212  }
1213  }
1214  result = builder.Finalize();
1215  }
1216 
1217  return result;
1218 }
1219 
1220 char* DoubleToRadixCString(double value, int radix) {
1221  DCHECK(radix >= 2 && radix <= 36);
1222  DCHECK(std::isfinite(value));
1223  DCHECK_NE(0.0, value);
1224  // Character array used for conversion.
1225  static const char chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
1226 
1227  // Temporary buffer for the result. We start with the decimal point in the
1228  // middle and write to the left for the integer part and to the right for the
1229  // fractional part. 1024 characters for the exponent and 52 for the mantissa
1230  // either way, with additional space for sign, decimal point and string
1231  // termination should be sufficient.
1232  static const int kBufferSize = 2200;
1233  char buffer[kBufferSize];
1234  int integer_cursor = kBufferSize / 2;
1235  int fraction_cursor = integer_cursor;
1236 
1237  bool negative = value < 0;
1238  if (negative) value = -value;
1239 
1240  // Split the value into an integer part and a fractional part.
1241  double integer = std::floor(value);
1242  double fraction = value - integer;
1243  // We only compute fractional digits up to the input double's precision.
1244  double delta = 0.5 * (Double(value).NextDouble() - value);
1245  delta = std::max(Double(0.0).NextDouble(), delta);
1246  DCHECK_GT(delta, 0.0);
1247  if (fraction > delta) {
1248  // Insert decimal point.
1249  buffer[fraction_cursor++] = '.';
1250  do {
1251  // Shift up by one digit.
1252  fraction *= radix;
1253  delta *= radix;
1254  // Write digit.
1255  int digit = static_cast<int>(fraction);
1256  buffer[fraction_cursor++] = chars[digit];
1257  // Calculate remainder.
1258  fraction -= digit;
1259  // Round to even.
1260  if (fraction > 0.5 || (fraction == 0.5 && (digit & 1))) {
1261  if (fraction + delta > 1) {
1262  // We need to back trace already written digits in case of carry-over.
1263  while (true) {
1264  fraction_cursor--;
1265  if (fraction_cursor == kBufferSize / 2) {
1266  CHECK_EQ('.', buffer[fraction_cursor]);
1267  // Carry over to the integer part.
1268  integer += 1;
1269  break;
1270  }
1271  char c = buffer[fraction_cursor];
1272  // Reconstruct digit.
1273  int digit = c > '9' ? (c - 'a' + 10) : (c - '0');
1274  if (digit + 1 < radix) {
1275  buffer[fraction_cursor++] = chars[digit + 1];
1276  break;
1277  }
1278  }
1279  break;
1280  }
1281  }
1282  } while (fraction > delta);
1283  }
1284 
1285  // Compute integer digits. Fill unrepresented digits with zero.
1286  while (Double(integer / radix).Exponent() > 0) {
1287  integer /= radix;
1288  buffer[--integer_cursor] = '0';
1289  }
1290  do {
1291  double remainder = Modulo(integer, radix);
1292  buffer[--integer_cursor] = chars[static_cast<int>(remainder)];
1293  integer = (integer - remainder) / radix;
1294  } while (integer > 0);
1295 
1296  // Add sign and terminate string.
1297  if (negative) buffer[--integer_cursor] = '-';
1298  buffer[fraction_cursor++] = '\0';
1299  DCHECK_LT(fraction_cursor, kBufferSize);
1300  DCHECK_LE(0, integer_cursor);
1301  // Allocate new string as return value.
1302  char* result = NewArray<char>(fraction_cursor - integer_cursor);
1303  memcpy(result, buffer + integer_cursor, fraction_cursor - integer_cursor);
1304  return result;
1305 }
1306 
1307 
1308 // ES6 18.2.4 parseFloat(string)
1309 double StringToDouble(Isolate* isolate, Handle<String> string, int flags,
1310  double empty_string_val) {
1311  Handle<String> flattened = String::Flatten(isolate, string);
1312  {
1313  DisallowHeapAllocation no_gc;
1314  String::FlatContent flat = flattened->GetFlatContent();
1315  DCHECK(flat.IsFlat());
1316  if (flat.IsOneByte()) {
1317  return StringToDouble(flat.ToOneByteVector(), flags, empty_string_val);
1318  } else {
1319  return StringToDouble(flat.ToUC16Vector(), flags, empty_string_val);
1320  }
1321  }
1322 }
1323 
1324 bool IsSpecialIndex(String string) {
1325  // Max length of canonical double: -X.XXXXXXXXXXXXXXXXX-eXXX
1326  const int kBufferSize = 24;
1327  const int length = string->length();
1328  if (length == 0 || length > kBufferSize) return false;
1329  uint16_t buffer[kBufferSize];
1330  String::WriteToFlat(string, buffer, 0, length);
1331  // If the first char is not a digit or a '-' or we can't match 'NaN' or
1332  // '(-)Infinity', bailout immediately.
1333  int offset = 0;
1334  if (!IsDecimalDigit(buffer[0])) {
1335  if (buffer[0] == '-') {
1336  if (length == 1) return false; // Just '-' is bad.
1337  if (!IsDecimalDigit(buffer[1])) {
1338  if (buffer[1] == 'I' && length == 9) {
1339  // Allow matching of '-Infinity' below.
1340  } else {
1341  return false;
1342  }
1343  }
1344  offset++;
1345  } else if (buffer[0] == 'I' && length == 8) {
1346  // Allow matching of 'Infinity' below.
1347  } else if (buffer[0] == 'N' && length == 3) {
1348  // Match NaN.
1349  return buffer[1] == 'a' && buffer[2] == 'N';
1350  } else {
1351  return false;
1352  }
1353  }
1354  // Expected fast path: key is an integer.
1355  static const int kRepresentableIntegerLength = 15; // (-)XXXXXXXXXXXXXXX
1356  if (length - offset <= kRepresentableIntegerLength) {
1357  const int initial_offset = offset;
1358  bool matches = true;
1359  for (; offset < length; offset++) {
1360  matches &= IsDecimalDigit(buffer[offset]);
1361  }
1362  if (matches) {
1363  // Match 0 and -0.
1364  if (buffer[initial_offset] == '0') return initial_offset == length - 1;
1365  return true;
1366  }
1367  }
1368  // Slow path: test DoubleToString(StringToDouble(string)) == string.
1369  Vector<const uint16_t> vector(buffer, length);
1370  double d = StringToDouble(vector, NO_FLAGS);
1371  if (std::isnan(d)) return false;
1372  // Compute reverse string.
1373  char reverse_buffer[kBufferSize + 1]; // Result will be /0 terminated.
1374  Vector<char> reverse_vector(reverse_buffer, arraysize(reverse_buffer));
1375  const char* reverse_string = DoubleToCString(d, reverse_vector);
1376  for (int i = 0; i < length; ++i) {
1377  if (static_cast<uint16_t>(reverse_string[i]) != buffer[i]) return false;
1378  }
1379  return true;
1380 }
1381 } // namespace internal
1382 } // namespace v8
Definition: libplatform.h:13