mfbt/double-conversion/double-conversion.cc

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/mfbt/double-conversion/double-conversion.cc	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,892 @@
     1.4 +// Copyright 2010 the V8 project authors. All rights reserved.
     1.5 +// Redistribution and use in source and binary forms, with or without
     1.6 +// modification, are permitted provided that the following conditions are
     1.7 +// met:
     1.8 +//
     1.9 +//     * Redistributions of source code must retain the above copyright
    1.10 +//       notice, this list of conditions and the following disclaimer.
    1.11 +//     * Redistributions in binary form must reproduce the above
    1.12 +//       copyright notice, this list of conditions and the following
    1.13 +//       disclaimer in the documentation and/or other materials provided
    1.14 +//       with the distribution.
    1.15 +//     * Neither the name of Google Inc. nor the names of its
    1.16 +//       contributors may be used to endorse or promote products derived
    1.17 +//       from this software without specific prior written permission.
    1.18 +//
    1.19 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    1.20 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    1.21 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    1.22 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    1.23 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    1.24 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    1.25 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    1.26 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    1.27 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    1.28 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    1.29 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    1.30 +
    1.31 +#include <limits.h>
    1.32 +#include <math.h>
    1.33 +
    1.34 +#include "double-conversion.h"
    1.35 +
    1.36 +#include "bignum-dtoa.h"
    1.37 +#include "fast-dtoa.h"
    1.38 +#include "fixed-dtoa.h"
    1.39 +#include "ieee.h"
    1.40 +#include "strtod.h"
    1.41 +#include "utils.h"
    1.42 +
    1.43 +namespace double_conversion {
    1.44 +
    1.45 +const DoubleToStringConverter& DoubleToStringConverter::EcmaScriptConverter() {
    1.46 +  int flags = UNIQUE_ZERO | EMIT_POSITIVE_EXPONENT_SIGN;
    1.47 +  static DoubleToStringConverter converter(flags,
    1.48 +                                           "Infinity",
    1.49 +                                           "NaN",
    1.50 +                                           'e',
    1.51 +                                           -6, 21,
    1.52 +                                           6, 0);
    1.53 +  return converter;
    1.54 +}
    1.55 +
    1.56 +
    1.57 +bool DoubleToStringConverter::HandleSpecialValues(
    1.58 +    double value,
    1.59 +    StringBuilder* result_builder) const {
    1.60 +  Double double_inspect(value);
    1.61 +  if (double_inspect.IsInfinite()) {
    1.62 +    if (infinity_symbol_ == NULL) return false;
    1.63 +    if (value < 0) {
    1.64 +      result_builder->AddCharacter('-');
    1.65 +    }
    1.66 +    result_builder->AddString(infinity_symbol_);
    1.67 +    return true;
    1.68 +  }
    1.69 +  if (double_inspect.IsNan()) {
    1.70 +    if (nan_symbol_ == NULL) return false;
    1.71 +    result_builder->AddString(nan_symbol_);
    1.72 +    return true;
    1.73 +  }
    1.74 +  return false;
    1.75 +}
    1.76 +
    1.77 +
    1.78 +void DoubleToStringConverter::CreateExponentialRepresentation(
    1.79 +    const char* decimal_digits,
    1.80 +    int length,
    1.81 +    int exponent,
    1.82 +    StringBuilder* result_builder) const {
    1.83 +  ASSERT(length != 0);
    1.84 +  result_builder->AddCharacter(decimal_digits[0]);
    1.85 +  if (length != 1) {
    1.86 +    result_builder->AddCharacter('.');
    1.87 +    result_builder->AddSubstring(&decimal_digits[1], length-1);
    1.88 +  }
    1.89 +  result_builder->AddCharacter(exponent_character_);
    1.90 +  if (exponent < 0) {
    1.91 +    result_builder->AddCharacter('-');
    1.92 +    exponent = -exponent;
    1.93 +  } else {
    1.94 +    if ((flags_ & EMIT_POSITIVE_EXPONENT_SIGN) != 0) {
    1.95 +      result_builder->AddCharacter('+');
    1.96 +    }
    1.97 +  }
    1.98 +  if (exponent == 0) {
    1.99 +    result_builder->AddCharacter('0');
   1.100 +    return;
   1.101 +  }
   1.102 +  ASSERT(exponent < 1e4);
   1.103 +  const int kMaxExponentLength = 5;
   1.104 +  char buffer[kMaxExponentLength + 1];
   1.105 +  buffer[kMaxExponentLength] = '\0';
   1.106 +  int first_char_pos = kMaxExponentLength;
   1.107 +  while (exponent > 0) {
   1.108 +    buffer[--first_char_pos] = '0' + (exponent % 10);
   1.109 +    exponent /= 10;
   1.110 +  }
   1.111 +  result_builder->AddSubstring(&buffer[first_char_pos],
   1.112 +                               kMaxExponentLength - first_char_pos);
   1.113 +}
   1.114 +
   1.115 +
   1.116 +void DoubleToStringConverter::CreateDecimalRepresentation(
   1.117 +    const char* decimal_digits,
   1.118 +    int length,
   1.119 +    int decimal_point,
   1.120 +    int digits_after_point,
   1.121 +    StringBuilder* result_builder) const {
   1.122 +  // Create a representation that is padded with zeros if needed.
   1.123 +  if (decimal_point <= 0) {
   1.124 +      // "0.00000decimal_rep".
   1.125 +    result_builder->AddCharacter('0');
   1.126 +    if (digits_after_point > 0) {
   1.127 +      result_builder->AddCharacter('.');
   1.128 +      result_builder->AddPadding('0', -decimal_point);
   1.129 +      ASSERT(length <= digits_after_point - (-decimal_point));
   1.130 +      result_builder->AddSubstring(decimal_digits, length);
   1.131 +      int remaining_digits = digits_after_point - (-decimal_point) - length;
   1.132 +      result_builder->AddPadding('0', remaining_digits);
   1.133 +    }
   1.134 +  } else if (decimal_point >= length) {
   1.135 +    // "decimal_rep0000.00000" or "decimal_rep.0000"
   1.136 +    result_builder->AddSubstring(decimal_digits, length);
   1.137 +    result_builder->AddPadding('0', decimal_point - length);
   1.138 +    if (digits_after_point > 0) {
   1.139 +      result_builder->AddCharacter('.');
   1.140 +      result_builder->AddPadding('0', digits_after_point);
   1.141 +    }
   1.142 +  } else {
   1.143 +    // "decima.l_rep000"
   1.144 +    ASSERT(digits_after_point > 0);
   1.145 +    result_builder->AddSubstring(decimal_digits, decimal_point);
   1.146 +    result_builder->AddCharacter('.');
   1.147 +    ASSERT(length - decimal_point <= digits_after_point);
   1.148 +    result_builder->AddSubstring(&decimal_digits[decimal_point],
   1.149 +                                 length - decimal_point);
   1.150 +    int remaining_digits = digits_after_point - (length - decimal_point);
   1.151 +    result_builder->AddPadding('0', remaining_digits);
   1.152 +  }
   1.153 +  if (digits_after_point == 0) {
   1.154 +    if ((flags_ & EMIT_TRAILING_DECIMAL_POINT) != 0) {
   1.155 +      result_builder->AddCharacter('.');
   1.156 +    }
   1.157 +    if ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) {
   1.158 +      result_builder->AddCharacter('0');
   1.159 +    }
   1.160 +  }
   1.161 +}
   1.162 +
   1.163 +
   1.164 +bool DoubleToStringConverter::ToShortestIeeeNumber(
   1.165 +    double value,
   1.166 +    StringBuilder* result_builder,
   1.167 +    DoubleToStringConverter::DtoaMode mode) const {
   1.168 +  ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE);
   1.169 +  if (Double(value).IsSpecial()) {
   1.170 +    return HandleSpecialValues(value, result_builder);
   1.171 +  }
   1.172 +
   1.173 +  int decimal_point;
   1.174 +  bool sign;
   1.175 +  const int kDecimalRepCapacity = kBase10MaximalLength + 1;
   1.176 +  char decimal_rep[kDecimalRepCapacity];
   1.177 +  int decimal_rep_length;
   1.178 +
   1.179 +  DoubleToAscii(value, mode, 0, decimal_rep, kDecimalRepCapacity,
   1.180 +                &sign, &decimal_rep_length, &decimal_point);
   1.181 +
   1.182 +  bool unique_zero = (flags_ & UNIQUE_ZERO) != 0;
   1.183 +  if (sign && (value != 0.0 || !unique_zero)) {
   1.184 +    result_builder->AddCharacter('-');
   1.185 +  }
   1.186 +
   1.187 +  int exponent = decimal_point - 1;
   1.188 +  if ((decimal_in_shortest_low_ <= exponent) &&
   1.189 +      (exponent < decimal_in_shortest_high_)) {
   1.190 +    CreateDecimalRepresentation(decimal_rep, decimal_rep_length,
   1.191 +                                decimal_point,
   1.192 +                                Max(0, decimal_rep_length - decimal_point),
   1.193 +                                result_builder);
   1.194 +  } else {
   1.195 +    CreateExponentialRepresentation(decimal_rep, decimal_rep_length, exponent,
   1.196 +                                    result_builder);
   1.197 +  }
   1.198 +  return true;
   1.199 +}
   1.200 +
   1.201 +
   1.202 +bool DoubleToStringConverter::ToFixed(double value,
   1.203 +                                      int requested_digits,
   1.204 +                                      StringBuilder* result_builder) const {
   1.205 +  ASSERT(kMaxFixedDigitsBeforePoint == 60);
   1.206 +  const double kFirstNonFixed = 1e60;
   1.207 +
   1.208 +  if (Double(value).IsSpecial()) {
   1.209 +    return HandleSpecialValues(value, result_builder);
   1.210 +  }
   1.211 +
   1.212 +  if (requested_digits > kMaxFixedDigitsAfterPoint) return false;
   1.213 +  if (value >= kFirstNonFixed || value <= -kFirstNonFixed) return false;
   1.214 +
   1.215 +  // Find a sufficiently precise decimal representation of n.
   1.216 +  int decimal_point;
   1.217 +  bool sign;
   1.218 +  // Add space for the '\0' byte.
   1.219 +  const int kDecimalRepCapacity =
   1.220 +      kMaxFixedDigitsBeforePoint + kMaxFixedDigitsAfterPoint + 1;
   1.221 +  char decimal_rep[kDecimalRepCapacity];
   1.222 +  int decimal_rep_length;
   1.223 +  DoubleToAscii(value, FIXED, requested_digits,
   1.224 +                decimal_rep, kDecimalRepCapacity,
   1.225 +                &sign, &decimal_rep_length, &decimal_point);
   1.226 +
   1.227 +  bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
   1.228 +  if (sign && (value != 0.0 || !unique_zero)) {
   1.229 +    result_builder->AddCharacter('-');
   1.230 +  }
   1.231 +
   1.232 +  CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
   1.233 +                              requested_digits, result_builder);
   1.234 +  return true;
   1.235 +}
   1.236 +
   1.237 +
   1.238 +bool DoubleToStringConverter::ToExponential(
   1.239 +    double value,
   1.240 +    int requested_digits,
   1.241 +    StringBuilder* result_builder) const {
   1.242 +  if (Double(value).IsSpecial()) {
   1.243 +    return HandleSpecialValues(value, result_builder);
   1.244 +  }
   1.245 +
   1.246 +  if (requested_digits < -1) return false;
   1.247 +  if (requested_digits > kMaxExponentialDigits) return false;
   1.248 +
   1.249 +  int decimal_point;
   1.250 +  bool sign;
   1.251 +  // Add space for digit before the decimal point and the '\0' character.
   1.252 +  const int kDecimalRepCapacity = kMaxExponentialDigits + 2;
   1.253 +  ASSERT(kDecimalRepCapacity > kBase10MaximalLength);
   1.254 +  char decimal_rep[kDecimalRepCapacity];
   1.255 +  int decimal_rep_length;
   1.256 +
   1.257 +  if (requested_digits == -1) {
   1.258 +    DoubleToAscii(value, SHORTEST, 0,
   1.259 +                  decimal_rep, kDecimalRepCapacity,
   1.260 +                  &sign, &decimal_rep_length, &decimal_point);
   1.261 +  } else {
   1.262 +    DoubleToAscii(value, PRECISION, requested_digits + 1,
   1.263 +                  decimal_rep, kDecimalRepCapacity,
   1.264 +                  &sign, &decimal_rep_length, &decimal_point);
   1.265 +    ASSERT(decimal_rep_length <= requested_digits + 1);
   1.266 +
   1.267 +    for (int i = decimal_rep_length; i < requested_digits + 1; ++i) {
   1.268 +      decimal_rep[i] = '0';
   1.269 +    }
   1.270 +    decimal_rep_length = requested_digits + 1;
   1.271 +  }
   1.272 +
   1.273 +  bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
   1.274 +  if (sign && (value != 0.0 || !unique_zero)) {
   1.275 +    result_builder->AddCharacter('-');
   1.276 +  }
   1.277 +
   1.278 +  int exponent = decimal_point - 1;
   1.279 +  CreateExponentialRepresentation(decimal_rep,
   1.280 +                                  decimal_rep_length,
   1.281 +                                  exponent,
   1.282 +                                  result_builder);
   1.283 +  return true;
   1.284 +}
   1.285 +
   1.286 +
   1.287 +bool DoubleToStringConverter::ToPrecision(double value,
   1.288 +                                          int precision,
   1.289 +                                          bool* used_exponential_notation,
   1.290 +                                          StringBuilder* result_builder) const {
   1.291 +  *used_exponential_notation = false;
   1.292 +  if (Double(value).IsSpecial()) {
   1.293 +    return HandleSpecialValues(value, result_builder);
   1.294 +  }
   1.295 +
   1.296 +  if (precision < kMinPrecisionDigits || precision > kMaxPrecisionDigits) {
   1.297 +    return false;
   1.298 +  }
   1.299 +
   1.300 +  // Find a sufficiently precise decimal representation of n.
   1.301 +  int decimal_point;
   1.302 +  bool sign;
   1.303 +  // Add one for the terminating null character.
   1.304 +  const int kDecimalRepCapacity = kMaxPrecisionDigits + 1;
   1.305 +  char decimal_rep[kDecimalRepCapacity];
   1.306 +  int decimal_rep_length;
   1.307 +
   1.308 +  DoubleToAscii(value, PRECISION, precision,
   1.309 +                decimal_rep, kDecimalRepCapacity,
   1.310 +                &sign, &decimal_rep_length, &decimal_point);
   1.311 +  ASSERT(decimal_rep_length <= precision);
   1.312 +
   1.313 +  bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
   1.314 +  if (sign && (value != 0.0 || !unique_zero)) {
   1.315 +    result_builder->AddCharacter('-');
   1.316 +  }
   1.317 +
   1.318 +  // The exponent if we print the number as x.xxeyyy. That is with the
   1.319 +  // decimal point after the first digit.
   1.320 +  int exponent = decimal_point - 1;
   1.321 +
   1.322 +  int extra_zero = ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) ? 1 : 0;
   1.323 +  if ((-decimal_point + 1 > max_leading_padding_zeroes_in_precision_mode_) ||
   1.324 +      (decimal_point - precision + extra_zero >
   1.325 +       max_trailing_padding_zeroes_in_precision_mode_)) {
   1.326 +    // Fill buffer to contain 'precision' digits.
   1.327 +    // Usually the buffer is already at the correct length, but 'DoubleToAscii'
   1.328 +    // is allowed to return less characters.
   1.329 +    for (int i = decimal_rep_length; i < precision; ++i) {
   1.330 +      decimal_rep[i] = '0';
   1.331 +    }
   1.332 +
   1.333 +    *used_exponential_notation = true;
   1.334 +    CreateExponentialRepresentation(decimal_rep,
   1.335 +                                    precision,
   1.336 +                                    exponent,
   1.337 +                                    result_builder);
   1.338 +  } else {
   1.339 +    CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
   1.340 +                                Max(0, precision - decimal_point),
   1.341 +                                result_builder);
   1.342 +  }
   1.343 +  return true;
   1.344 +}
   1.345 +
   1.346 +
   1.347 +static BignumDtoaMode DtoaToBignumDtoaMode(
   1.348 +    DoubleToStringConverter::DtoaMode dtoa_mode) {
   1.349 +  switch (dtoa_mode) {
   1.350 +    case DoubleToStringConverter::SHORTEST:  return BIGNUM_DTOA_SHORTEST;
   1.351 +    case DoubleToStringConverter::SHORTEST_SINGLE:
   1.352 +        return BIGNUM_DTOA_SHORTEST_SINGLE;
   1.353 +    case DoubleToStringConverter::FIXED:     return BIGNUM_DTOA_FIXED;
   1.354 +    case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISION;
   1.355 +    default:
   1.356 +      UNREACHABLE();
   1.357 +      return BIGNUM_DTOA_SHORTEST;  // To silence compiler.
   1.358 +  }
   1.359 +}
   1.360 +
   1.361 +
   1.362 +void DoubleToStringConverter::DoubleToAscii(double v,
   1.363 +                                            DtoaMode mode,
   1.364 +                                            int requested_digits,
   1.365 +                                            char* buffer,
   1.366 +                                            int buffer_length,
   1.367 +                                            bool* sign,
   1.368 +                                            int* length,
   1.369 +                                            int* point) {
   1.370 +  Vector<char> vector(buffer, buffer_length);
   1.371 +  ASSERT(!Double(v).IsSpecial());
   1.372 +  ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE || requested_digits >= 0);
   1.373 +
   1.374 +  if (Double(v).Sign() < 0) {
   1.375 +    *sign = true;
   1.376 +    v = -v;
   1.377 +  } else {
   1.378 +    *sign = false;
   1.379 +  }
   1.380 +
   1.381 +  if (mode == PRECISION && requested_digits == 0) {
   1.382 +    vector[0] = '\0';
   1.383 +    *length = 0;
   1.384 +    return;
   1.385 +  }
   1.386 +
   1.387 +  if (v == 0) {
   1.388 +    vector[0] = '0';
   1.389 +    vector[1] = '\0';
   1.390 +    *length = 1;
   1.391 +    *point = 1;
   1.392 +    return;
   1.393 +  }
   1.394 +
   1.395 +  bool fast_worked;
   1.396 +  switch (mode) {
   1.397 +    case SHORTEST:
   1.398 +      fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST, 0, vector, length, point);
   1.399 +      break;
   1.400 +    case SHORTEST_SINGLE:
   1.401 +      fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST_SINGLE, 0,
   1.402 +                             vector, length, point);
   1.403 +      break;
   1.404 +    case FIXED:
   1.405 +      fast_worked = FastFixedDtoa(v, requested_digits, vector, length, point);
   1.406 +      break;
   1.407 +    case PRECISION:
   1.408 +      fast_worked = FastDtoa(v, FAST_DTOA_PRECISION, requested_digits,
   1.409 +                             vector, length, point);
   1.410 +      break;
   1.411 +    default:
   1.412 +      UNREACHABLE();
   1.413 +      fast_worked = false;
   1.414 +  }
   1.415 +  if (fast_worked) return;
   1.416 +
   1.417 +  // If the fast dtoa didn't succeed use the slower bignum version.
   1.418 +  BignumDtoaMode bignum_mode = DtoaToBignumDtoaMode(mode);
   1.419 +  BignumDtoa(v, bignum_mode, requested_digits, vector, length, point);
   1.420 +  vector[*length] = '\0';
   1.421 +}
   1.422 +
   1.423 +
   1.424 +// Consumes the given substring from the iterator.
   1.425 +// Returns false, if the substring does not match.
   1.426 +static bool ConsumeSubString(const char** current,
   1.427 +                             const char* end,
   1.428 +                             const char* substring) {
   1.429 +  ASSERT(**current == *substring);
   1.430 +  for (substring++; *substring != '\0'; substring++) {
   1.431 +    ++*current;
   1.432 +    if (*current == end || **current != *substring) return false;
   1.433 +  }
   1.434 +  ++*current;
   1.435 +  return true;
   1.436 +}
   1.437 +
   1.438 +
   1.439 +// Maximum number of significant digits in decimal representation.
   1.440 +// The longest possible double in decimal representation is
   1.441 +// (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074
   1.442 +// (768 digits). If we parse a number whose first digits are equal to a
   1.443 +// mean of 2 adjacent doubles (that could have up to 769 digits) the result
   1.444 +// must be rounded to the bigger one unless the tail consists of zeros, so
   1.445 +// we don't need to preserve all the digits.
   1.446 +const int kMaxSignificantDigits = 772;
   1.447 +
   1.448 +
   1.449 +// Returns true if a nonspace found and false if the end has reached.
   1.450 +static inline bool AdvanceToNonspace(const char** current, const char* end) {
   1.451 +  while (*current != end) {
   1.452 +    if (**current != ' ') return true;
   1.453 +    ++*current;
   1.454 +  }
   1.455 +  return false;
   1.456 +}
   1.457 +
   1.458 +
   1.459 +static bool isDigit(int x, int radix) {
   1.460 +  return (x >= '0' && x <= '9' && x < '0' + radix)
   1.461 +      || (radix > 10 && x >= 'a' && x < 'a' + radix - 10)
   1.462 +      || (radix > 10 && x >= 'A' && x < 'A' + radix - 10);
   1.463 +}
   1.464 +
   1.465 +
   1.466 +static double SignedZero(bool sign) {
   1.467 +  return sign ? -0.0 : 0.0;
   1.468 +}
   1.469 +
   1.470 +
   1.471 +// Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
   1.472 +template <int radix_log_2>
   1.473 +static double RadixStringToIeee(const char* current,
   1.474 +                                const char* end,
   1.475 +                                bool sign,
   1.476 +                                bool allow_trailing_junk,
   1.477 +                                double junk_string_value,
   1.478 +                                bool read_as_double,
   1.479 +                                const char** trailing_pointer) {
   1.480 +  ASSERT(current != end);
   1.481 +
   1.482 +  const int kDoubleSize = Double::kSignificandSize;
   1.483 +  const int kSingleSize = Single::kSignificandSize;
   1.484 +  const int kSignificandSize = read_as_double? kDoubleSize: kSingleSize;
   1.485 +
   1.486 +  // Skip leading 0s.
   1.487 +  while (*current == '0') {
   1.488 +    ++current;
   1.489 +    if (current == end) {
   1.490 +      *trailing_pointer = end;
   1.491 +      return SignedZero(sign);
   1.492 +    }
   1.493 +  }
   1.494 +
   1.495 +  int64_t number = 0;
   1.496 +  int exponent = 0;
   1.497 +  const int radix = (1 << radix_log_2);
   1.498 +
   1.499 +  do {
   1.500 +    int digit;
   1.501 +    if (*current >= '0' && *current <= '9' && *current < '0' + radix) {
   1.502 +      digit = static_cast<char>(*current) - '0';
   1.503 +    } else if (radix > 10 && *current >= 'a' && *current < 'a' + radix - 10) {
   1.504 +      digit = static_cast<char>(*current) - 'a' + 10;
   1.505 +    } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) {
   1.506 +      digit = static_cast<char>(*current) - 'A' + 10;
   1.507 +    } else {
   1.508 +      if (allow_trailing_junk || !AdvanceToNonspace(&current, end)) {
   1.509 +        break;
   1.510 +      } else {
   1.511 +        return junk_string_value;
   1.512 +      }
   1.513 +    }
   1.514 +
   1.515 +    number = number * radix + digit;
   1.516 +    int overflow = static_cast<int>(number >> kSignificandSize);
   1.517 +    if (overflow != 0) {
   1.518 +      // Overflow occurred. Need to determine which direction to round the
   1.519 +      // result.
   1.520 +      int overflow_bits_count = 1;
   1.521 +      while (overflow > 1) {
   1.522 +        overflow_bits_count++;
   1.523 +        overflow >>= 1;
   1.524 +      }
   1.525 +
   1.526 +      int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
   1.527 +      int dropped_bits = static_cast<int>(number) & dropped_bits_mask;
   1.528 +      number >>= overflow_bits_count;
   1.529 +      exponent = overflow_bits_count;
   1.530 +
   1.531 +      bool zero_tail = true;
   1.532 +      while (true) {
   1.533 +        ++current;
   1.534 +        if (current == end || !isDigit(*current, radix)) break;
   1.535 +        zero_tail = zero_tail && *current == '0';
   1.536 +        exponent += radix_log_2;
   1.537 +      }
   1.538 +
   1.539 +      if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
   1.540 +        return junk_string_value;
   1.541 +      }
   1.542 +
   1.543 +      int middle_value = (1 << (overflow_bits_count - 1));
   1.544 +      if (dropped_bits > middle_value) {
   1.545 +        number++;  // Rounding up.
   1.546 +      } else if (dropped_bits == middle_value) {
   1.547 +        // Rounding to even to consistency with decimals: half-way case rounds
   1.548 +        // up if significant part is odd and down otherwise.
   1.549 +        if ((number & 1) != 0 || !zero_tail) {
   1.550 +          number++;  // Rounding up.
   1.551 +        }
   1.552 +      }
   1.553 +
   1.554 +      // Rounding up may cause overflow.
   1.555 +      if ((number & ((int64_t)1 << kSignificandSize)) != 0) {
   1.556 +        exponent++;
   1.557 +        number >>= 1;
   1.558 +      }
   1.559 +      break;
   1.560 +    }
   1.561 +    ++current;
   1.562 +  } while (current != end);
   1.563 +
   1.564 +  ASSERT(number < ((int64_t)1 << kSignificandSize));
   1.565 +  ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number);
   1.566 +
   1.567 +  *trailing_pointer = current;
   1.568 +
   1.569 +  if (exponent == 0) {
   1.570 +    if (sign) {
   1.571 +      if (number == 0) return -0.0;
   1.572 +      number = -number;
   1.573 +    }
   1.574 +    return static_cast<double>(number);
   1.575 +  }
   1.576 +
   1.577 +  ASSERT(number != 0);
   1.578 +  return Double(DiyFp(number, exponent)).value();
   1.579 +}
   1.580 +
   1.581 +
   1.582 +double StringToDoubleConverter::StringToIeee(
   1.583 +    const char* input,
   1.584 +    int length,
   1.585 +    int* processed_characters_count,
   1.586 +    bool read_as_double) const {
   1.587 +  const char* current = input;
   1.588 +  const char* end = input + length;
   1.589 +
   1.590 +  *processed_characters_count = 0;
   1.591 +
   1.592 +  const bool allow_trailing_junk = (flags_ & ALLOW_TRAILING_JUNK) != 0;
   1.593 +  const bool allow_leading_spaces = (flags_ & ALLOW_LEADING_SPACES) != 0;
   1.594 +  const bool allow_trailing_spaces = (flags_ & ALLOW_TRAILING_SPACES) != 0;
   1.595 +  const bool allow_spaces_after_sign = (flags_ & ALLOW_SPACES_AFTER_SIGN) != 0;
   1.596 +
   1.597 +  // To make sure that iterator dereferencing is valid the following
   1.598 +  // convention is used:
   1.599 +  // 1. Each '++current' statement is followed by check for equality to 'end'.
   1.600 +  // 2. If AdvanceToNonspace returned false then current == end.
   1.601 +  // 3. If 'current' becomes equal to 'end' the function returns or goes to
   1.602 +  // 'parsing_done'.
   1.603 +  // 4. 'current' is not dereferenced after the 'parsing_done' label.
   1.604 +  // 5. Code before 'parsing_done' may rely on 'current != end'.
   1.605 +  if (current == end) return empty_string_value_;
   1.606 +
   1.607 +  if (allow_leading_spaces || allow_trailing_spaces) {
   1.608 +    if (!AdvanceToNonspace(&current, end)) {
   1.609 +      *processed_characters_count = current - input;
   1.610 +      return empty_string_value_;
   1.611 +    }
   1.612 +    if (!allow_leading_spaces && (input != current)) {
   1.613 +      // No leading spaces allowed, but AdvanceToNonspace moved forward.
   1.614 +      return junk_string_value_;
   1.615 +    }
   1.616 +  }
   1.617 +
   1.618 +  // The longest form of simplified number is: "-<significant digits>.1eXXX\0".
   1.619 +  const int kBufferSize = kMaxSignificantDigits + 10;
   1.620 +  char buffer[kBufferSize];  // NOLINT: size is known at compile time.
   1.621 +  int buffer_pos = 0;
   1.622 +
   1.623 +  // Exponent will be adjusted if insignificant digits of the integer part
   1.624 +  // or insignificant leading zeros of the fractional part are dropped.
   1.625 +  int exponent = 0;
   1.626 +  int significant_digits = 0;
   1.627 +  int insignificant_digits = 0;
   1.628 +  bool nonzero_digit_dropped = false;
   1.629 +
   1.630 +  bool sign = false;
   1.631 +
   1.632 +  if (*current == '+' || *current == '-') {
   1.633 +    sign = (*current == '-');
   1.634 +    ++current;
   1.635 +    const char* next_non_space = current;
   1.636 +    // Skip following spaces (if allowed).
   1.637 +    if (!AdvanceToNonspace(&next_non_space, end)) return junk_string_value_;
   1.638 +    if (!allow_spaces_after_sign && (current != next_non_space)) {
   1.639 +      return junk_string_value_;
   1.640 +    }
   1.641 +    current = next_non_space;
   1.642 +  }
   1.643 +
   1.644 +  if (infinity_symbol_ != NULL) {
   1.645 +    if (*current == infinity_symbol_[0]) {
   1.646 +      if (!ConsumeSubString(&current, end, infinity_symbol_)) {
   1.647 +        return junk_string_value_;
   1.648 +      }
   1.649 +
   1.650 +      if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
   1.651 +        return junk_string_value_;
   1.652 +      }
   1.653 +      if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
   1.654 +        return junk_string_value_;
   1.655 +      }
   1.656 +
   1.657 +      ASSERT(buffer_pos == 0);
   1.658 +      *processed_characters_count = current - input;
   1.659 +      return sign ? -Double::Infinity() : Double::Infinity();
   1.660 +    }
   1.661 +  }
   1.662 +
   1.663 +  if (nan_symbol_ != NULL) {
   1.664 +    if (*current == nan_symbol_[0]) {
   1.665 +      if (!ConsumeSubString(&current, end, nan_symbol_)) {
   1.666 +        return junk_string_value_;
   1.667 +      }
   1.668 +
   1.669 +      if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
   1.670 +        return junk_string_value_;
   1.671 +      }
   1.672 +      if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
   1.673 +        return junk_string_value_;
   1.674 +      }
   1.675 +
   1.676 +      ASSERT(buffer_pos == 0);
   1.677 +      *processed_characters_count = current - input;
   1.678 +      return sign ? -Double::NaN() : Double::NaN();
   1.679 +    }
   1.680 +  }
   1.681 +
   1.682 +  bool leading_zero = false;
   1.683 +  if (*current == '0') {
   1.684 +    ++current;
   1.685 +    if (current == end) {
   1.686 +      *processed_characters_count = current - input;
   1.687 +      return SignedZero(sign);
   1.688 +    }
   1.689 +
   1.690 +    leading_zero = true;
   1.691 +
   1.692 +    // It could be hexadecimal value.
   1.693 +    if ((flags_ & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {
   1.694 +      ++current;
   1.695 +      if (current == end || !isDigit(*current, 16)) {
   1.696 +        return junk_string_value_;  // "0x".
   1.697 +      }
   1.698 +
   1.699 +      const char* tail_pointer = NULL;
   1.700 +      double result = RadixStringToIeee<4>(current,
   1.701 +                                           end,
   1.702 +                                           sign,
   1.703 +                                           allow_trailing_junk,
   1.704 +                                           junk_string_value_,
   1.705 +                                           read_as_double,
   1.706 +                                           &tail_pointer);
   1.707 +      if (tail_pointer != NULL) {
   1.708 +        if (allow_trailing_spaces) AdvanceToNonspace(&tail_pointer, end);
   1.709 +        *processed_characters_count = tail_pointer - input;
   1.710 +      }
   1.711 +      return result;
   1.712 +    }
   1.713 +
   1.714 +    // Ignore leading zeros in the integer part.
   1.715 +    while (*current == '0') {
   1.716 +      ++current;
   1.717 +      if (current == end) {
   1.718 +        *processed_characters_count = current - input;
   1.719 +        return SignedZero(sign);
   1.720 +      }
   1.721 +    }
   1.722 +  }
   1.723 +
   1.724 +  bool octal = leading_zero && (flags_ & ALLOW_OCTALS) != 0;
   1.725 +
   1.726 +  // Copy significant digits of the integer part (if any) to the buffer.
   1.727 +  while (*current >= '0' && *current <= '9') {
   1.728 +    if (significant_digits < kMaxSignificantDigits) {
   1.729 +      ASSERT(buffer_pos < kBufferSize);
   1.730 +      buffer[buffer_pos++] = static_cast<char>(*current);
   1.731 +      significant_digits++;
   1.732 +      // Will later check if it's an octal in the buffer.
   1.733 +    } else {
   1.734 +      insignificant_digits++;  // Move the digit into the exponential part.
   1.735 +      nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
   1.736 +    }
   1.737 +    octal = octal && *current < '8';
   1.738 +    ++current;
   1.739 +    if (current == end) goto parsing_done;
   1.740 +  }
   1.741 +
   1.742 +  if (significant_digits == 0) {
   1.743 +    octal = false;
   1.744 +  }
   1.745 +
   1.746 +  if (*current == '.') {
   1.747 +    if (octal && !allow_trailing_junk) return junk_string_value_;
   1.748 +    if (octal) goto parsing_done;
   1.749 +
   1.750 +    ++current;
   1.751 +    if (current == end) {
   1.752 +      if (significant_digits == 0 && !leading_zero) {
   1.753 +        return junk_string_value_;
   1.754 +      } else {
   1.755 +        goto parsing_done;
   1.756 +      }
   1.757 +    }
   1.758 +
   1.759 +    if (significant_digits == 0) {
   1.760 +      // octal = false;
   1.761 +      // Integer part consists of 0 or is absent. Significant digits start after
   1.762 +      // leading zeros (if any).
   1.763 +      while (*current == '0') {
   1.764 +        ++current;
   1.765 +        if (current == end) {
   1.766 +          *processed_characters_count = current - input;
   1.767 +          return SignedZero(sign);
   1.768 +        }
   1.769 +        exponent--;  // Move this 0 into the exponent.
   1.770 +      }
   1.771 +    }
   1.772 +
   1.773 +    // There is a fractional part.
   1.774 +    // We don't emit a '.', but adjust the exponent instead.
   1.775 +    while (*current >= '0' && *current <= '9') {
   1.776 +      if (significant_digits < kMaxSignificantDigits) {
   1.777 +        ASSERT(buffer_pos < kBufferSize);
   1.778 +        buffer[buffer_pos++] = static_cast<char>(*current);
   1.779 +        significant_digits++;
   1.780 +        exponent--;
   1.781 +      } else {
   1.782 +        // Ignore insignificant digits in the fractional part.
   1.783 +        nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
   1.784 +      }
   1.785 +      ++current;
   1.786 +      if (current == end) goto parsing_done;
   1.787 +    }
   1.788 +  }
   1.789 +
   1.790 +  if (!leading_zero && exponent == 0 && significant_digits == 0) {
   1.791 +    // If leading_zeros is true then the string contains zeros.
   1.792 +    // If exponent < 0 then string was [+-]\.0*...
   1.793 +    // If significant_digits != 0 the string is not equal to 0.
   1.794 +    // Otherwise there are no digits in the string.
   1.795 +    return junk_string_value_;
   1.796 +  }
   1.797 +
   1.798 +  // Parse exponential part.
   1.799 +  if (*current == 'e' || *current == 'E') {
   1.800 +    if (octal && !allow_trailing_junk) return junk_string_value_;
   1.801 +    if (octal) goto parsing_done;
   1.802 +    ++current;
   1.803 +    if (current == end) {
   1.804 +      if (allow_trailing_junk) {
   1.805 +        goto parsing_done;
   1.806 +      } else {
   1.807 +        return junk_string_value_;
   1.808 +      }
   1.809 +    }
   1.810 +    char sign = '+';
   1.811 +    if (*current == '+' || *current == '-') {
   1.812 +      sign = static_cast<char>(*current);
   1.813 +      ++current;
   1.814 +      if (current == end) {
   1.815 +        if (allow_trailing_junk) {
   1.816 +          goto parsing_done;
   1.817 +        } else {
   1.818 +          return junk_string_value_;
   1.819 +        }
   1.820 +      }
   1.821 +    }
   1.822 +
   1.823 +    if (current == end || *current < '0' || *current > '9') {
   1.824 +      if (allow_trailing_junk) {
   1.825 +        goto parsing_done;
   1.826 +      } else {
   1.827 +        return junk_string_value_;
   1.828 +      }
   1.829 +    }
   1.830 +
   1.831 +    const int max_exponent = INT_MAX / 2;
   1.832 +    ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
   1.833 +    int num = 0;
   1.834 +    do {
   1.835 +      // Check overflow.
   1.836 +      int digit = *current - '0';
   1.837 +      if (num >= max_exponent / 10
   1.838 +          && !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
   1.839 +        num = max_exponent;
   1.840 +      } else {
   1.841 +        num = num * 10 + digit;
   1.842 +      }
   1.843 +      ++current;
   1.844 +    } while (current != end && *current >= '0' && *current <= '9');
   1.845 +
   1.846 +    exponent += (sign == '-' ? -num : num);
   1.847 +  }
   1.848 +
   1.849 +  if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
   1.850 +    return junk_string_value_;
   1.851 +  }
   1.852 +  if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
   1.853 +    return junk_string_value_;
   1.854 +  }
   1.855 +  if (allow_trailing_spaces) {
   1.856 +    AdvanceToNonspace(&current, end);
   1.857 +  }
   1.858 +
   1.859 +  parsing_done:
   1.860 +  exponent += insignificant_digits;
   1.861 +
   1.862 +  if (octal) {
   1.863 +    double result;
   1.864 +    const char* tail_pointer = NULL;
   1.865 +    result = RadixStringToIeee<3>(buffer,
   1.866 +                                  buffer + buffer_pos,
   1.867 +                                  sign,
   1.868 +                                  allow_trailing_junk,
   1.869 +                                  junk_string_value_,
   1.870 +                                  read_as_double,
   1.871 +                                  &tail_pointer);
   1.872 +    ASSERT(tail_pointer != NULL);
   1.873 +    *processed_characters_count = current - input;
   1.874 +    return result;
   1.875 +  }
   1.876 +
   1.877 +  if (nonzero_digit_dropped) {
   1.878 +    buffer[buffer_pos++] = '1';
   1.879 +    exponent--;
   1.880 +  }
   1.881 +
   1.882 +  ASSERT(buffer_pos < kBufferSize);
   1.883 +  buffer[buffer_pos] = '\0';
   1.884 +
   1.885 +  double converted;
   1.886 +  if (read_as_double) {
   1.887 +    converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
   1.888 +  } else {
   1.889 +    converted = Strtof(Vector<const char>(buffer, buffer_pos), exponent);
   1.890 +  }
   1.891 +  *processed_characters_count = current - input;
   1.892 +  return sign? -converted: converted;
   1.893 +}
   1.894 +
   1.895 +}  // namespace double_conversion

mercurial