1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "double-conversion.h"
33 #include "bignum-dtoa.h"
34 #include "fast-dtoa.h"
35 #include "fixed-dtoa.h"
40 namespace double_conversion
{
42 const DoubleToStringConverter
& DoubleToStringConverter::EcmaScriptConverter() {
43 int flags
= UNIQUE_ZERO
| EMIT_POSITIVE_EXPONENT_SIGN
;
44 static DoubleToStringConverter
converter(flags
,
54 bool DoubleToStringConverter::HandleSpecialValues(
56 StringBuilder
* result_builder
) const {
57 Double
double_inspect(value
);
58 if (double_inspect
.IsInfinite()) {
59 if (infinity_symbol_
== NULL
) return false;
61 result_builder
->AddCharacter('-');
63 result_builder
->AddString(infinity_symbol_
);
66 if (double_inspect
.IsNan()) {
67 if (nan_symbol_
== NULL
) return false;
68 result_builder
->AddString(nan_symbol_
);
75 void DoubleToStringConverter::CreateExponentialRepresentation(
76 const char* decimal_digits
,
79 StringBuilder
* result_builder
) const {
81 result_builder
->AddCharacter(decimal_digits
[0]);
83 result_builder
->AddCharacter('.');
84 result_builder
->AddSubstring(&decimal_digits
[1], length
-1);
86 result_builder
->AddCharacter(exponent_character_
);
88 result_builder
->AddCharacter('-');
91 if ((flags_
& EMIT_POSITIVE_EXPONENT_SIGN
) != 0) {
92 result_builder
->AddCharacter('+');
96 result_builder
->AddCharacter('0');
99 ASSERT(exponent
< 1e4
);
100 const int kMaxExponentLength
= 5;
101 char buffer
[kMaxExponentLength
+ 1];
102 buffer
[kMaxExponentLength
] = '\0';
103 int first_char_pos
= kMaxExponentLength
;
104 while (exponent
> 0) {
105 buffer
[--first_char_pos
] = '0' + (exponent
% 10);
108 result_builder
->AddSubstring(&buffer
[first_char_pos
],
109 kMaxExponentLength
- first_char_pos
);
113 void DoubleToStringConverter::CreateDecimalRepresentation(
114 const char* decimal_digits
,
117 int digits_after_point
,
118 StringBuilder
* result_builder
) const {
119 // Create a representation that is padded with zeros if needed.
120 if (decimal_point
<= 0) {
121 // "0.00000decimal_rep".
122 result_builder
->AddCharacter('0');
123 if (digits_after_point
> 0) {
124 result_builder
->AddCharacter('.');
125 result_builder
->AddPadding('0', -decimal_point
);
126 ASSERT(length
<= digits_after_point
- (-decimal_point
));
127 result_builder
->AddSubstring(decimal_digits
, length
);
128 int remaining_digits
= digits_after_point
- (-decimal_point
) - length
;
129 result_builder
->AddPadding('0', remaining_digits
);
131 } else if (decimal_point
>= length
) {
132 // "decimal_rep0000.00000" or "decimal_rep.0000"
133 result_builder
->AddSubstring(decimal_digits
, length
);
134 result_builder
->AddPadding('0', decimal_point
- length
);
135 if (digits_after_point
> 0) {
136 result_builder
->AddCharacter('.');
137 result_builder
->AddPadding('0', digits_after_point
);
141 ASSERT(digits_after_point
> 0);
142 result_builder
->AddSubstring(decimal_digits
, decimal_point
);
143 result_builder
->AddCharacter('.');
144 ASSERT(length
- decimal_point
<= digits_after_point
);
145 result_builder
->AddSubstring(&decimal_digits
[decimal_point
],
146 length
- decimal_point
);
147 int remaining_digits
= digits_after_point
- (length
- decimal_point
);
148 result_builder
->AddPadding('0', remaining_digits
);
150 if (digits_after_point
== 0) {
151 if ((flags_
& EMIT_TRAILING_DECIMAL_POINT
) != 0) {
152 result_builder
->AddCharacter('.');
154 if ((flags_
& EMIT_TRAILING_ZERO_AFTER_POINT
) != 0) {
155 result_builder
->AddCharacter('0');
161 bool DoubleToStringConverter::ToShortestIeeeNumber(
163 StringBuilder
* result_builder
,
164 DoubleToStringConverter::DtoaMode mode
) const {
165 ASSERT(mode
== SHORTEST
|| mode
== SHORTEST_SINGLE
);
166 if (Double(value
).IsSpecial()) {
167 return HandleSpecialValues(value
, result_builder
);
172 const int kDecimalRepCapacity
= kBase10MaximalLength
+ 1;
173 char decimal_rep
[kDecimalRepCapacity
];
174 int decimal_rep_length
;
176 DoubleToAscii(value
, mode
, 0, decimal_rep
, kDecimalRepCapacity
,
177 &sign
, &decimal_rep_length
, &decimal_point
);
179 bool unique_zero
= (flags_
& UNIQUE_ZERO
) != 0;
180 if (sign
&& (value
!= 0.0 || !unique_zero
)) {
181 result_builder
->AddCharacter('-');
184 int exponent
= decimal_point
- 1;
185 if ((decimal_in_shortest_low_
<= exponent
) &&
186 (exponent
< decimal_in_shortest_high_
)) {
187 CreateDecimalRepresentation(decimal_rep
, decimal_rep_length
,
189 Max(0, decimal_rep_length
- decimal_point
),
192 CreateExponentialRepresentation(decimal_rep
, decimal_rep_length
, exponent
,
199 bool DoubleToStringConverter::ToFixed(double value
,
200 int requested_digits
,
201 StringBuilder
* result_builder
) const {
202 ASSERT(kMaxFixedDigitsBeforePoint
== 60);
203 const double kFirstNonFixed
= 1e60
;
205 if (Double(value
).IsSpecial()) {
206 return HandleSpecialValues(value
, result_builder
);
209 if (requested_digits
> kMaxFixedDigitsAfterPoint
) return false;
210 if (value
>= kFirstNonFixed
|| value
<= -kFirstNonFixed
) return false;
212 // Find a sufficiently precise decimal representation of n.
215 // Add space for the '\0' byte.
216 const int kDecimalRepCapacity
=
217 kMaxFixedDigitsBeforePoint
+ kMaxFixedDigitsAfterPoint
+ 1;
218 char decimal_rep
[kDecimalRepCapacity
];
219 int decimal_rep_length
;
220 DoubleToAscii(value
, FIXED
, requested_digits
,
221 decimal_rep
, kDecimalRepCapacity
,
222 &sign
, &decimal_rep_length
, &decimal_point
);
224 bool unique_zero
= ((flags_
& UNIQUE_ZERO
) != 0);
225 if (sign
&& (value
!= 0.0 || !unique_zero
)) {
226 result_builder
->AddCharacter('-');
229 CreateDecimalRepresentation(decimal_rep
, decimal_rep_length
, decimal_point
,
230 requested_digits
, result_builder
);
235 bool DoubleToStringConverter::ToExponential(
237 int requested_digits
,
238 StringBuilder
* result_builder
) const {
239 if (Double(value
).IsSpecial()) {
240 return HandleSpecialValues(value
, result_builder
);
243 if (requested_digits
< -1) return false;
244 if (requested_digits
> kMaxExponentialDigits
) return false;
248 // Add space for digit before the decimal point and the '\0' character.
249 const int kDecimalRepCapacity
= kMaxExponentialDigits
+ 2;
250 ASSERT(kDecimalRepCapacity
> kBase10MaximalLength
);
251 char decimal_rep
[kDecimalRepCapacity
];
252 int decimal_rep_length
;
254 if (requested_digits
== -1) {
255 DoubleToAscii(value
, SHORTEST
, 0,
256 decimal_rep
, kDecimalRepCapacity
,
257 &sign
, &decimal_rep_length
, &decimal_point
);
259 DoubleToAscii(value
, PRECISION
, requested_digits
+ 1,
260 decimal_rep
, kDecimalRepCapacity
,
261 &sign
, &decimal_rep_length
, &decimal_point
);
262 ASSERT(decimal_rep_length
<= requested_digits
+ 1);
264 for (int i
= decimal_rep_length
; i
< requested_digits
+ 1; ++i
) {
265 decimal_rep
[i
] = '0';
267 decimal_rep_length
= requested_digits
+ 1;
270 bool unique_zero
= ((flags_
& UNIQUE_ZERO
) != 0);
271 if (sign
&& (value
!= 0.0 || !unique_zero
)) {
272 result_builder
->AddCharacter('-');
275 int exponent
= decimal_point
- 1;
276 CreateExponentialRepresentation(decimal_rep
,
284 bool DoubleToStringConverter::ToPrecision(double value
,
286 bool* used_exponential_notation
,
287 StringBuilder
* result_builder
) const {
288 *used_exponential_notation
= false;
289 if (Double(value
).IsSpecial()) {
290 return HandleSpecialValues(value
, result_builder
);
293 if (precision
< kMinPrecisionDigits
|| precision
> kMaxPrecisionDigits
) {
297 // Find a sufficiently precise decimal representation of n.
300 // Add one for the terminating null character.
301 const int kDecimalRepCapacity
= kMaxPrecisionDigits
+ 1;
302 char decimal_rep
[kDecimalRepCapacity
];
303 int decimal_rep_length
;
305 DoubleToAscii(value
, PRECISION
, precision
,
306 decimal_rep
, kDecimalRepCapacity
,
307 &sign
, &decimal_rep_length
, &decimal_point
);
308 ASSERT(decimal_rep_length
<= precision
);
310 bool unique_zero
= ((flags_
& UNIQUE_ZERO
) != 0);
311 if (sign
&& (value
!= 0.0 || !unique_zero
)) {
312 result_builder
->AddCharacter('-');
315 // The exponent if we print the number as x.xxeyyy. That is with the
316 // decimal point after the first digit.
317 int exponent
= decimal_point
- 1;
319 int extra_zero
= ((flags_
& EMIT_TRAILING_ZERO_AFTER_POINT
) != 0) ? 1 : 0;
320 if ((-decimal_point
+ 1 > max_leading_padding_zeroes_in_precision_mode_
) ||
321 (decimal_point
- precision
+ extra_zero
>
322 max_trailing_padding_zeroes_in_precision_mode_
)) {
323 // Fill buffer to contain 'precision' digits.
324 // Usually the buffer is already at the correct length, but 'DoubleToAscii'
325 // is allowed to return less characters.
326 for (int i
= decimal_rep_length
; i
< precision
; ++i
) {
327 decimal_rep
[i
] = '0';
330 *used_exponential_notation
= true;
331 CreateExponentialRepresentation(decimal_rep
,
336 CreateDecimalRepresentation(decimal_rep
, decimal_rep_length
, decimal_point
,
337 Max(0, precision
- decimal_point
),
344 static BignumDtoaMode
DtoaToBignumDtoaMode(
345 DoubleToStringConverter::DtoaMode dtoa_mode
) {
347 case DoubleToStringConverter::SHORTEST
: return BIGNUM_DTOA_SHORTEST
;
348 case DoubleToStringConverter::SHORTEST_SINGLE
:
349 return BIGNUM_DTOA_SHORTEST_SINGLE
;
350 case DoubleToStringConverter::FIXED
: return BIGNUM_DTOA_FIXED
;
351 case DoubleToStringConverter::PRECISION
: return BIGNUM_DTOA_PRECISION
;
354 return BIGNUM_DTOA_SHORTEST
; // To silence compiler.
359 void DoubleToStringConverter::DoubleToAscii(double v
,
361 int requested_digits
,
367 Vector
<char> vector(buffer
, buffer_length
);
368 ASSERT(!Double(v
).IsSpecial());
369 ASSERT(mode
== SHORTEST
|| mode
== SHORTEST_SINGLE
|| requested_digits
>= 0);
371 if (Double(v
).Sign() < 0) {
378 if (mode
== PRECISION
&& requested_digits
== 0) {
395 fast_worked
= FastDtoa(v
, FAST_DTOA_SHORTEST
, 0, vector
, length
, point
);
397 case SHORTEST_SINGLE
:
398 fast_worked
= FastDtoa(v
, FAST_DTOA_SHORTEST_SINGLE
, 0,
399 vector
, length
, point
);
402 fast_worked
= FastFixedDtoa(v
, requested_digits
, vector
, length
, point
);
405 fast_worked
= FastDtoa(v
, FAST_DTOA_PRECISION
, requested_digits
,
406 vector
, length
, point
);
412 if (fast_worked
) return;
414 // If the fast dtoa didn't succeed use the slower bignum version.
415 BignumDtoaMode bignum_mode
= DtoaToBignumDtoaMode(mode
);
416 BignumDtoa(v
, bignum_mode
, requested_digits
, vector
, length
, point
);
417 vector
[*length
] = '\0';
421 // Consumes the given substring from the iterator.
422 // Returns false, if the substring does not match.
423 static bool ConsumeSubString(const char** current
,
425 const char* substring
) {
426 ASSERT(**current
== *substring
);
427 for (substring
++; *substring
!= '\0'; substring
++) {
429 if (*current
== end
|| **current
!= *substring
) return false;
436 // Maximum number of significant digits in decimal representation.
437 // The longest possible double in decimal representation is
438 // (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074
439 // (768 digits). If we parse a number whose first digits are equal to a
440 // mean of 2 adjacent doubles (that could have up to 769 digits) the result
441 // must be rounded to the bigger one unless the tail consists of zeros, so
442 // we don't need to preserve all the digits.
443 const int kMaxSignificantDigits
= 772;
446 // Returns true if a nonspace found and false if the end has reached.
447 static inline bool AdvanceToNonspace(const char** current
, const char* end
) {
448 while (*current
!= end
) {
449 if (**current
!= ' ') return true;
456 static bool isDigit(int x
, int radix
) {
457 return (x
>= '0' && x
<= '9' && x
< '0' + radix
)
458 || (radix
> 10 && x
>= 'a' && x
< 'a' + radix
- 10)
459 || (radix
> 10 && x
>= 'A' && x
< 'A' + radix
- 10);
463 static double SignedZero(bool sign
) {
464 return sign
? -0.0 : 0.0;
468 // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
469 template <int radix_log_2
>
470 static double RadixStringToIeee(const char* current
,
473 bool allow_trailing_junk
,
474 double junk_string_value
,
476 const char** trailing_pointer
) {
477 ASSERT(current
!= end
);
479 const int kDoubleSize
= Double::kSignificandSize
;
480 const int kSingleSize
= Single::kSignificandSize
;
481 const int kSignificandSize
= read_as_double
? kDoubleSize
: kSingleSize
;
484 while (*current
== '0') {
486 if (current
== end
) {
487 *trailing_pointer
= end
;
488 return SignedZero(sign
);
494 const int radix
= (1 << radix_log_2
);
498 if (*current
>= '0' && *current
<= '9' && *current
< '0' + radix
) {
499 digit
= static_cast<char>(*current
) - '0';
500 } else if (radix
> 10 && *current
>= 'a' && *current
< 'a' + radix
- 10) {
501 digit
= static_cast<char>(*current
) - 'a' + 10;
502 } else if (radix
> 10 && *current
>= 'A' && *current
< 'A' + radix
- 10) {
503 digit
= static_cast<char>(*current
) - 'A' + 10;
505 if (allow_trailing_junk
|| !AdvanceToNonspace(¤t
, end
)) {
508 return junk_string_value
;
512 number
= number
* radix
+ digit
;
513 int overflow
= static_cast<int>(number
>> kSignificandSize
);
515 // Overflow occurred. Need to determine which direction to round the
517 int overflow_bits_count
= 1;
518 while (overflow
> 1) {
519 overflow_bits_count
++;
523 int dropped_bits_mask
= ((1 << overflow_bits_count
) - 1);
524 int dropped_bits
= static_cast<int>(number
) & dropped_bits_mask
;
525 number
>>= overflow_bits_count
;
526 exponent
= overflow_bits_count
;
528 bool zero_tail
= true;
531 if (current
== end
|| !isDigit(*current
, radix
)) break;
532 zero_tail
= zero_tail
&& *current
== '0';
533 exponent
+= radix_log_2
;
536 if (!allow_trailing_junk
&& AdvanceToNonspace(¤t
, end
)) {
537 return junk_string_value
;
540 int middle_value
= (1 << (overflow_bits_count
- 1));
541 if (dropped_bits
> middle_value
) {
542 number
++; // Rounding up.
543 } else if (dropped_bits
== middle_value
) {
544 // Rounding to even to consistency with decimals: half-way case rounds
545 // up if significant part is odd and down otherwise.
546 if ((number
& 1) != 0 || !zero_tail
) {
547 number
++; // Rounding up.
551 // Rounding up may cause overflow.
552 if ((number
& ((int64_t)1 << kSignificandSize
)) != 0) {
559 } while (current
!= end
);
561 ASSERT(number
< ((int64_t)1 << kSignificandSize
));
562 ASSERT(static_cast<int64_t>(static_cast<double>(number
)) == number
);
564 *trailing_pointer
= current
;
568 if (number
== 0) return -0.0;
571 return static_cast<double>(number
);
575 return Double(DiyFp(number
, exponent
)).value();
579 double StringToDoubleConverter::StringToIeee(
582 int* processed_characters_count
,
583 bool read_as_double
) const {
584 const char* current
= input
;
585 const char* end
= input
+ length
;
587 *processed_characters_count
= 0;
589 const bool allow_trailing_junk
= (flags_
& ALLOW_TRAILING_JUNK
) != 0;
590 const bool allow_leading_spaces
= (flags_
& ALLOW_LEADING_SPACES
) != 0;
591 const bool allow_trailing_spaces
= (flags_
& ALLOW_TRAILING_SPACES
) != 0;
592 const bool allow_spaces_after_sign
= (flags_
& ALLOW_SPACES_AFTER_SIGN
) != 0;
594 // To make sure that iterator dereferencing is valid the following
595 // convention is used:
596 // 1. Each '++current' statement is followed by check for equality to 'end'.
597 // 2. If AdvanceToNonspace returned false then current == end.
598 // 3. If 'current' becomes equal to 'end' the function returns or goes to
600 // 4. 'current' is not dereferenced after the 'parsing_done' label.
601 // 5. Code before 'parsing_done' may rely on 'current != end'.
602 if (current
== end
) return empty_string_value_
;
604 if (allow_leading_spaces
|| allow_trailing_spaces
) {
605 if (!AdvanceToNonspace(¤t
, end
)) {
606 *processed_characters_count
= current
- input
;
607 return empty_string_value_
;
609 if (!allow_leading_spaces
&& (input
!= current
)) {
610 // No leading spaces allowed, but AdvanceToNonspace moved forward.
611 return junk_string_value_
;
615 // The longest form of simplified number is: "-<significant digits>.1eXXX\0".
616 const int kBufferSize
= kMaxSignificantDigits
+ 10;
617 char buffer
[kBufferSize
]; // NOLINT: size is known at compile time.
620 // Exponent will be adjusted if insignificant digits of the integer part
621 // or insignificant leading zeros of the fractional part are dropped.
623 int significant_digits
= 0;
624 int insignificant_digits
= 0;
625 bool nonzero_digit_dropped
= false;
629 if (*current
== '+' || *current
== '-') {
630 sign
= (*current
== '-');
632 const char* next_non_space
= current
;
633 // Skip following spaces (if allowed).
634 if (!AdvanceToNonspace(&next_non_space
, end
)) return junk_string_value_
;
635 if (!allow_spaces_after_sign
&& (current
!= next_non_space
)) {
636 return junk_string_value_
;
638 current
= next_non_space
;
641 if (infinity_symbol_
!= NULL
) {
642 if (*current
== infinity_symbol_
[0]) {
643 if (!ConsumeSubString(¤t
, end
, infinity_symbol_
)) {
644 return junk_string_value_
;
647 if (!(allow_trailing_spaces
|| allow_trailing_junk
) && (current
!= end
)) {
648 return junk_string_value_
;
650 if (!allow_trailing_junk
&& AdvanceToNonspace(¤t
, end
)) {
651 return junk_string_value_
;
654 ASSERT(buffer_pos
== 0);
655 *processed_characters_count
= current
- input
;
656 return sign
? -Double::Infinity() : Double::Infinity();
660 if (nan_symbol_
!= NULL
) {
661 if (*current
== nan_symbol_
[0]) {
662 if (!ConsumeSubString(¤t
, end
, nan_symbol_
)) {
663 return junk_string_value_
;
666 if (!(allow_trailing_spaces
|| allow_trailing_junk
) && (current
!= end
)) {
667 return junk_string_value_
;
669 if (!allow_trailing_junk
&& AdvanceToNonspace(¤t
, end
)) {
670 return junk_string_value_
;
673 ASSERT(buffer_pos
== 0);
674 *processed_characters_count
= current
- input
;
675 return sign
? -Double::NaN() : Double::NaN();
679 bool leading_zero
= false;
680 if (*current
== '0') {
682 if (current
== end
) {
683 *processed_characters_count
= current
- input
;
684 return SignedZero(sign
);
689 // It could be hexadecimal value.
690 if ((flags_
& ALLOW_HEX
) && (*current
== 'x' || *current
== 'X')) {
692 if (current
== end
|| !isDigit(*current
, 16)) {
693 return junk_string_value_
; // "0x".
696 const char* tail_pointer
= NULL
;
697 double result
= RadixStringToIeee
<4>(current
,
704 if (tail_pointer
!= NULL
) {
705 if (allow_trailing_spaces
) AdvanceToNonspace(&tail_pointer
, end
);
706 *processed_characters_count
= tail_pointer
- input
;
711 // Ignore leading zeros in the integer part.
712 while (*current
== '0') {
714 if (current
== end
) {
715 *processed_characters_count
= current
- input
;
716 return SignedZero(sign
);
721 bool octal
= leading_zero
&& (flags_
& ALLOW_OCTALS
) != 0;
723 // Copy significant digits of the integer part (if any) to the buffer.
724 while (*current
>= '0' && *current
<= '9') {
725 if (significant_digits
< kMaxSignificantDigits
) {
726 ASSERT(buffer_pos
< kBufferSize
);
727 buffer
[buffer_pos
++] = static_cast<char>(*current
);
728 significant_digits
++;
729 // Will later check if it's an octal in the buffer.
731 insignificant_digits
++; // Move the digit into the exponential part.
732 nonzero_digit_dropped
= nonzero_digit_dropped
|| *current
!= '0';
734 octal
= octal
&& *current
< '8';
736 if (current
== end
) goto parsing_done
;
739 if (significant_digits
== 0) {
743 if (*current
== '.') {
744 if (octal
&& !allow_trailing_junk
) return junk_string_value_
;
745 if (octal
) goto parsing_done
;
748 if (current
== end
) {
749 if (significant_digits
== 0 && !leading_zero
) {
750 return junk_string_value_
;
756 if (significant_digits
== 0) {
758 // Integer part consists of 0 or is absent. Significant digits start after
759 // leading zeros (if any).
760 while (*current
== '0') {
762 if (current
== end
) {
763 *processed_characters_count
= current
- input
;
764 return SignedZero(sign
);
766 exponent
--; // Move this 0 into the exponent.
770 // There is a fractional part.
771 // We don't emit a '.', but adjust the exponent instead.
772 while (*current
>= '0' && *current
<= '9') {
773 if (significant_digits
< kMaxSignificantDigits
) {
774 ASSERT(buffer_pos
< kBufferSize
);
775 buffer
[buffer_pos
++] = static_cast<char>(*current
);
776 significant_digits
++;
779 // Ignore insignificant digits in the fractional part.
780 nonzero_digit_dropped
= nonzero_digit_dropped
|| *current
!= '0';
783 if (current
== end
) goto parsing_done
;
787 if (!leading_zero
&& exponent
== 0 && significant_digits
== 0) {
788 // If leading_zeros is true then the string contains zeros.
789 // If exponent < 0 then string was [+-]\.0*...
790 // If significant_digits != 0 the string is not equal to 0.
791 // Otherwise there are no digits in the string.
792 return junk_string_value_
;
795 // Parse exponential part.
796 if (*current
== 'e' || *current
== 'E') {
797 if (octal
&& !allow_trailing_junk
) return junk_string_value_
;
798 if (octal
) goto parsing_done
;
800 if (current
== end
) {
801 if (allow_trailing_junk
) {
804 return junk_string_value_
;
808 if (*current
== '+' || *current
== '-') {
809 sign
= static_cast<char>(*current
);
811 if (current
== end
) {
812 if (allow_trailing_junk
) {
815 return junk_string_value_
;
820 if (current
== end
|| *current
< '0' || *current
> '9') {
821 if (allow_trailing_junk
) {
824 return junk_string_value_
;
828 const int max_exponent
= INT_MAX
/ 2;
829 ASSERT(-max_exponent
/ 2 <= exponent
&& exponent
<= max_exponent
/ 2);
833 int digit
= *current
- '0';
834 if (num
>= max_exponent
/ 10
835 && !(num
== max_exponent
/ 10 && digit
<= max_exponent
% 10)) {
838 num
= num
* 10 + digit
;
841 } while (current
!= end
&& *current
>= '0' && *current
<= '9');
843 exponent
+= (sign
== '-' ? -num
: num
);
846 if (!(allow_trailing_spaces
|| allow_trailing_junk
) && (current
!= end
)) {
847 return junk_string_value_
;
849 if (!allow_trailing_junk
&& AdvanceToNonspace(¤t
, end
)) {
850 return junk_string_value_
;
852 if (allow_trailing_spaces
) {
853 AdvanceToNonspace(¤t
, end
);
857 exponent
+= insignificant_digits
;
861 const char* tail_pointer
= NULL
;
862 result
= RadixStringToIeee
<3>(buffer
,
869 ASSERT(tail_pointer
!= NULL
);
870 *processed_characters_count
= current
- input
;
874 if (nonzero_digit_dropped
) {
875 buffer
[buffer_pos
++] = '1';
879 ASSERT(buffer_pos
< kBufferSize
);
880 buffer
[buffer_pos
] = '\0';
883 if (read_as_double
) {
884 converted
= Strtod(Vector
<const char>(buffer
, buffer_pos
), exponent
);
886 converted
= Strtof(Vector
<const char>(buffer
, buffer_pos
), exponent
);
888 *processed_characters_count
= current
- input
;
889 return sign
? -converted
: converted
;
892 } // namespace double_conversion