Bumping manifests a=b2g-bump
[gecko.git] / mfbt / double-conversion / double-conversion.cc
blob394b6a0538a90c9c448e4d9ceb154b8cc5b76d5b
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
4 // met:
5 //
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.
28 #include <limits.h>
29 #include <math.h>
31 #include "double-conversion.h"
33 #include "bignum-dtoa.h"
34 #include "fast-dtoa.h"
35 #include "fixed-dtoa.h"
36 #include "ieee.h"
37 #include "strtod.h"
38 #include "utils.h"
40 namespace double_conversion {
42 const DoubleToStringConverter& DoubleToStringConverter::EcmaScriptConverter() {
43 int flags = UNIQUE_ZERO | EMIT_POSITIVE_EXPONENT_SIGN;
44 static DoubleToStringConverter converter(flags,
45 "Infinity",
46 "NaN",
47 'e',
48 -6, 21,
49 6, 0);
50 return converter;
54 bool DoubleToStringConverter::HandleSpecialValues(
55 double value,
56 StringBuilder* result_builder) const {
57 Double double_inspect(value);
58 if (double_inspect.IsInfinite()) {
59 if (infinity_symbol_ == NULL) return false;
60 if (value < 0) {
61 result_builder->AddCharacter('-');
63 result_builder->AddString(infinity_symbol_);
64 return true;
66 if (double_inspect.IsNan()) {
67 if (nan_symbol_ == NULL) return false;
68 result_builder->AddString(nan_symbol_);
69 return true;
71 return false;
75 void DoubleToStringConverter::CreateExponentialRepresentation(
76 const char* decimal_digits,
77 int length,
78 int exponent,
79 StringBuilder* result_builder) const {
80 ASSERT(length != 0);
81 result_builder->AddCharacter(decimal_digits[0]);
82 if (length != 1) {
83 result_builder->AddCharacter('.');
84 result_builder->AddSubstring(&decimal_digits[1], length-1);
86 result_builder->AddCharacter(exponent_character_);
87 if (exponent < 0) {
88 result_builder->AddCharacter('-');
89 exponent = -exponent;
90 } else {
91 if ((flags_ & EMIT_POSITIVE_EXPONENT_SIGN) != 0) {
92 result_builder->AddCharacter('+');
95 if (exponent == 0) {
96 result_builder->AddCharacter('0');
97 return;
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);
106 exponent /= 10;
108 result_builder->AddSubstring(&buffer[first_char_pos],
109 kMaxExponentLength - first_char_pos);
113 void DoubleToStringConverter::CreateDecimalRepresentation(
114 const char* decimal_digits,
115 int length,
116 int decimal_point,
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);
139 } else {
140 // "decima.l_rep000"
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(
162 double value,
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);
170 int decimal_point;
171 bool sign;
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,
188 decimal_point,
189 Max(0, decimal_rep_length - decimal_point),
190 result_builder);
191 } else {
192 CreateExponentialRepresentation(decimal_rep, decimal_rep_length, exponent,
193 result_builder);
195 return true;
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.
213 int decimal_point;
214 bool sign;
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);
231 return true;
235 bool DoubleToStringConverter::ToExponential(
236 double value,
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;
246 int decimal_point;
247 bool sign;
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);
258 } else {
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,
277 decimal_rep_length,
278 exponent,
279 result_builder);
280 return true;
284 bool DoubleToStringConverter::ToPrecision(double value,
285 int precision,
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) {
294 return false;
297 // Find a sufficiently precise decimal representation of n.
298 int decimal_point;
299 bool sign;
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,
332 precision,
333 exponent,
334 result_builder);
335 } else {
336 CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
337 Max(0, precision - decimal_point),
338 result_builder);
340 return true;
344 static BignumDtoaMode DtoaToBignumDtoaMode(
345 DoubleToStringConverter::DtoaMode dtoa_mode) {
346 switch (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;
352 default:
353 UNREACHABLE();
354 return BIGNUM_DTOA_SHORTEST; // To silence compiler.
359 void DoubleToStringConverter::DoubleToAscii(double v,
360 DtoaMode mode,
361 int requested_digits,
362 char* buffer,
363 int buffer_length,
364 bool* sign,
365 int* length,
366 int* point) {
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) {
372 *sign = true;
373 v = -v;
374 } else {
375 *sign = false;
378 if (mode == PRECISION && requested_digits == 0) {
379 vector[0] = '\0';
380 *length = 0;
381 return;
384 if (v == 0) {
385 vector[0] = '0';
386 vector[1] = '\0';
387 *length = 1;
388 *point = 1;
389 return;
392 bool fast_worked;
393 switch (mode) {
394 case SHORTEST:
395 fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST, 0, vector, length, point);
396 break;
397 case SHORTEST_SINGLE:
398 fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST_SINGLE, 0,
399 vector, length, point);
400 break;
401 case FIXED:
402 fast_worked = FastFixedDtoa(v, requested_digits, vector, length, point);
403 break;
404 case PRECISION:
405 fast_worked = FastDtoa(v, FAST_DTOA_PRECISION, requested_digits,
406 vector, length, point);
407 break;
408 default:
409 UNREACHABLE();
410 fast_worked = false;
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,
424 const char* end,
425 const char* substring) {
426 ASSERT(**current == *substring);
427 for (substring++; *substring != '\0'; substring++) {
428 ++*current;
429 if (*current == end || **current != *substring) return false;
431 ++*current;
432 return true;
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;
450 ++*current;
452 return false;
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,
471 const char* end,
472 bool sign,
473 bool allow_trailing_junk,
474 double junk_string_value,
475 bool read_as_double,
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;
483 // Skip leading 0s.
484 while (*current == '0') {
485 ++current;
486 if (current == end) {
487 *trailing_pointer = end;
488 return SignedZero(sign);
492 int64_t number = 0;
493 int exponent = 0;
494 const int radix = (1 << radix_log_2);
496 do {
497 int digit;
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;
504 } else {
505 if (allow_trailing_junk || !AdvanceToNonspace(&current, end)) {
506 break;
507 } else {
508 return junk_string_value;
512 number = number * radix + digit;
513 int overflow = static_cast<int>(number >> kSignificandSize);
514 if (overflow != 0) {
515 // Overflow occurred. Need to determine which direction to round the
516 // result.
517 int overflow_bits_count = 1;
518 while (overflow > 1) {
519 overflow_bits_count++;
520 overflow >>= 1;
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;
529 while (true) {
530 ++current;
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(&current, 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) {
553 exponent++;
554 number >>= 1;
556 break;
558 ++current;
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;
566 if (exponent == 0) {
567 if (sign) {
568 if (number == 0) return -0.0;
569 number = -number;
571 return static_cast<double>(number);
574 ASSERT(number != 0);
575 return Double(DiyFp(number, exponent)).value();
579 double StringToDoubleConverter::StringToIeee(
580 const char* input,
581 int length,
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
599 // 'parsing_done'.
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(&current, 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.
618 int buffer_pos = 0;
620 // Exponent will be adjusted if insignificant digits of the integer part
621 // or insignificant leading zeros of the fractional part are dropped.
622 int exponent = 0;
623 int significant_digits = 0;
624 int insignificant_digits = 0;
625 bool nonzero_digit_dropped = false;
627 bool sign = false;
629 if (*current == '+' || *current == '-') {
630 sign = (*current == '-');
631 ++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(&current, 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(&current, 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(&current, 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(&current, 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') {
681 ++current;
682 if (current == end) {
683 *processed_characters_count = current - input;
684 return SignedZero(sign);
687 leading_zero = true;
689 // It could be hexadecimal value.
690 if ((flags_ & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {
691 ++current;
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,
698 end,
699 sign,
700 allow_trailing_junk,
701 junk_string_value_,
702 read_as_double,
703 &tail_pointer);
704 if (tail_pointer != NULL) {
705 if (allow_trailing_spaces) AdvanceToNonspace(&tail_pointer, end);
706 *processed_characters_count = tail_pointer - input;
708 return result;
711 // Ignore leading zeros in the integer part.
712 while (*current == '0') {
713 ++current;
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.
730 } else {
731 insignificant_digits++; // Move the digit into the exponential part.
732 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
734 octal = octal && *current < '8';
735 ++current;
736 if (current == end) goto parsing_done;
739 if (significant_digits == 0) {
740 octal = false;
743 if (*current == '.') {
744 if (octal && !allow_trailing_junk) return junk_string_value_;
745 if (octal) goto parsing_done;
747 ++current;
748 if (current == end) {
749 if (significant_digits == 0 && !leading_zero) {
750 return junk_string_value_;
751 } else {
752 goto parsing_done;
756 if (significant_digits == 0) {
757 // octal = false;
758 // Integer part consists of 0 or is absent. Significant digits start after
759 // leading zeros (if any).
760 while (*current == '0') {
761 ++current;
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++;
777 exponent--;
778 } else {
779 // Ignore insignificant digits in the fractional part.
780 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
782 ++current;
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;
799 ++current;
800 if (current == end) {
801 if (allow_trailing_junk) {
802 goto parsing_done;
803 } else {
804 return junk_string_value_;
807 char sign = '+';
808 if (*current == '+' || *current == '-') {
809 sign = static_cast<char>(*current);
810 ++current;
811 if (current == end) {
812 if (allow_trailing_junk) {
813 goto parsing_done;
814 } else {
815 return junk_string_value_;
820 if (current == end || *current < '0' || *current > '9') {
821 if (allow_trailing_junk) {
822 goto parsing_done;
823 } else {
824 return junk_string_value_;
828 const int max_exponent = INT_MAX / 2;
829 ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
830 int num = 0;
831 do {
832 // Check overflow.
833 int digit = *current - '0';
834 if (num >= max_exponent / 10
835 && !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
836 num = max_exponent;
837 } else {
838 num = num * 10 + digit;
840 ++current;
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(&current, end)) {
850 return junk_string_value_;
852 if (allow_trailing_spaces) {
853 AdvanceToNonspace(&current, end);
856 parsing_done:
857 exponent += insignificant_digits;
859 if (octal) {
860 double result;
861 const char* tail_pointer = NULL;
862 result = RadixStringToIeee<3>(buffer,
863 buffer + buffer_pos,
864 sign,
865 allow_trailing_junk,
866 junk_string_value_,
867 read_as_double,
868 &tail_pointer);
869 ASSERT(tail_pointer != NULL);
870 *processed_characters_count = current - input;
871 return result;
874 if (nonzero_digit_dropped) {
875 buffer[buffer_pos++] = '1';
876 exponent--;
879 ASSERT(buffer_pos < kBufferSize);
880 buffer[buffer_pos] = '\0';
882 double converted;
883 if (read_as_double) {
884 converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
885 } else {
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