Commits

Anonymous committed dbba162 Merge

.

Comments (0)

Files changed (6)

src/conversions.cc

-// Copyright 2006-2008 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include <stdarg.h>
-#include <limits.h>
-
-#include "v8.h"
-
-#include "conversions-inl.h"
-#include "dtoa.h"
-#include "factory.h"
-#include "scanner-base.h"
-#include "strtod.h"
-
-namespace v8 {
-namespace internal {
-
-namespace {
-
-// Maximum number of significant digits in decimal representation.
-// The longest possible double in decimal representation is
-// (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074
-// (768 digits). If we parse a number whose first digits are equal to a
-// mean of 2 adjacent doubles (that could have up to 769 digits) the result
-// must be rounded to the bigger one unless the tail consists of zeros, so
-// we don't need to preserve all the digits.
-const int kMaxSignificantDigits = 772;
-
-
-// Returns true if a nonspace found and false if the end has reached.
-template <class Iterator, class EndMark>
-static inline bool AdvanceToNonspace(Iterator* current, EndMark end) {
-  while (*current != end) {
-    if (!ScannerConstants::kIsWhiteSpace.get(**current)) return true;
-    ++*current;
-  }
-  return false;
-}
-
-
-static bool isDigit(int x, int radix) {
-  return (x >= '0' && x <= '9' && x < '0' + radix)
-      || (radix > 10 && x >= 'a' && x < 'a' + radix - 10)
-      || (radix > 10 && x >= 'A' && x < 'A' + radix - 10);
-}
-
-
-static double SignedZero(bool sign) {
-  return sign ? -0.0 : 0.0;
-}
-
-
-// Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
-template <int radix_log_2, class Iterator, class EndMark>
-static double InternalStringToIntDouble(Iterator current,
-                                        EndMark end,
-                                        bool sign,
-                                        bool allow_trailing_junk) {
-  ASSERT(current != end);
-
-  // Skip leading 0s.
-  while (*current == '0') {
-    ++current;
-    if (current == end) return SignedZero(sign);
-  }
-
-  int64_t number = 0;
-  int exponent = 0;
-  const int radix = (1 << radix_log_2);
-
-  do {
-    int digit;
-    if (*current >= '0' && *current <= '9' && *current < '0' + radix) {
-      digit = static_cast<char>(*current) - '0';
-    } else if (radix > 10 && *current >= 'a' && *current < 'a' + radix - 10) {
-      digit = static_cast<char>(*current) - 'a' + 10;
-    } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) {
-      digit = static_cast<char>(*current) - 'A' + 10;
-    } else {
-      if (allow_trailing_junk || !AdvanceToNonspace(&current, end)) {
-        break;
-      } else {
-        return JUNK_STRING_VALUE;
-      }
-    }
-
-    number = number * radix + digit;
-    int overflow = static_cast<int>(number >> 53);
-    if (overflow != 0) {
-      // Overflow occurred. Need to determine which direction to round the
-      // result.
-      int overflow_bits_count = 1;
-      while (overflow > 1) {
-        overflow_bits_count++;
-        overflow >>= 1;
-      }
-
-      int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
-      int dropped_bits = static_cast<int>(number) & dropped_bits_mask;
-      number >>= overflow_bits_count;
-      exponent = overflow_bits_count;
-
-      bool zero_tail = true;
-      while (true) {
-        ++current;
-        if (current == end || !isDigit(*current, radix)) break;
-        zero_tail = zero_tail && *current == '0';
-        exponent += radix_log_2;
-      }
-
-      if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
-        return JUNK_STRING_VALUE;
-      }
-
-      int middle_value = (1 << (overflow_bits_count - 1));
-      if (dropped_bits > middle_value) {
-        number++;  // Rounding up.
-      } else if (dropped_bits == middle_value) {
-        // Rounding to even to consistency with decimals: half-way case rounds
-        // up if significant part is odd and down otherwise.
-        if ((number & 1) != 0 || !zero_tail) {
-          number++;  // Rounding up.
-        }
-      }
-
-      // Rounding up may cause overflow.
-      if ((number & ((int64_t)1 << 53)) != 0) {
-        exponent++;
-        number >>= 1;
-      }
-      break;
-    }
-    ++current;
-  } while (current != end);
-
-  ASSERT(number < ((int64_t)1 << 53));
-  ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number);
-
-  if (exponent == 0) {
-    if (sign) {
-      if (number == 0) return -0.0;
-      number = -number;
-    }
-    return static_cast<double>(number);
-  }
-
-  ASSERT(number != 0);
-  // The double could be constructed faster from number (mantissa), exponent
-  // and sign. Assuming it's a rare case more simple code is used.
-  return static_cast<double>(sign ? -number : number) * pow(2.0, exponent);
-}
-
-
-// Converts a string to a double value. Assumes the Iterator supports
-// the following operations:
-// 1. current == end (other ops are not allowed), current != end.
-// 2. *current - gets the current character in the sequence.
-// 3. ++current (advances the position).
-template <class Iterator, class EndMark>
-static double InternalStringToDouble(Iterator current,
-                                     EndMark end,
-                                     int flags,
-                                     double empty_string_val) {
-  // To make sure that iterator dereferencing is valid the following
-  // convention is used:
-  // 1. Each '++current' statement is followed by check for equality to 'end'.
-  // 2. If AdvanceToNonspace returned false then current == end.
-  // 3. If 'current' becomes be equal to 'end' the function returns or goes to
-  // 'parsing_done'.
-  // 4. 'current' is not dereferenced after the 'parsing_done' label.
-  // 5. Code before 'parsing_done' may rely on 'current != end'.
-  if (!AdvanceToNonspace(&current, end)) return empty_string_val;
-
-  const bool allow_trailing_junk = (flags & ALLOW_TRAILING_JUNK) != 0;
-
-  // The longest form of simplified number is: "-<significant digits>'.1eXXX\0".
-  const int kBufferSize = kMaxSignificantDigits + 10;
-  char buffer[kBufferSize];  // NOLINT: size is known at compile time.
-  int buffer_pos = 0;
-
-  // Exponent will be adjusted if insignificant digits of the integer part
-  // or insignificant leading zeros of the fractional part are dropped.
-  int exponent = 0;
-  int significant_digits = 0;
-  int insignificant_digits = 0;
-  bool nonzero_digit_dropped = false;
-  bool fractional_part = false;
-
-  bool sign = false;
-
-  if (*current == '+') {
-    // Ignore leading sign; skip following spaces.
-    ++current;
-    if (!AdvanceToNonspace(&current, end)) return JUNK_STRING_VALUE;
-  } else if (*current == '-') {
-    ++current;
-    if (!AdvanceToNonspace(&current, end)) return JUNK_STRING_VALUE;
-    sign = true;
-  }
-
-  static const char kInfinitySymbol[] = "Infinity";
-  if (*current == kInfinitySymbol[0]) {
-    if (!SubStringEquals(&current, end, kInfinitySymbol)) {
-      return JUNK_STRING_VALUE;
-    }
-
-    if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
-      return JUNK_STRING_VALUE;
-    }
-
-    ASSERT(buffer_pos == 0);
-    return sign ? -V8_INFINITY : V8_INFINITY;
-  }
-
-  bool leading_zero = false;
-  if (*current == '0') {
-    ++current;
-    if (current == end) return SignedZero(sign);
-
-    leading_zero = true;
-
-    // It could be hexadecimal value.
-    if ((flags & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {
-      ++current;
-      if (current == end || !isDigit(*current, 16)) {
-        return JUNK_STRING_VALUE;  // "0x".
-      }
-
-      return InternalStringToIntDouble<4>(current,
-                                          end,
-                                          sign,
-                                          allow_trailing_junk);
-    }
-
-    // Ignore leading zeros in the integer part.
-    while (*current == '0') {
-      ++current;
-      if (current == end) return SignedZero(sign);
-    }
-  }
-
-  bool octal = leading_zero && (flags & ALLOW_OCTALS) != 0;
-
-  // Copy significant digits of the integer part (if any) to the buffer.
-  while (*current >= '0' && *current <= '9') {
-    if (significant_digits < kMaxSignificantDigits) {
-      ASSERT(buffer_pos < kBufferSize);
-      buffer[buffer_pos++] = static_cast<char>(*current);
-      significant_digits++;
-      // Will later check if it's an octal in the buffer.
-    } else {
-      insignificant_digits++;  // Move the digit into the exponential part.
-      nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
-    }
-    octal = octal && *current < '8';
-    ++current;
-    if (current == end) goto parsing_done;
-  }
-
-  if (significant_digits == 0) {
-    octal = false;
-  }
-
-  if (*current == '.') {
-    if (octal && !allow_trailing_junk) return JUNK_STRING_VALUE;
-    if (octal) goto parsing_done;
-
-    ++current;
-    if (current == end) {
-      if (significant_digits == 0 && !leading_zero) {
-        return JUNK_STRING_VALUE;
-      } else {
-        goto parsing_done;
-      }
-    }
-
-    if (significant_digits == 0) {
-      // octal = false;
-      // Integer part consists of 0 or is absent. Significant digits start after
-      // leading zeros (if any).
-      while (*current == '0') {
-        ++current;
-        if (current == end) return SignedZero(sign);
-        exponent--;  // Move this 0 into the exponent.
-      }
-    }
-
-    // We don't emit a '.', but adjust the exponent instead.
-    fractional_part = true;
-
-    // There is a fractional part.
-    while (*current >= '0' && *current <= '9') {
-      if (significant_digits < kMaxSignificantDigits) {
-        ASSERT(buffer_pos < kBufferSize);
-        buffer[buffer_pos++] = static_cast<char>(*current);
-        significant_digits++;
-        exponent--;
-      } else {
-        // Ignore insignificant digits in the fractional part.
-        nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
-      }
-      ++current;
-      if (current == end) goto parsing_done;
-    }
-  }
-
-  if (!leading_zero && exponent == 0 && significant_digits == 0) {
-    // If leading_zeros is true then the string contains zeros.
-    // If exponent < 0 then string was [+-]\.0*...
-    // If significant_digits != 0 the string is not equal to 0.
-    // Otherwise there are no digits in the string.
-    return JUNK_STRING_VALUE;
-  }
-
-  // Parse exponential part.
-  if (*current == 'e' || *current == 'E') {
-    if (octal) return JUNK_STRING_VALUE;
-    ++current;
-    if (current == end) {
-      if (allow_trailing_junk) {
-        goto parsing_done;
-      } else {
-        return JUNK_STRING_VALUE;
-      }
-    }
-    char sign = '+';
-    if (*current == '+' || *current == '-') {
-      sign = static_cast<char>(*current);
-      ++current;
-      if (current == end) {
-        if (allow_trailing_junk) {
-          goto parsing_done;
-        } else {
-          return JUNK_STRING_VALUE;
-        }
-      }
-    }
-
-    if (current == end || *current < '0' || *current > '9') {
-      if (allow_trailing_junk) {
-        goto parsing_done;
-      } else {
-        return JUNK_STRING_VALUE;
-      }
-    }
-
-    const int max_exponent = INT_MAX / 2;
-    ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
-    int num = 0;
-    do {
-      // Check overflow.
-      int digit = *current - '0';
-      if (num >= max_exponent / 10
-          && !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
-        num = max_exponent;
-      } else {
-        num = num * 10 + digit;
-      }
-      ++current;
-    } while (current != end && *current >= '0' && *current <= '9');
-
-    exponent += (sign == '-' ? -num : num);
-  }
-
-  if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
-    return JUNK_STRING_VALUE;
-  }
-
-  parsing_done:
-  exponent += insignificant_digits;
-
-  if (octal) {
-    return InternalStringToIntDouble<3>(buffer,
-                                        buffer + buffer_pos,
-                                        sign,
-                                        allow_trailing_junk);
-  }
-
-  if (nonzero_digit_dropped) {
-    buffer[buffer_pos++] = '1';
-    exponent--;
-  }
-
-  ASSERT(buffer_pos < kBufferSize);
-  buffer[buffer_pos] = '\0';
-
-  double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
-  return sign ? -converted : converted;
-}
-
-
-const char* DoubleToCString(double v, Vector<char> buffer) {
-  StringBuilder builder(buffer.start(), buffer.length());
-
-  switch (fpclassify(v)) {
-    case FP_NAN:
-      builder.AddString("NaN");
-      break;
-
-    case FP_INFINITE:
-      if (v < 0.0) {
-        builder.AddString("-Infinity");
-      } else {
-        builder.AddString("Infinity");
-      }
-      break;
-
-    case FP_ZERO:
-      builder.AddCharacter('0');
-      break;
-
-    default: {
-      int decimal_point;
-      int sign;
-      const int kV8DtoaBufferCapacity = kBase10MaximalLength + 1;
-      char decimal_rep[kV8DtoaBufferCapacity];
-      int length;
-
-      DoubleToAscii(v, DTOA_SHORTEST, 0,
-                    Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
-                    &sign, &length, &decimal_point);
-
-      if (sign) builder.AddCharacter('-');
-
-      if (length <= decimal_point && decimal_point <= 21) {
-        // ECMA-262 section 9.8.1 step 6.
-        builder.AddString(decimal_rep);
-        builder.AddPadding('0', decimal_point - length);
-
-      } else if (0 < decimal_point && decimal_point <= 21) {
-        // ECMA-262 section 9.8.1 step 7.
-        builder.AddSubstring(decimal_rep, decimal_point);
-        builder.AddCharacter('.');
-        builder.AddString(decimal_rep + decimal_point);
-
-      } else if (decimal_point <= 0 && decimal_point > -6) {
-        // ECMA-262 section 9.8.1 step 8.
-        builder.AddString("0.");
-        builder.AddPadding('0', -decimal_point);
-        builder.AddString(decimal_rep);
-
-      } else {
-        // ECMA-262 section 9.8.1 step 9 and 10 combined.
-        builder.AddCharacter(decimal_rep[0]);
-        if (length != 1) {
-          builder.AddCharacter('.');
-          builder.AddString(decimal_rep + 1);
-        }
-        builder.AddCharacter('e');
-        builder.AddCharacter((decimal_point >= 0) ? '+' : '-');
-        int exponent = decimal_point - 1;
-        if (exponent < 0) exponent = -exponent;
-        builder.AddFormatted("%d", exponent);
-      }
-    }
-  }
-  return builder.Finalize();
-}
-
-
-char* DoubleToFixedCString(double value, int f) {
-  const int kMaxDigitsBeforePoint = 21;
-  const double kFirstNonFixed = 1e21;
-  const int kMaxDigitsAfterPoint = 20;
-  ASSERT(f >= 0);
-  ASSERT(f <= kMaxDigitsAfterPoint);
-
-  bool negative = false;
-  double abs_value = value;
-  if (value < 0) {
-    abs_value = -value;
-    negative = true;
-  }
-
-  // If abs_value has more than kMaxDigitsBeforePoint digits before the point
-  // use the non-fixed conversion routine.
-  if (abs_value >= kFirstNonFixed) {
-    char arr[100];
-    Vector<char> buffer(arr, ARRAY_SIZE(arr));
-    return StrDup(DoubleToCString(value, buffer));
-  }
-
-  // Find a sufficiently precise decimal representation of n.
-  int decimal_point;
-  int sign;
-  // Add space for the '\0' byte.
-  const int kDecimalRepCapacity =
-      kMaxDigitsBeforePoint + kMaxDigitsAfterPoint + 1;
-  char decimal_rep[kDecimalRepCapacity];
-  int decimal_rep_length;
-  DoubleToAscii(value, DTOA_FIXED, f,
-                Vector<char>(decimal_rep, kDecimalRepCapacity),
-                &sign, &decimal_rep_length, &decimal_point);
-
-  // Create a representation that is padded with zeros if needed.
-  int zero_prefix_length = 0;
-  int zero_postfix_length = 0;
-
-  if (decimal_point <= 0) {
-    zero_prefix_length = -decimal_point + 1;
-    decimal_point = 1;
-  }
-
-  if (zero_prefix_length + decimal_rep_length < decimal_point + f) {
-    zero_postfix_length = decimal_point + f - decimal_rep_length -
-                          zero_prefix_length;
-  }
-
-  unsigned rep_length =
-      zero_prefix_length + decimal_rep_length + zero_postfix_length;
-  StringBuilder rep_builder(rep_length + 1);
-  rep_builder.AddPadding('0', zero_prefix_length);
-  rep_builder.AddString(decimal_rep);
-  rep_builder.AddPadding('0', zero_postfix_length);
-  char* rep = rep_builder.Finalize();
-
-  // Create the result string by appending a minus and putting in a
-  // decimal point if needed.
-  unsigned result_size = decimal_point + f + 2;
-  StringBuilder builder(result_size + 1);
-  if (negative) builder.AddCharacter('-');
-  builder.AddSubstring(rep, decimal_point);
-  if (f > 0) {
-    builder.AddCharacter('.');
-    builder.AddSubstring(rep + decimal_point, f);
-  }
-  DeleteArray(rep);
-  return builder.Finalize();
-}
-
-
-static char* CreateExponentialRepresentation(char* decimal_rep,
-                                             int exponent,
-                                             bool negative,
-                                             int significant_digits) {
-  bool negative_exponent = false;
-  if (exponent < 0) {
-    negative_exponent = true;
-    exponent = -exponent;
-  }
-
-  // Leave room in the result for appending a minus, for a period, the
-  // letter 'e', a minus or a plus depending on the exponent, and a
-  // three digit exponent.
-  unsigned result_size = significant_digits + 7;
-  StringBuilder builder(result_size + 1);
-
-  if (negative) builder.AddCharacter('-');
-  builder.AddCharacter(decimal_rep[0]);
-  if (significant_digits != 1) {
-    builder.AddCharacter('.');
-    builder.AddString(decimal_rep + 1);
-    int rep_length = StrLength(decimal_rep);
-    builder.AddPadding('0', significant_digits - rep_length);
-  }
-
-  builder.AddCharacter('e');
-  builder.AddCharacter(negative_exponent ? '-' : '+');
-  builder.AddFormatted("%d", exponent);
-  return builder.Finalize();
-}
-
-
-
-char* DoubleToExponentialCString(double value, int f) {
-  const int kMaxDigitsAfterPoint = 20;
-  // f might be -1 to signal that f was undefined in JavaScript.
-  ASSERT(f >= -1 && f <= kMaxDigitsAfterPoint);
-
-  bool negative = false;
-  if (value < 0) {
-    value = -value;
-    negative = true;
-  }
-
-  // Find a sufficiently precise decimal representation of n.
-  int decimal_point;
-  int sign;
-  // f corresponds to the digits after the point. There is always one digit
-  // before the point. The number of requested_digits equals hence f + 1.
-  // And we have to add one character for the null-terminator.
-  const int kV8DtoaBufferCapacity = kMaxDigitsAfterPoint + 1 + 1;
-  // Make sure that the buffer is big enough, even if we fall back to the
-  // shortest representation (which happens when f equals -1).
-  ASSERT(kBase10MaximalLength <= kMaxDigitsAfterPoint + 1);
-  char decimal_rep[kV8DtoaBufferCapacity];
-  int decimal_rep_length;
-
-  if (f == -1) {
-    DoubleToAscii(value, DTOA_SHORTEST, 0,
-                  Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
-                  &sign, &decimal_rep_length, &decimal_point);
-    f = decimal_rep_length - 1;
-  } else {
-    DoubleToAscii(value, DTOA_PRECISION, f + 1,
-                  Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
-                  &sign, &decimal_rep_length, &decimal_point);
-  }
-  ASSERT(decimal_rep_length > 0);
-  ASSERT(decimal_rep_length <= f + 1);
-
-  int exponent = decimal_point - 1;
-  char* result =
-      CreateExponentialRepresentation(decimal_rep, exponent, negative, f+1);
-
-  return result;
-}
-
-
-char* DoubleToPrecisionCString(double value, int p) {
-  const int kMinimalDigits = 1;
-  const int kMaximalDigits = 21;
-  ASSERT(p >= kMinimalDigits && p <= kMaximalDigits);
-  USE(kMinimalDigits);
-
-  bool negative = false;
-  if (value < 0) {
-    value = -value;
-    negative = true;
-  }
-
-  // Find a sufficiently precise decimal representation of n.
-  int decimal_point;
-  int sign;
-  // Add one for the terminating null character.
-  const int kV8DtoaBufferCapacity = kMaximalDigits + 1;
-  char decimal_rep[kV8DtoaBufferCapacity];
-  int decimal_rep_length;
-
-  DoubleToAscii(value, DTOA_PRECISION, p,
-                Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
-                &sign, &decimal_rep_length, &decimal_point);
-  ASSERT(decimal_rep_length <= p);
-
-  int exponent = decimal_point - 1;
-
-  char* result = NULL;
-
-  if (exponent < -6 || exponent >= p) {
-    result =
-        CreateExponentialRepresentation(decimal_rep, exponent, negative, p);
-  } else {
-    // Use fixed notation.
-    //
-    // Leave room in the result for appending a minus, a period and in
-    // the case where decimal_point is not positive for a zero in
-    // front of the period.
-    unsigned result_size = (decimal_point <= 0)
-        ? -decimal_point + p + 3
-        : p + 2;
-    StringBuilder builder(result_size + 1);
-    if (negative) builder.AddCharacter('-');
-    if (decimal_point <= 0) {
-      builder.AddString("0.");
-      builder.AddPadding('0', -decimal_point);
-      builder.AddString(decimal_rep);
-      builder.AddPadding('0', p - decimal_rep_length);
-    } else {
-      const int m = Min(decimal_rep_length, decimal_point);
-      builder.AddSubstring(decimal_rep, m);
-      builder.AddPadding('0', decimal_point - decimal_rep_length);
-      if (decimal_point < p) {
-        builder.AddCharacter('.');
-        const int extra = negative ? 2 : 1;
-        if (decimal_rep_length > decimal_point) {
-          const int len = StrLength(decimal_rep + decimal_point);
-          const int n = Min(len, p - (builder.position() - extra));
-          builder.AddSubstring(decimal_rep + decimal_point, n);
-        }
-        builder.AddPadding('0', extra + (p - builder.position()));
-      }
-    }
-    result = builder.Finalize();
-  }
-
-  return result;
-}
-
-} }  // namespace v8::internal

src/double-conversion.cc

+// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <stdarg.h>
+#include <limits.h>
+
+#include "v8.h"
+
+#include "conversions-inl.h"
+#include "dtoa.h"
+#include "factory.h"
+#include "scanner-base.h"
+#include "strtod.h"
+
+namespace v8 {
+namespace internal {
+
+namespace {
+
+static char* CreateExponentialRepresentation(char* decimal_rep,
+                                             int exponent,
+                                             bool negative,
+                                             int significant_digits) {
+  bool negative_exponent = false;
+  if (exponent < 0) {
+    negative_exponent = true;
+    exponent = -exponent;
+  }
+
+  // Leave room in the result for appending a minus, for a period, the
+  // letter 'e', a minus or a plus depending on the exponent, and a
+  // three digit exponent.
+  unsigned result_size = significant_digits + 7;
+  StringBuilder builder(result_size + 1);
+
+  if (negative) builder.AddCharacter('-');
+  builder.AddCharacter(decimal_rep[0]);
+  if (significant_digits != 1) {
+    builder.AddCharacter('.');
+    builder.AddString(decimal_rep + 1);
+    int rep_length = StrLength(decimal_rep);
+    builder.AddPadding('0', significant_digits - rep_length);
+  }
+
+  builder.AddCharacter('e');
+  builder.AddCharacter(negative_exponent ? '-' : '+');
+  builder.AddFormatted("%d", exponent);
+  return builder.Finalize();
+}
+
+const char* DoubleToCString(double v, Vector<char> buffer) {
+  StringBuilder builder(buffer.start(), buffer.length());
+
+  switch (fpclassify(v)) {
+    case FP_NAN:
+      builder.AddString("NaN");
+      break;
+
+    case FP_INFINITE:
+      if (v < 0.0) {
+        builder.AddString("-Infinity");
+      } else {
+        builder.AddString("Infinity");
+      }
+      break;
+
+    case FP_ZERO:
+      builder.AddCharacter('0');
+      break;
+
+    default: {
+      int decimal_point;
+      int sign;
+      const int kV8DtoaBufferCapacity = kBase10MaximalLength + 1;
+      char decimal_rep[kV8DtoaBufferCapacity];
+      int length;
+
+      DoubleToAscii(v, DTOA_SHORTEST, 0,
+                    Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
+                    &sign, &length, &decimal_point);
+
+      if (sign) builder.AddCharacter('-');
+
+      if (length <= decimal_point && decimal_point <= 21) {
+        // ECMA-262 section 9.8.1 step 6.
+        builder.AddString(decimal_rep);
+        builder.AddPadding('0', decimal_point - length);
+
+      } else if (0 < decimal_point && decimal_point <= 21) {
+        // ECMA-262 section 9.8.1 step 7.
+        builder.AddSubstring(decimal_rep, decimal_point);
+        builder.AddCharacter('.');
+        builder.AddString(decimal_rep + decimal_point);
+
+      } else if (decimal_point <= 0 && decimal_point > -6) {
+        // ECMA-262 section 9.8.1 step 8.
+        builder.AddString("0.");
+        builder.AddPadding('0', -decimal_point);
+        builder.AddString(decimal_rep);
+
+      } else {
+        // ECMA-262 section 9.8.1 step 9 and 10 combined.
+        builder.AddCharacter(decimal_rep[0]);
+        if (length != 1) {
+          builder.AddCharacter('.');
+          builder.AddString(decimal_rep + 1);
+        }
+        builder.AddCharacter('e');
+        builder.AddCharacter((decimal_point >= 0) ? '+' : '-');
+        int exponent = decimal_point - 1;
+        if (exponent < 0) exponent = -exponent;
+        builder.AddFormatted("%d", exponent);
+      }
+    }
+  }
+  return builder.Finalize();
+}
+
+
+char* DoubleToFixedCString(double value, int f) {
+  const int kMaxDigitsBeforePoint = 21;
+  const double kFirstNonFixed = 1e21;
+  const int kMaxDigitsAfterPoint = 20;
+  ASSERT(f >= 0);
+  ASSERT(f <= kMaxDigitsAfterPoint);
+
+  bool negative = false;
+  double abs_value = value;
+  if (value < 0) {
+    abs_value = -value;
+    negative = true;
+  }
+
+  // If abs_value has more than kMaxDigitsBeforePoint digits before the point
+  // use the non-fixed conversion routine.
+  if (abs_value >= kFirstNonFixed) {
+    char arr[100];
+    Vector<char> buffer(arr, ARRAY_SIZE(arr));
+    return StrDup(DoubleToCString(value, buffer));
+  }
+
+  // Find a sufficiently precise decimal representation of n.
+  int decimal_point;
+  int sign;
+  // Add space for the '\0' byte.
+  const int kDecimalRepCapacity =
+      kMaxDigitsBeforePoint + kMaxDigitsAfterPoint + 1;
+  char decimal_rep[kDecimalRepCapacity];
+  int decimal_rep_length;
+  DoubleToAscii(value, DTOA_FIXED, f,
+                Vector<char>(decimal_rep, kDecimalRepCapacity),
+                &sign, &decimal_rep_length, &decimal_point);
+
+  // Create a representation that is padded with zeros if needed.
+  int zero_prefix_length = 0;
+  int zero_postfix_length = 0;
+
+  if (decimal_point <= 0) {
+    zero_prefix_length = -decimal_point + 1;
+    decimal_point = 1;
+  }
+
+  if (zero_prefix_length + decimal_rep_length < decimal_point + f) {
+    zero_postfix_length = decimal_point + f - decimal_rep_length -
+                          zero_prefix_length;
+  }
+
+  unsigned rep_length =
+      zero_prefix_length + decimal_rep_length + zero_postfix_length;
+  StringBuilder rep_builder(rep_length + 1);
+  rep_builder.AddPadding('0', zero_prefix_length);
+  rep_builder.AddString(decimal_rep);
+  rep_builder.AddPadding('0', zero_postfix_length);
+  char* rep = rep_builder.Finalize();
+
+  // Create the result string by appending a minus and putting in a
+  // decimal point if needed.
+  unsigned result_size = decimal_point + f + 2;
+  StringBuilder builder(result_size + 1);
+  if (negative) builder.AddCharacter('-');
+  builder.AddSubstring(rep, decimal_point);
+  if (f > 0) {
+    builder.AddCharacter('.');
+    builder.AddSubstring(rep + decimal_point, f);
+  }
+  DeleteArray(rep);
+  return builder.Finalize();
+}
+
+
+char* DoubleToExponentialCString(double value, int f) {
+  const int kMaxDigitsAfterPoint = 20;
+  // f might be -1 to signal that f was undefined in JavaScript.
+  ASSERT(f >= -1 && f <= kMaxDigitsAfterPoint);
+
+  bool negative = false;
+  if (value < 0) {
+    value = -value;
+    negative = true;
+  }
+
+  // Find a sufficiently precise decimal representation of n.
+  int decimal_point;
+  int sign;
+  // f corresponds to the digits after the point. There is always one digit
+  // before the point. The number of requested_digits equals hence f + 1.
+  // And we have to add one character for the null-terminator.
+  const int kV8DtoaBufferCapacity = kMaxDigitsAfterPoint + 1 + 1;
+  // Make sure that the buffer is big enough, even if we fall back to the
+  // shortest representation (which happens when f equals -1).
+  ASSERT(kBase10MaximalLength <= kMaxDigitsAfterPoint + 1);
+  char decimal_rep[kV8DtoaBufferCapacity];
+  int decimal_rep_length;
+
+  if (f == -1) {
+    DoubleToAscii(value, DTOA_SHORTEST, 0,
+                  Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
+                  &sign, &decimal_rep_length, &decimal_point);
+    f = decimal_rep_length - 1;
+  } else {
+    DoubleToAscii(value, DTOA_PRECISION, f + 1,
+                  Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
+                  &sign, &decimal_rep_length, &decimal_point);
+  }
+  ASSERT(decimal_rep_length > 0);
+  ASSERT(decimal_rep_length <= f + 1);
+
+  int exponent = decimal_point - 1;
+  char* result =
+      CreateExponentialRepresentation(decimal_rep, exponent, negative, f+1);
+
+  return result;
+}
+
+
+char* DoubleToPrecisionCString(double value, int p) {
+  const int kMinimalDigits = 1;
+  const int kMaximalDigits = 21;
+  ASSERT(p >= kMinimalDigits && p <= kMaximalDigits);
+  USE(kMinimalDigits);
+
+  bool negative = false;
+  if (value < 0) {
+    value = -value;
+    negative = true;
+  }
+
+  // Find a sufficiently precise decimal representation of n.
+  int decimal_point;
+  int sign;
+  // Add one for the terminating null character.
+  const int kV8DtoaBufferCapacity = kMaximalDigits + 1;
+  char decimal_rep[kV8DtoaBufferCapacity];
+  int decimal_rep_length;
+
+  DoubleToAscii(value, DTOA_PRECISION, p,
+                Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
+                &sign, &decimal_rep_length, &decimal_point);
+  ASSERT(decimal_rep_length <= p);
+
+  int exponent = decimal_point - 1;
+
+  char* result = NULL;
+
+  if (exponent < -6 || exponent >= p) {
+    result =
+        CreateExponentialRepresentation(decimal_rep, exponent, negative, p);
+  } else {
+    // Use fixed notation.
+    //
+    // Leave room in the result for appending a minus, a period and in
+    // the case where decimal_point is not positive for a zero in
+    // front of the period.
+    unsigned result_size = (decimal_point <= 0)
+        ? -decimal_point + p + 3
+        : p + 2;
+    StringBuilder builder(result_size + 1);
+    if (negative) builder.AddCharacter('-');
+    if (decimal_point <= 0) {
+      builder.AddString("0.");
+      builder.AddPadding('0', -decimal_point);
+      builder.AddString(decimal_rep);
+      builder.AddPadding('0', p - decimal_rep_length);
+    } else {
+      const int m = Min(decimal_rep_length, decimal_point);
+      builder.AddSubstring(decimal_rep, m);
+      builder.AddPadding('0', decimal_point - decimal_rep_length);
+      if (decimal_point < p) {
+        builder.AddCharacter('.');
+        const int extra = negative ? 2 : 1;
+        if (decimal_rep_length > decimal_point) {
+          const int len = StrLength(decimal_rep + decimal_point);
+          const int n = Min(len, p - (builder.position() - extra));
+          builder.AddSubstring(decimal_rep + decimal_point, n);
+        }
+        builder.AddPadding('0', extra + (p - builder.position()));
+      }
+    }
+    result = builder.Finalize();
+  }
+
+  return result;
+}
+
+// Maximum number of significant digits in decimal representation.
+// The longest possible double in decimal representation is
+// (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074
+// (768 digits). If we parse a number whose first digits are equal to a
+// mean of 2 adjacent doubles (that could have up to 769 digits) the result
+// must be rounded to the bigger one unless the tail consists of zeros, so
+// we don't need to preserve all the digits.
+const int kMaxSignificantDigits = 772;
+
+
+// Returns true if a nonspace found and false if the end has reached.
+template <class Iterator, class EndMark>
+static inline bool AdvanceToNonspace(Iterator* current, EndMark end) {
+  while (*current != end) {
+    if (!ScannerConstants::kIsWhiteSpace.get(**current)) return true;
+    ++*current;
+  }
+  return false;
+}
+
+
+static bool isDigit(int x, int radix) {
+  return (x >= '0' && x <= '9' && x < '0' + radix)
+      || (radix > 10 && x >= 'a' && x < 'a' + radix - 10)
+      || (radix > 10 && x >= 'A' && x < 'A' + radix - 10);
+}
+
+
+static double SignedZero(bool sign) {
+  return sign ? -0.0 : 0.0;
+}
+
+
+// Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
+template <int radix_log_2, class Iterator, class EndMark>
+static double InternalStringToIntDouble(Iterator current,
+                                        EndMark end,
+                                        bool sign,
+                                        bool allow_trailing_junk) {
+  ASSERT(current != end);
+
+  // Skip leading 0s.
+  while (*current == '0') {
+    ++current;
+    if (current == end) return SignedZero(sign);
+  }
+
+  int64_t number = 0;
+  int exponent = 0;
+  const int radix = (1 << radix_log_2);
+
+  do {
+    int digit;
+    if (*current >= '0' && *current <= '9' && *current < '0' + radix) {
+      digit = static_cast<char>(*current) - '0';
+    } else if (radix > 10 && *current >= 'a' && *current < 'a' + radix - 10) {
+      digit = static_cast<char>(*current) - 'a' + 10;
+    } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) {
+      digit = static_cast<char>(*current) - 'A' + 10;
+    } else {
+      if (allow_trailing_junk || !AdvanceToNonspace(&current, end)) {
+        break;
+      } else {
+        return JUNK_STRING_VALUE;
+      }
+    }
+
+    number = number * radix + digit;
+    int overflow = static_cast<int>(number >> 53);
+    if (overflow != 0) {
+      // Overflow occurred. Need to determine which direction to round the
+      // result.
+      int overflow_bits_count = 1;
+      while (overflow > 1) {
+        overflow_bits_count++;
+        overflow >>= 1;
+      }
+
+      int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
+      int dropped_bits = static_cast<int>(number) & dropped_bits_mask;
+      number >>= overflow_bits_count;
+      exponent = overflow_bits_count;
+
+      bool zero_tail = true;
+      while (true) {
+        ++current;
+        if (current == end || !isDigit(*current, radix)) break;
+        zero_tail = zero_tail && *current == '0';
+        exponent += radix_log_2;
+      }
+
+      if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
+        return JUNK_STRING_VALUE;
+      }
+
+      int middle_value = (1 << (overflow_bits_count - 1));
+      if (dropped_bits > middle_value) {
+        number++;  // Rounding up.
+      } else if (dropped_bits == middle_value) {
+        // Rounding to even to consistency with decimals: half-way case rounds
+        // up if significant part is odd and down otherwise.
+        if ((number & 1) != 0 || !zero_tail) {
+          number++;  // Rounding up.
+        }
+      }
+
+      // Rounding up may cause overflow.
+      if ((number & ((int64_t)1 << 53)) != 0) {
+        exponent++;
+        number >>= 1;
+      }
+      break;
+    }
+    ++current;
+  } while (current != end);
+
+  ASSERT(number < ((int64_t)1 << 53));
+  ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number);
+
+  if (exponent == 0) {
+    if (sign) {
+      if (number == 0) return -0.0;
+      number = -number;
+    }
+    return static_cast<double>(number);
+  }
+
+  ASSERT(number != 0);
+  // The double could be constructed faster from number (mantissa), exponent
+  // and sign. Assuming it's a rare case more simple code is used.
+  return static_cast<double>(sign ? -number : number) * pow(2.0, exponent);
+}
+
+
+// Converts a string to a double value. Assumes the Iterator supports
+// the following operations:
+// 1. current == end (other ops are not allowed), current != end.
+// 2. *current - gets the current character in the sequence.
+// 3. ++current (advances the position).
+template <class Iterator, class EndMark>
+static double InternalStringToDouble(Iterator current,
+                                     EndMark end,
+                                     int flags,
+                                     double empty_string_val) {
+  // To make sure that iterator dereferencing is valid the following
+  // convention is used:
+  // 1. Each '++current' statement is followed by check for equality to 'end'.
+  // 2. If AdvanceToNonspace returned false then current == end.
+  // 3. If 'current' becomes be equal to 'end' the function returns or goes to
+  // 'parsing_done'.
+  // 4. 'current' is not dereferenced after the 'parsing_done' label.
+  // 5. Code before 'parsing_done' may rely on 'current != end'.
+  if (!AdvanceToNonspace(&current, end)) return empty_string_val;
+
+  const bool allow_trailing_junk = (flags & ALLOW_TRAILING_JUNK) != 0;
+
+  // The longest form of simplified number is: "-<significant digits>'.1eXXX\0".
+  const int kBufferSize = kMaxSignificantDigits + 10;
+  char buffer[kBufferSize];  // NOLINT: size is known at compile time.
+  int buffer_pos = 0;
+
+  // Exponent will be adjusted if insignificant digits of the integer part
+  // or insignificant leading zeros of the fractional part are dropped.
+  int exponent = 0;
+  int significant_digits = 0;
+  int insignificant_digits = 0;
+  bool nonzero_digit_dropped = false;
+  bool fractional_part = false;
+
+  bool sign = false;
+
+  if (*current == '+') {
+    // Ignore leading sign; skip following spaces.
+    ++current;
+    if (!AdvanceToNonspace(&current, end)) return JUNK_STRING_VALUE;
+  } else if (*current == '-') {
+    ++current;
+    if (!AdvanceToNonspace(&current, end)) return JUNK_STRING_VALUE;
+    sign = true;
+  }
+
+  static const char kInfinitySymbol[] = "Infinity";
+  if (*current == kInfinitySymbol[0]) {
+    if (!SubStringEquals(&current, end, kInfinitySymbol)) {
+      return JUNK_STRING_VALUE;
+    }
+
+    if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
+      return JUNK_STRING_VALUE;
+    }
+
+    ASSERT(buffer_pos == 0);
+    return sign ? -V8_INFINITY : V8_INFINITY;
+  }
+
+  bool leading_zero = false;
+  if (*current == '0') {
+    ++current;
+    if (current == end) return SignedZero(sign);
+
+    leading_zero = true;
+
+    // It could be hexadecimal value.
+    if ((flags & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {
+      ++current;
+      if (current == end || !isDigit(*current, 16)) {
+        return JUNK_STRING_VALUE;  // "0x".
+      }
+
+      return InternalStringToIntDouble<4>(current,
+                                          end,
+                                          sign,
+                                          allow_trailing_junk);
+    }
+
+    // Ignore leading zeros in the integer part.
+    while (*current == '0') {
+      ++current;
+      if (current == end) return SignedZero(sign);
+    }
+  }
+
+  bool octal = leading_zero && (flags & ALLOW_OCTALS) != 0;
+
+  // Copy significant digits of the integer part (if any) to the buffer.
+  while (*current >= '0' && *current <= '9') {
+    if (significant_digits < kMaxSignificantDigits) {
+      ASSERT(buffer_pos < kBufferSize);
+      buffer[buffer_pos++] = static_cast<char>(*current);
+      significant_digits++;
+      // Will later check if it's an octal in the buffer.
+    } else {
+      insignificant_digits++;  // Move the digit into the exponential part.
+      nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
+    }
+    octal = octal && *current < '8';
+    ++current;
+    if (current == end) goto parsing_done;
+  }
+
+  if (significant_digits == 0) {
+    octal = false;
+  }
+
+  if (*current == '.') {
+    if (octal && !allow_trailing_junk) return JUNK_STRING_VALUE;
+    if (octal) goto parsing_done;
+
+    ++current;
+    if (current == end) {
+      if (significant_digits == 0 && !leading_zero) {
+        return JUNK_STRING_VALUE;
+      } else {
+        goto parsing_done;
+      }
+    }
+
+    if (significant_digits == 0) {
+      // octal = false;
+      // Integer part consists of 0 or is absent. Significant digits start after
+      // leading zeros (if any).
+      while (*current == '0') {
+        ++current;
+        if (current == end) return SignedZero(sign);
+        exponent--;  // Move this 0 into the exponent.
+      }
+    }
+
+    // We don't emit a '.', but adjust the exponent instead.
+    fractional_part = true;
+
+    // There is a fractional part.
+    while (*current >= '0' && *current <= '9') {
+      if (significant_digits < kMaxSignificantDigits) {
+        ASSERT(buffer_pos < kBufferSize);
+        buffer[buffer_pos++] = static_cast<char>(*current);
+        significant_digits++;
+        exponent--;
+      } else {
+        // Ignore insignificant digits in the fractional part.
+        nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
+      }
+      ++current;
+      if (current == end) goto parsing_done;
+    }
+  }
+
+  if (!leading_zero && exponent == 0 && significant_digits == 0) {
+    // If leading_zeros is true then the string contains zeros.
+    // If exponent < 0 then string was [+-]\.0*...
+    // If significant_digits != 0 the string is not equal to 0.
+    // Otherwise there are no digits in the string.
+    return JUNK_STRING_VALUE;
+  }
+
+  // Parse exponential part.
+  if (*current == 'e' || *current == 'E') {
+    if (octal) return JUNK_STRING_VALUE;
+    ++current;
+    if (current == end) {
+      if (allow_trailing_junk) {
+        goto parsing_done;
+      } else {
+        return JUNK_STRING_VALUE;
+      }
+    }
+    char sign = '+';
+    if (*current == '+' || *current == '-') {
+      sign = static_cast<char>(*current);
+      ++current;
+      if (current == end) {
+        if (allow_trailing_junk) {
+          goto parsing_done;
+        } else {
+          return JUNK_STRING_VALUE;
+        }
+      }
+    }
+
+    if (current == end || *current < '0' || *current > '9') {
+      if (allow_trailing_junk) {
+        goto parsing_done;
+      } else {
+        return JUNK_STRING_VALUE;
+      }
+    }
+
+    const int max_exponent = INT_MAX / 2;
+    ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
+    int num = 0;
+    do {
+      // Check overflow.
+      int digit = *current - '0';
+      if (num >= max_exponent / 10
+          && !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
+        num = max_exponent;
+      } else {
+        num = num * 10 + digit;
+      }
+      ++current;
+    } while (current != end && *current >= '0' && *current <= '9');
+
+    exponent += (sign == '-' ? -num : num);
+  }
+
+  if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
+    return JUNK_STRING_VALUE;
+  }
+
+  parsing_done:
+  exponent += insignificant_digits;
+
+  if (octal) {
+    return InternalStringToIntDouble<3>(buffer,
+                                        buffer + buffer_pos,
+                                        sign,
+                                        allow_trailing_junk);
+  }
+
+  if (nonzero_digit_dropped) {
+    buffer[buffer_pos++] = '1';
+    exponent--;
+  }
+
+  ASSERT(buffer_pos < kBufferSize);
+  buffer[buffer_pos] = '\0';
+
+  double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
+  return sign ? -converted : converted;
+}
+
+} }  // namespace v8::internal

src/utils.cc

-// Copyright 2006-2008 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include <stdarg.h>
-
-#include "v8.h"
-
-#include "platform.h"
-
-#include "sys/stat.h"
-
-namespace v8 {
-namespace internal {
-
-void StringBuilder::AddString(const char* s) {
-  AddSubstring(s, StrLength(s));
-}
-
-
-void StringBuilder::AddSubstring(const char* s, int n) {
-  ASSERT(!is_finalized() && position_ + n < buffer_.length());
-  ASSERT(static_cast<size_t>(n) <= strlen(s));
-  memcpy(&buffer_[position_], s, n * kCharSize);
-  position_ += n;
-}
-
-
-void StringBuilder::AddPadding(char c, int count) {
-  for (int i = 0; i < count; i++) {
-    AddCharacter(c);
-  }
-}
-
-
-char* StringBuilder::Finalize() {
-  ASSERT(!is_finalized() && position_ < buffer_.length());
-  buffer_[position_] = '\0';
-  // Make sure nobody managed to add a 0-character to the
-  // buffer while building the string.
-  ASSERT(strlen(buffer_.start()) == static_cast<size_t>(position_));
-  position_ = -1;
-  ASSERT(is_finalized());
-  return buffer_.start();
-}
-
-
-} }  // namespace v8::internal
 #include <stdlib.h>
 #include <string.h>
 
+
+#if defined(_WIN32) && !defined(__MINGW32__)
+
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef short int16_t;  // NOLINT
+typedef unsigned short uint16_t;  // NOLINT
+typedef int int32_t;
+typedef unsigned int uint32_t;
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+// intptr_t and friends are defined in crtdefs.h through stdio.h.
+
+#else
+
+#include <stdint.h>
+
+#endif
+
 namespace v8 {
 namespace internal {
 
 };
 
 
+// Helper class for building result strings in a character buffer. The
+// purpose of the class is to use safe operations that checks the
+// buffer bounds on all operations in debug mode.
+class StringBuilder {
+ public:
+  StringBuilder(char* buffer, int size)
+      : buffer_(buffer, size), position_(0) { }
+
+  ~StringBuilder() { if (!is_finalized()) Finalize(); }
+
+  int size() const { return buffer_.length(); }
+
+  // Get the current position in the builder.
+  int position() const {
+    ASSERT(!is_finalized());
+    return position_;
+  }
+
+  // Reset the position.
+  void Reset() { position_ = 0; }
+
+  // Add a single character to the builder. It is not allowed to add
+  // 0-characters; use the Finalize() method to terminate the string
+  // instead.
+  void AddCharacter(char c) {
+    ASSERT(c != '\0');
+    ASSERT(!is_finalized() && position_ < buffer_.length());
+    buffer_[position_++] = c;
+  }
+
+  // Add an entire string to the builder. Uses strlen() internally to
+  // compute the length of the input string.
+  void AddString(const char* s) {
+    AddSubstring(s, StrLength(s));
+  }
+
+
+  // Add the first 'n' characters of the given string 's' to the
+  // builder. The input string must have enough characters.
+  void AddSubstring(const char* s, int n) {
+    ASSERT(!is_finalized() && position_ + n < buffer_.length());
+    ASSERT(static_cast<size_t>(n) <= strlen(s));
+    memcpy(&buffer_[position_], s, n * kCharSize);
+    position_ += n;
+  }
+
+
+  // Add character padding to the builder. If count is non-positive,
+  // nothing is added to the builder.
+  void AddPadding(char c, int count) {
+    for (int i = 0; i < count; i++) {
+      AddCharacter(c);
+    }
+  }
+
+  // Finalize the string by 0-terminating it and returning the buffer.
+  char* Finalize() {
+    ASSERT(!is_finalized() && position_ < buffer_.length());
+    buffer_[position_] = '\0';
+    // Make sure nobody managed to add a 0-character to the
+    // buffer while building the string.
+    ASSERT(strlen(buffer_.start()) == static_cast<size_t>(position_));
+    position_ = -1;
+    ASSERT(is_finalized());
+    return buffer_.start();
+  }
+
+ private:
+  Vector<char> buffer_;
+  int position_;
+
+  bool is_finalized() const { return position_ < 0; }
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
+};
+
+
 // The type-based aliasing rule allows the compiler to assume that pointers of
 // different types (for some definition of different) never alias each other.
 // Thus the following code does not work:

src/v8stdint.h

-// Copyright 2010 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Load definitions of standard types.
-
-#ifndef V8STDINT_H_
-#define V8STDINT_H_
-
-#include <stdio.h>
-
-#if defined(_WIN32) && !defined(__MINGW32__)
-
-typedef signed char int8_t;
-typedef unsigned char uint8_t;
-typedef short int16_t;  // NOLINT
-typedef unsigned short uint16_t;  // NOLINT
-typedef int int32_t;
-typedef unsigned int uint32_t;
-typedef __int64 int64_t;
-typedef unsigned __int64 uint64_t;
-// intptr_t and friends are defined in crtdefs.h through stdio.h.
-
-#else
-
-#include <stdint.h>
-
-#endif
-
-#endif  // V8STDINT_H_

src/v8utils.h

-// Copyright 2010 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef V8_V8UTILS_H_
-#define V8_V8UTILS_H_
-
-#include "utils.h"
-
-namespace v8 {
-namespace internal {
-
-// Helper class for building result strings in a character buffer. The
-// purpose of the class is to use safe operations that checks the
-// buffer bounds on all operations in debug mode.
-class StringBuilder {
- public:
-  StringBuilder(char* buffer, int size)
-      : buffer_(buffer, size), position_(0) { }
-
-  ~StringBuilder() { if (!is_finalized()) Finalize(); }
-
-  int size() const { return buffer_.length(); }
-
-  // Get the current position in the builder.
-  int position() const {
-    ASSERT(!is_finalized());
-    return position_;
-  }
-
-  // Reset the position.
-  void Reset() { position_ = 0; }
-
-  // Add a single character to the builder. It is not allowed to add
-  // 0-characters; use the Finalize() method to terminate the string
-  // instead.
-  void AddCharacter(char c) {
-    ASSERT(c != '\0');
-    ASSERT(!is_finalized() && position_ < buffer_.length());
-    buffer_[position_++] = c;
-  }
-
-  // Add an entire string to the builder. Uses strlen() internally to
-  // compute the length of the input string.
-  void AddString(const char* s);
-
-  // Add the first 'n' characters of the given string 's' to the
-  // builder. The input string must have enough characters.
-  void AddSubstring(const char* s, int n);
-
-  // Add character padding to the builder. If count is non-positive,
-  // nothing is added to the builder.
-  void AddPadding(char c, int count);
-
-  // Finalize the string by 0-terminating it and returning the buffer.
-  char* Finalize();
-
- private:
-  Vector<char> buffer_;
-  int position_;
-
-  bool is_finalized() const { return position_ < 0; }
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
-};
-
-} }  // namespace v8::internal
-
-#endif  // V8_V8UTILS_H_