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