OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 16 matching lines...) Expand all Loading... |
27 | 27 |
28 #include <stdarg.h> | 28 #include <stdarg.h> |
29 #include <limits.h> | 29 #include <limits.h> |
30 | 30 |
31 #include "v8.h" | 31 #include "v8.h" |
32 | 32 |
33 #include "conversions-inl.h" | 33 #include "conversions-inl.h" |
34 #include "dtoa.h" | 34 #include "dtoa.h" |
35 #include "factory.h" | 35 #include "factory.h" |
36 #include "scanner.h" | 36 #include "scanner.h" |
| 37 #include "strtod.h" |
37 | 38 |
38 namespace v8 { | 39 namespace v8 { |
39 namespace internal { | 40 namespace internal { |
40 | 41 |
41 int HexValue(uc32 c) { | 42 int HexValue(uc32 c) { |
42 if ('0' <= c && c <= '9') | 43 if ('0' <= c && c <= '9') |
43 return c - '0'; | 44 return c - '0'; |
44 if ('a' <= c && c <= 'f') | 45 if ('a' <= c && c <= 'f') |
45 return c - 'a' + 10; | 46 return c - 'a' + 10; |
46 if ('A' <= c && c <= 'F') | 47 if ('A' <= c && c <= 'F') |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
96 ASSERT(**current == *substring); | 97 ASSERT(**current == *substring); |
97 for (substring++; *substring != '\0'; substring++) { | 98 for (substring++; *substring != '\0'; substring++) { |
98 ++*current; | 99 ++*current; |
99 if (*current == end || **current != *substring) return false; | 100 if (*current == end || **current != *substring) return false; |
100 } | 101 } |
101 ++*current; | 102 ++*current; |
102 return true; | 103 return true; |
103 } | 104 } |
104 | 105 |
105 | 106 |
106 extern "C" double gay_strtod(const char* s00, const char** se); | |
107 | |
108 // Maximum number of significant digits in decimal representation. | 107 // Maximum number of significant digits in decimal representation. |
109 // The longest possible double in decimal representation is | 108 // The longest possible double in decimal representation is |
110 // (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074 | 109 // (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074 |
111 // (768 digits). If we parse a number whose first digits are equal to a | 110 // (768 digits). If we parse a number whose first digits are equal to a |
112 // mean of 2 adjacent doubles (that could have up to 769 digits) the result | 111 // mean of 2 adjacent doubles (that could have up to 769 digits) the result |
113 // must be rounded to the bigger one unless the tail consists of zeros, so | 112 // must be rounded to the bigger one unless the tail consists of zeros, so |
114 // we don't need to preserve all the digits. | 113 // we don't need to preserve all the digits. |
115 const int kMaxSignificantDigits = 772; | 114 const int kMaxSignificantDigits = 772; |
116 | 115 |
117 | 116 |
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
346 } | 345 } |
347 ++current; | 346 ++current; |
348 if (current == end) break; | 347 if (current == end) break; |
349 } | 348 } |
350 | 349 |
351 if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { | 350 if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { |
352 return JUNK_STRING_VALUE; | 351 return JUNK_STRING_VALUE; |
353 } | 352 } |
354 | 353 |
355 ASSERT(buffer_pos < kBufferSize); | 354 ASSERT(buffer_pos < kBufferSize); |
356 buffer[buffer_pos++] = '\0'; | 355 buffer[buffer_pos] = '\0'; |
357 return sign ? -gay_strtod(buffer, NULL) : gay_strtod(buffer, NULL); | 356 Vector<char> buffer_vector(buffer, buffer_pos); |
| 357 return sign ? -strtod(buffer_vector, NULL) : strtod(buffer_vector, NULL); |
358 } | 358 } |
359 | 359 |
360 // The following code causes accumulating rounding error for numbers greater | 360 // The following code causes accumulating rounding error for numbers greater |
361 // than ~2^56. It's explicitly allowed in the spec: "if R is not 2, 4, 8, 10, | 361 // than ~2^56. It's explicitly allowed in the spec: "if R is not 2, 4, 8, 10, |
362 // 16, or 32, then mathInt may be an implementation-dependent approximation to | 362 // 16, or 32, then mathInt may be an implementation-dependent approximation to |
363 // the mathematical integer value" (15.1.2.2). | 363 // the mathematical integer value" (15.1.2.2). |
364 | 364 |
365 int lim_0 = '0' + (radix < 10 ? radix : 10); | 365 int lim_0 = '0' + (radix < 10 ? radix : 10); |
366 int lim_a = 'a' + (radix - 10); | 366 int lim_a = 'a' + (radix - 10); |
367 int lim_A = 'A' + (radix - 10); | 367 int lim_A = 'A' + (radix - 10); |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
455 bool nonzero_digit_dropped = false; | 455 bool nonzero_digit_dropped = false; |
456 bool fractional_part = false; | 456 bool fractional_part = false; |
457 | 457 |
458 bool sign = false; | 458 bool sign = false; |
459 | 459 |
460 if (*current == '+') { | 460 if (*current == '+') { |
461 // Ignore leading sign; skip following spaces. | 461 // Ignore leading sign; skip following spaces. |
462 ++current; | 462 ++current; |
463 if (!AdvanceToNonspace(¤t, end)) return JUNK_STRING_VALUE; | 463 if (!AdvanceToNonspace(¤t, end)) return JUNK_STRING_VALUE; |
464 } else if (*current == '-') { | 464 } else if (*current == '-') { |
465 buffer[buffer_pos++] = '-'; | |
466 ++current; | 465 ++current; |
467 if (!AdvanceToNonspace(¤t, end)) return JUNK_STRING_VALUE; | 466 if (!AdvanceToNonspace(¤t, end)) return JUNK_STRING_VALUE; |
468 sign = true; | 467 sign = true; |
469 } | 468 } |
470 | 469 |
471 static const char kInfinitySymbol[] = "Infinity"; | 470 static const char kInfinitySymbol[] = "Infinity"; |
472 if (*current == kInfinitySymbol[0]) { | 471 if (*current == kInfinitySymbol[0]) { |
473 if (!SubStringEquals(¤t, end, kInfinitySymbol)) { | 472 if (!SubStringEquals(¤t, end, kInfinitySymbol)) { |
474 return JUNK_STRING_VALUE; | 473 return JUNK_STRING_VALUE; |
475 } | 474 } |
476 | 475 |
477 if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { | 476 if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { |
478 return JUNK_STRING_VALUE; | 477 return JUNK_STRING_VALUE; |
479 } | 478 } |
480 | 479 |
481 ASSERT(buffer_pos == 0 || buffer[0] == '-'); | 480 ASSERT(buffer_pos == 0); |
482 return buffer_pos > 0 ? -V8_INFINITY : V8_INFINITY; | 481 return sign ? -V8_INFINITY : V8_INFINITY; |
483 } | 482 } |
484 | 483 |
485 bool leading_zero = false; | 484 bool leading_zero = false; |
486 if (*current == '0') { | 485 if (*current == '0') { |
487 ++current; | 486 ++current; |
488 if (current == end) return SignedZero(sign); | 487 if (current == end) return SignedZero(sign); |
489 | 488 |
490 leading_zero = true; | 489 leading_zero = true; |
491 | 490 |
492 // It could be hexadecimal value. | 491 // It could be hexadecimal value. |
493 if ((flags & ALLOW_HEX) && (*current == 'x' || *current == 'X')) { | 492 if ((flags & ALLOW_HEX) && (*current == 'x' || *current == 'X')) { |
494 ++current; | 493 ++current; |
495 if (current == end || !isDigit(*current, 16)) { | 494 if (current == end || !isDigit(*current, 16)) { |
496 return JUNK_STRING_VALUE; // "0x". | 495 return JUNK_STRING_VALUE; // "0x". |
497 } | 496 } |
498 | 497 |
499 bool sign = (buffer_pos > 0 && buffer[0] == '-'); | |
500 return InternalStringToIntDouble<4>(current, | 498 return InternalStringToIntDouble<4>(current, |
501 end, | 499 end, |
502 sign, | 500 sign, |
503 allow_trailing_junk); | 501 allow_trailing_junk); |
504 } | 502 } |
505 | 503 |
506 // Ignore leading zeros in the integer part. | 504 // Ignore leading zeros in the integer part. |
507 while (*current == '0') { | 505 while (*current == '0') { |
508 ++current; | 506 ++current; |
509 if (current == end) return SignedZero(sign); | 507 if (current == end) return SignedZero(sign); |
(...skipping 16 matching lines...) Expand all Loading... |
526 octal = octal && *current < '8'; | 524 octal = octal && *current < '8'; |
527 ++current; | 525 ++current; |
528 if (current == end) goto parsing_done; | 526 if (current == end) goto parsing_done; |
529 } | 527 } |
530 | 528 |
531 if (significant_digits == 0) { | 529 if (significant_digits == 0) { |
532 octal = false; | 530 octal = false; |
533 } | 531 } |
534 | 532 |
535 if (*current == '.') { | 533 if (*current == '.') { |
| 534 if (octal && !allow_trailing_junk) return JUNK_STRING_VALUE; |
| 535 if (octal) goto parsing_done; |
| 536 |
536 ++current; | 537 ++current; |
537 if (current == end) { | 538 if (current == end) { |
538 if (significant_digits == 0 && !leading_zero) { | 539 if (significant_digits == 0 && !leading_zero) { |
539 return JUNK_STRING_VALUE; | 540 return JUNK_STRING_VALUE; |
540 } else { | 541 } else { |
541 goto parsing_done; | 542 goto parsing_done; |
542 } | 543 } |
543 } | 544 } |
544 | 545 |
545 if (significant_digits == 0) { | 546 if (significant_digits == 0) { |
546 // octal = false; | 547 // octal = false; |
547 // Integer part consists of 0 or is absent. Significant digits start after | 548 // Integer part consists of 0 or is absent. Significant digits start after |
548 // leading zeros (if any). | 549 // leading zeros (if any). |
549 while (*current == '0') { | 550 while (*current == '0') { |
550 ++current; | 551 ++current; |
551 if (current == end) return SignedZero(sign); | 552 if (current == end) return SignedZero(sign); |
552 exponent--; // Move this 0 into the exponent. | 553 exponent--; // Move this 0 into the exponent. |
553 } | 554 } |
554 } | 555 } |
555 | 556 |
556 ASSERT(buffer_pos < kBufferSize); | 557 // We don't emit a '.', but adjust the exponent instead. |
557 buffer[buffer_pos++] = '.'; | |
558 fractional_part = true; | 558 fractional_part = true; |
559 | 559 |
560 // There is the fractional part. | 560 // There is a fractional part. |
561 while (*current >= '0' && *current <= '9') { | 561 while (*current >= '0' && *current <= '9') { |
562 if (significant_digits < kMaxSignificantDigits) { | 562 if (significant_digits < kMaxSignificantDigits) { |
563 ASSERT(buffer_pos < kBufferSize); | 563 ASSERT(buffer_pos < kBufferSize); |
564 buffer[buffer_pos++] = static_cast<char>(*current); | 564 buffer[buffer_pos++] = static_cast<char>(*current); |
565 significant_digits++; | 565 significant_digits++; |
| 566 exponent--; |
566 } else { | 567 } else { |
567 // Ignore insignificant digits in the fractional part. | 568 // Ignore insignificant digits in the fractional part. |
568 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0'; | 569 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0'; |
569 } | 570 } |
570 ++current; | 571 ++current; |
571 if (current == end) goto parsing_done; | 572 if (current == end) goto parsing_done; |
572 } | 573 } |
573 } | 574 } |
574 | 575 |
575 if (!leading_zero && exponent == 0 && significant_digits == 0) { | 576 if (!leading_zero && exponent == 0 && significant_digits == 0) { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
631 } | 632 } |
632 | 633 |
633 if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { | 634 if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { |
634 return JUNK_STRING_VALUE; | 635 return JUNK_STRING_VALUE; |
635 } | 636 } |
636 | 637 |
637 parsing_done: | 638 parsing_done: |
638 exponent += insignificant_digits; | 639 exponent += insignificant_digits; |
639 | 640 |
640 if (octal) { | 641 if (octal) { |
641 bool sign = buffer[0] == '-'; | 642 return InternalStringToIntDouble<3>(buffer, |
642 int start_pos = (sign ? 1 : 0); | |
643 | |
644 return InternalStringToIntDouble<3>(buffer + start_pos, | |
645 buffer + buffer_pos, | 643 buffer + buffer_pos, |
646 sign, | 644 sign, |
647 allow_trailing_junk); | 645 allow_trailing_junk); |
648 } | 646 } |
649 | 647 |
650 if (nonzero_digit_dropped) { | 648 if (nonzero_digit_dropped) { |
651 if (insignificant_digits) buffer[buffer_pos++] = '.'; | |
652 buffer[buffer_pos++] = '1'; | 649 buffer[buffer_pos++] = '1'; |
653 } | 650 exponent--; |
654 | |
655 // If the number has no more than kMaxDigitsInInt digits and doesn't have | |
656 // fractional part it could be parsed faster (without checks for | |
657 // spaces, overflow, etc.). | |
658 const int kMaxDigitsInInt = 9 * sizeof(int) / 4; // NOLINT | |
659 | |
660 if (exponent != 0) { | |
661 ASSERT(buffer_pos < kBufferSize); | |
662 buffer[buffer_pos++] = 'e'; | |
663 if (exponent < 0) { | |
664 ASSERT(buffer_pos < kBufferSize); | |
665 buffer[buffer_pos++] = '-'; | |
666 exponent = -exponent; | |
667 } | |
668 | |
669 // The minimal/maximal double is +/-1.7e-308. Given that | |
670 // the buffer contains at most 773 (kMaxSignificantDigits + 1) the | |
671 // minimal possible exponent is hence -(308 + 773)=-1081. | |
672 // Since leading zeros are removed the maximal exponent cannot exceed 308. | |
673 // If the following test triggers the result will be +/-infinity or +/-0. | |
674 if (exponent > 9999) exponent = 9999; | |
675 | |
676 const int exp_digits = 4; | |
677 for (int i = 0; i < exp_digits; i++) { | |
678 buffer[buffer_pos + exp_digits - 1 - i] = '0' + exponent % 10; | |
679 exponent /= 10; | |
680 } | |
681 ASSERT(exponent == 0); | |
682 buffer_pos += exp_digits; | |
683 } else if (!fractional_part && significant_digits <= kMaxDigitsInInt) { | |
684 if (significant_digits == 0) return SignedZero(sign); | |
685 ASSERT(buffer_pos > 0); | |
686 int num = 0; | |
687 int start_pos = (buffer[0] == '-' ? 1 : 0); | |
688 for (int i = start_pos; i < buffer_pos; i++) { | |
689 ASSERT(buffer[i] >= '0' && buffer[i] <= '9'); | |
690 num = 10 * num + (buffer[i] - '0'); | |
691 } | |
692 return static_cast<double>(start_pos == 0 ? num : -num); | |
693 } | 651 } |
694 | 652 |
695 ASSERT(buffer_pos < kBufferSize); | 653 ASSERT(buffer_pos < kBufferSize); |
696 buffer[buffer_pos] = '\0'; | 654 buffer[buffer_pos] = '\0'; |
697 | 655 |
698 return gay_strtod(buffer, NULL); | 656 double converted = strtod(Vector<char>(buffer, buffer_pos), exponent); |
| 657 return sign? -converted: converted; |
699 } | 658 } |
700 | 659 |
| 660 |
701 double StringToDouble(String* str, int flags, double empty_string_val) { | 661 double StringToDouble(String* str, int flags, double empty_string_val) { |
702 StringShape shape(str); | 662 StringShape shape(str); |
703 if (shape.IsSequentialAscii()) { | 663 if (shape.IsSequentialAscii()) { |
704 const char* begin = SeqAsciiString::cast(str)->GetChars(); | 664 const char* begin = SeqAsciiString::cast(str)->GetChars(); |
705 const char* end = begin + str->length(); | 665 const char* end = begin + str->length(); |
706 return InternalStringToDouble(begin, end, flags, empty_string_val); | 666 return InternalStringToDouble(begin, end, flags, empty_string_val); |
707 } else if (shape.IsSequentialTwoByte()) { | 667 } else if (shape.IsSequentialTwoByte()) { |
708 const uc16* begin = SeqTwoByteString::cast(str)->GetChars(); | 668 const uc16* begin = SeqTwoByteString::cast(str)->GetChars(); |
709 const uc16* end = begin + str->length(); | 669 const uc16* end = begin + str->length(); |
710 return InternalStringToDouble(begin, end, flags, empty_string_val); | 670 return InternalStringToDouble(begin, end, flags, empty_string_val); |
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1171 // Allocate result and fill in the parts. | 1131 // Allocate result and fill in the parts. |
1172 StringBuilder builder(result_size + 1); | 1132 StringBuilder builder(result_size + 1); |
1173 builder.AddSubstring(integer_buffer + integer_pos + 1, integer_part_size); | 1133 builder.AddSubstring(integer_buffer + integer_pos + 1, integer_part_size); |
1174 if (decimal_pos > 0) builder.AddCharacter('.'); | 1134 if (decimal_pos > 0) builder.AddCharacter('.'); |
1175 builder.AddSubstring(decimal_buffer, decimal_pos); | 1135 builder.AddSubstring(decimal_buffer, decimal_pos); |
1176 return builder.Finalize(); | 1136 return builder.Finalize(); |
1177 } | 1137 } |
1178 | 1138 |
1179 | 1139 |
1180 } } // namespace v8::internal | 1140 } } // namespace v8::internal |
OLD | NEW |