| 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 |