Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(466)

Side by Side Diff: src/conversions.cc

Issue 3563009: Move gay_strtod outside conversions.cc. (Closed)
Patch Set: Created 10 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/SConscript ('k') | src/strtod.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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(&current, end)) { 350 if (!allow_trailing_junk && AdvanceToNonspace(&current, 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
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(&current, end)) return JUNK_STRING_VALUE; 463 if (!AdvanceToNonspace(&current, end)) return JUNK_STRING_VALUE;
464 } else if (*current == '-') { 464 } else if (*current == '-') {
465 buffer[buffer_pos++] = '-';
466 ++current; 465 ++current;
467 if (!AdvanceToNonspace(&current, end)) return JUNK_STRING_VALUE; 466 if (!AdvanceToNonspace(&current, 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(&current, end, kInfinitySymbol)) { 472 if (!SubStringEquals(&current, end, kInfinitySymbol)) {
474 return JUNK_STRING_VALUE; 473 return JUNK_STRING_VALUE;
475 } 474 }
476 475
477 if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) { 476 if (!allow_trailing_junk && AdvanceToNonspace(&current, 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
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
631 } 632 }
632 633
633 if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) { 634 if (!allow_trailing_junk && AdvanceToNonspace(&current, 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
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
OLDNEW
« no previous file with comments | « src/SConscript ('k') | src/strtod.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698