mfbt/double-conversion/double-conversion.cc

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

     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.
    15 //
    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;
    51 }
    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('-');
    62     }
    63     result_builder->AddString(infinity_symbol_);
    64     return true;
    65   }
    66   if (double_inspect.IsNan()) {
    67     if (nan_symbol_ == NULL) return false;
    68     result_builder->AddString(nan_symbol_);
    69     return true;
    70   }
    71   return false;
    72 }
    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);
    85   }
    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('+');
    93     }
    94   }
    95   if (exponent == 0) {
    96     result_builder->AddCharacter('0');
    97     return;
    98   }
    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;
   107   }
   108   result_builder->AddSubstring(&buffer[first_char_pos],
   109                                kMaxExponentLength - first_char_pos);
   110 }
   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);
   130     }
   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);
   138     }
   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);
   149   }
   150   if (digits_after_point == 0) {
   151     if ((flags_ & EMIT_TRAILING_DECIMAL_POINT) != 0) {
   152       result_builder->AddCharacter('.');
   153     }
   154     if ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) {
   155       result_builder->AddCharacter('0');
   156     }
   157   }
   158 }
   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);
   168   }
   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('-');
   182   }
   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);
   194   }
   195   return true;
   196 }
   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);
   207   }
   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('-');
   227   }
   229   CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
   230                               requested_digits, result_builder);
   231   return true;
   232 }
   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);
   241   }
   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';
   266     }
   267     decimal_rep_length = requested_digits + 1;
   268   }
   270   bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
   271   if (sign && (value != 0.0 || !unique_zero)) {
   272     result_builder->AddCharacter('-');
   273   }
   275   int exponent = decimal_point - 1;
   276   CreateExponentialRepresentation(decimal_rep,
   277                                   decimal_rep_length,
   278                                   exponent,
   279                                   result_builder);
   280   return true;
   281 }
   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);
   291   }
   293   if (precision < kMinPrecisionDigits || precision > kMaxPrecisionDigits) {
   294     return false;
   295   }
   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('-');
   313   }
   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';
   328     }
   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);
   339   }
   340   return true;
   341 }
   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.
   355   }
   356 }
   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;
   376   }
   378   if (mode == PRECISION && requested_digits == 0) {
   379     vector[0] = '\0';
   380     *length = 0;
   381     return;
   382   }
   384   if (v == 0) {
   385     vector[0] = '0';
   386     vector[1] = '\0';
   387     *length = 1;
   388     *point = 1;
   389     return;
   390   }
   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;
   411   }
   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';
   418 }
   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;
   430   }
   431   ++*current;
   432   return true;
   433 }
   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;
   451   }
   452   return false;
   453 }
   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);
   460 }
   463 static double SignedZero(bool sign) {
   464   return sign ? -0.0 : 0.0;
   465 }
   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);
   489     }
   490   }
   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;
   509       }
   510     }
   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;
   521       }
   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;
   534       }
   536       if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
   537         return junk_string_value;
   538       }
   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.
   548         }
   549       }
   551       // Rounding up may cause overflow.
   552       if ((number & ((int64_t)1 << kSignificandSize)) != 0) {
   553         exponent++;
   554         number >>= 1;
   555       }
   556       break;
   557     }
   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;
   570     }
   571     return static_cast<double>(number);
   572   }
   574   ASSERT(number != 0);
   575   return Double(DiyFp(number, exponent)).value();
   576 }
   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_;
   608     }
   609     if (!allow_leading_spaces && (input != current)) {
   610       // No leading spaces allowed, but AdvanceToNonspace moved forward.
   611       return junk_string_value_;
   612     }
   613   }
   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_;
   637     }
   638     current = next_non_space;
   639   }
   641   if (infinity_symbol_ != NULL) {
   642     if (*current == infinity_symbol_[0]) {
   643       if (!ConsumeSubString(&current, end, infinity_symbol_)) {
   644         return junk_string_value_;
   645       }
   647       if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
   648         return junk_string_value_;
   649       }
   650       if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
   651         return junk_string_value_;
   652       }
   654       ASSERT(buffer_pos == 0);
   655       *processed_characters_count = current - input;
   656       return sign ? -Double::Infinity() : Double::Infinity();
   657     }
   658   }
   660   if (nan_symbol_ != NULL) {
   661     if (*current == nan_symbol_[0]) {
   662       if (!ConsumeSubString(&current, end, nan_symbol_)) {
   663         return junk_string_value_;
   664       }
   666       if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
   667         return junk_string_value_;
   668       }
   669       if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
   670         return junk_string_value_;
   671       }
   673       ASSERT(buffer_pos == 0);
   674       *processed_characters_count = current - input;
   675       return sign ? -Double::NaN() : Double::NaN();
   676     }
   677   }
   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);
   685     }
   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".
   694       }
   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;
   707       }
   708       return result;
   709     }
   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);
   717       }
   718     }
   719   }
   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';
   733     }
   734     octal = octal && *current < '8';
   735     ++current;
   736     if (current == end) goto parsing_done;
   737   }
   739   if (significant_digits == 0) {
   740     octal = false;
   741   }
   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;
   753       }
   754     }
   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);
   765         }
   766         exponent--;  // Move this 0 into the exponent.
   767       }
   768     }
   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';
   781       }
   782       ++current;
   783       if (current == end) goto parsing_done;
   784     }
   785   }
   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_;
   793   }
   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_;
   805       }
   806     }
   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_;
   816         }
   817       }
   818     }
   820     if (current == end || *current < '0' || *current > '9') {
   821       if (allow_trailing_junk) {
   822         goto parsing_done;
   823       } else {
   824         return junk_string_value_;
   825       }
   826     }
   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;
   839       }
   840       ++current;
   841     } while (current != end && *current >= '0' && *current <= '9');
   843     exponent += (sign == '-' ? -num : num);
   844   }
   846   if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
   847     return junk_string_value_;
   848   }
   849   if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
   850     return junk_string_value_;
   851   }
   852   if (allow_trailing_spaces) {
   853     AdvanceToNonspace(&current, end);
   854   }
   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;
   872   }
   874   if (nonzero_digit_dropped) {
   875     buffer[buffer_pos++] = '1';
   876     exponent--;
   877   }
   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);
   887   }
   888   *processed_characters_count = current - input;
   889   return sign? -converted: converted;
   890 }
   892 }  // namespace double_conversion

mercurial