13fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef V8_CONVERSIONS_INL_H_
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_CONVERSIONS_INL_H_
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#include <limits.h>        // Required for INT_MAX etc.
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <math.h>
333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#include <float.h>         // Required for DBL_MAX and on Win32 for finite()
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <stdarg.h>
35589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#include "globals.h"       // Required for V8_INFINITY
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Extra POSIX/ANSI functions for Win32/MSVC.
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "conversions.h"
41589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#include "double.h"
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "platform.h"
43589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#include "scanner.h"
44589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#include "strtod.h"
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline double JunkStringValue() {
503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return BitCast<double, uint64_t>(kQuietNaNMask);
513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// The fast double-to-unsigned-int conversion routine does not guarantee
556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// rounding towards zero, or any reasonable value if the argument is larger
566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// than what fits in an unsigned 32-bit integer.
573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline unsigned int FastD2UI(double x) {
586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // There is no unsigned version of lrint, so there is no fast path
596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // in this function as there is in FastD2I. Using lrint doesn't work
606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // for values of 2^31 and above.
616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Convert "small enough" doubles to uint32_t by fixing the 32
636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // least significant non-fractional bits in the low 32 bits of the
646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // double, and reading them from there.
656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const double k2Pow52 = 4503599627370496.0;
666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool negative = x < 0;
676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (negative) {
686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    x = -x;
696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (x < k2Pow52) {
716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    x += k2Pow52;
726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    uint32_t result;
736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Address mantissa_ptr = reinterpret_cast<Address>(&x);
746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Copy least significant 32 bits of mantissa.
756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    memcpy(&result, mantissa_ptr, sizeof(result));
766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return negative ? ~result + 1 : result;
776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Large number (outside uint32 range), Infinity or NaN.
796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return 0x80000000u;  // Return integer indefinite.
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline double DoubleToInteger(double x) {
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (isnan(x)) return 0;
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!isfinite(x) || x == 0) return x;
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return (x >= 0) ? floor(x) : ceil(x);
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint32_t DoubleToInt32(double x) {
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int32_t i = FastD2I(x);
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FastI2D(i) == x) return i;
93589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Double d(x);
94589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  int exponent = d.Exponent();
95589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (exponent < 0) {
96589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (exponent <= -Double::kSignificandSize) return 0;
97589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    return d.Sign() * static_cast<int32_t>(d.Significand() >> -exponent);
98589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  } else {
99589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (exponent > 31) return 0;
100589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    return d.Sign() * static_cast<int32_t>(d.Significand() << exponent);
101589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  }
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochtemplate <class Iterator, class EndMark>
1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool SubStringEquals(Iterator* current,
1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     EndMark end,
1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     const char* substring) {
1093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(**current == *substring);
1103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (substring++; *substring != '\0'; substring++) {
1113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ++*current;
1123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (*current == end || **current != *substring) return false;
1133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
1143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ++*current;
1153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return true;
1163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
1173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// Returns true if a nonspace character has been found and false if the
1203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// end was been reached before finding a nonspace character.
1213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochtemplate <class Iterator, class EndMark>
1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline bool AdvanceToNonspace(UnicodeCache* unicode_cache,
1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Iterator* current,
1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              EndMark end) {
1253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  while (*current != end) {
1263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (!unicode_cache->IsWhiteSpace(**current)) return true;
1273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ++*current;
1283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
1293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return false;
1303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
1313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
1343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochtemplate <int radix_log_2, class Iterator, class EndMark>
1353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochdouble InternalStringToIntDouble(UnicodeCache* unicode_cache,
1363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Iterator current,
1373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 EndMark end,
1383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 bool negative,
1393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 bool allow_trailing_junk) {
1403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(current != end);
1413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Skip leading 0s.
1433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  while (*current == '0') {
1443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ++current;
1453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (current == end) return SignedZero(negative);
1463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
1473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int64_t number = 0;
1493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int exponent = 0;
1503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int radix = (1 << radix_log_2);
1513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  do {
1533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int digit;
1543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (*current >= '0' && *current <= '9' && *current < '0' + radix) {
1553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      digit = static_cast<char>(*current) - '0';
1563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else if (radix > 10 && *current >= 'a' && *current < 'a' + radix - 10) {
1573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      digit = static_cast<char>(*current) - 'a' + 10;
1583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) {
1593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      digit = static_cast<char>(*current) - 'A' + 10;
1603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
1613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (allow_trailing_junk ||
1623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          !AdvanceToNonspace(unicode_cache, &current, end)) {
1633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        break;
1643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      } else {
1653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        return JunkStringValue();
1663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
1673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
1683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    number = number * radix + digit;
1703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int overflow = static_cast<int>(number >> 53);
1713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (overflow != 0) {
1723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // Overflow occurred. Need to determine which direction to round the
1733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // result.
1743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      int overflow_bits_count = 1;
1753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      while (overflow > 1) {
1763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        overflow_bits_count++;
1773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        overflow >>= 1;
1783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
1793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
1813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      int dropped_bits = static_cast<int>(number) & dropped_bits_mask;
1823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      number >>= overflow_bits_count;
1833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      exponent = overflow_bits_count;
1843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      bool zero_tail = true;
1863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      while (true) {
1873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        ++current;
1883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        if (current == end || !isDigit(*current, radix)) break;
1893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        zero_tail = zero_tail && *current == '0';
1903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        exponent += radix_log_2;
1913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
1923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (!allow_trailing_junk &&
1943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          AdvanceToNonspace(unicode_cache, &current, end)) {
1953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        return JunkStringValue();
1963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
1973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      int middle_value = (1 << (overflow_bits_count - 1));
1993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (dropped_bits > middle_value) {
2003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        number++;  // Rounding up.
2013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      } else if (dropped_bits == middle_value) {
2023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        // Rounding to even to consistency with decimals: half-way case rounds
2033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        // up if significant part is odd and down otherwise.
2043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        if ((number & 1) != 0 || !zero_tail) {
2053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          number++;  // Rounding up.
2063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        }
2073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
2083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // Rounding up may cause overflow.
2103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if ((number & ((int64_t)1 << 53)) != 0) {
2113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        exponent++;
2123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        number >>= 1;
2133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
2143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      break;
2153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
2163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ++current;
2173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } while (current != end);
2183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(number < ((int64_t)1 << 53));
2203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number);
2213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (exponent == 0) {
2233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (negative) {
2243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (number == 0) return -0.0;
2253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      number = -number;
2263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
2273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return static_cast<double>(number);
2283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
2293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(number != 0);
2313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // The double could be constructed faster from number (mantissa), exponent
2323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // and sign. Assuming it's a rare case more simple code is used.
2333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return static_cast<double>(negative ? -number : number) * pow(2.0, exponent);
2343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
2353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochtemplate <class Iterator, class EndMark>
2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochdouble InternalStringToInt(UnicodeCache* unicode_cache,
2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           Iterator current,
2403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           EndMark end,
2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           int radix) {
2423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const bool allow_trailing_junk = true;
2433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const double empty_string_val = JunkStringValue();
2443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (!AdvanceToNonspace(unicode_cache, &current, end)) {
2463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return empty_string_val;
2473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
2483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bool negative = false;
2503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bool leading_zero = false;
2513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (*current == '+') {
2533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Ignore leading sign; skip following spaces.
2543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ++current;
2553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (current == end) {
2563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return JunkStringValue();
2573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
2583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else if (*current == '-') {
2593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ++current;
2603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (current == end) {
2613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return JunkStringValue();
2623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
2633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    negative = true;
2643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
2653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (radix == 0) {
2673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Radix detection.
2683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (*current == '0') {
2693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ++current;
2703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (current == end) return SignedZero(negative);
2713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (*current == 'x' || *current == 'X') {
2723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        radix = 16;
2733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        ++current;
2743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        if (current == end) return JunkStringValue();
2753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      } else {
2763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        radix = 8;
2773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        leading_zero = true;
2783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
2793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
2803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      radix = 10;
2813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
2823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else if (radix == 16) {
2833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (*current == '0') {
2843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // Allow "0x" prefix.
2853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ++current;
2863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (current == end) return SignedZero(negative);
2873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (*current == 'x' || *current == 'X') {
2883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        ++current;
2893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        if (current == end) return JunkStringValue();
2903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      } else {
2913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        leading_zero = true;
2923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
2933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
2943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
2953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (radix < 2 || radix > 36) return JunkStringValue();
2973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Skip leading zeros.
2993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  while (*current == '0') {
3003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    leading_zero = true;
3013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ++current;
3023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (current == end) return SignedZero(negative);
3033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
3043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (!leading_zero && !isDigit(*current, radix)) {
3063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return JunkStringValue();
3073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
3083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (IsPowerOf2(radix)) {
3103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    switch (radix) {
3113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      case 2:
3123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        return InternalStringToIntDouble<1>(
3133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            unicode_cache, current, end, negative, allow_trailing_junk);
3143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      case 4:
3153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        return InternalStringToIntDouble<2>(
3163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            unicode_cache, current, end, negative, allow_trailing_junk);
3173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      case 8:
3183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        return InternalStringToIntDouble<3>(
3193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            unicode_cache, current, end, negative, allow_trailing_junk);
3203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      case 16:
3223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        return InternalStringToIntDouble<4>(
3233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            unicode_cache, current, end, negative, allow_trailing_junk);
3243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      case 32:
3263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        return InternalStringToIntDouble<5>(
3273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            unicode_cache, current, end, negative, allow_trailing_junk);
3283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      default:
3293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        UNREACHABLE();
3303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
3313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
3323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (radix == 10) {
3343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Parsing with strtod.
3353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    const int kMaxSignificantDigits = 309;  // Doubles are less than 1.8e308.
3363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // The buffer may contain up to kMaxSignificantDigits + 1 digits and a zero
3373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // end.
3383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    const int kBufferSize = kMaxSignificantDigits + 2;
3393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    char buffer[kBufferSize];
3403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int buffer_pos = 0;
3413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    while (*current >= '0' && *current <= '9') {
3423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (buffer_pos <= kMaxSignificantDigits) {
3433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        // If the number has more than kMaxSignificantDigits it will be parsed
3443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        // as infinity.
3453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        ASSERT(buffer_pos < kBufferSize);
3463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        buffer[buffer_pos++] = static_cast<char>(*current);
3473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
3483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ++current;
3493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (current == end) break;
3503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
3513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (!allow_trailing_junk &&
3533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        AdvanceToNonspace(unicode_cache, &current, end)) {
3543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return JunkStringValue();
3553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
3563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ASSERT(buffer_pos < kBufferSize);
3583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    buffer[buffer_pos] = '\0';
3593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Vector<const char> buffer_vector(buffer, buffer_pos);
3603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return negative ? -Strtod(buffer_vector, 0) : Strtod(buffer_vector, 0);
3613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
3623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // The following code causes accumulating rounding error for numbers greater
3643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // than ~2^56. It's explicitly allowed in the spec: "if R is not 2, 4, 8, 10,
3653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // 16, or 32, then mathInt may be an implementation-dependent approximation to
3663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // the mathematical integer value" (15.1.2.2).
3673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int lim_0 = '0' + (radix < 10 ? radix : 10);
3693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int lim_a = 'a' + (radix - 10);
3703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int lim_A = 'A' + (radix - 10);
3713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // NOTE: The code for computing the value may seem a bit complex at
3733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // first glance. It is structured to use 32-bit multiply-and-add
3743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // loops as long as possible to avoid loosing precision.
3753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  double v = 0.0;
3773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bool done = false;
3783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  do {
3793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Parse the longest part of the string starting at index j
3803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // possible while keeping the multiplier, and thus the part
3813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // itself, within 32 bits.
3823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    unsigned int part = 0, multiplier = 1;
3833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    while (true) {
3843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      int d;
3853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (*current >= '0' && *current < lim_0) {
3863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        d = *current - '0';
3873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      } else if (*current >= 'a' && *current < lim_a) {
3883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        d = *current - 'a' + 10;
3893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      } else if (*current >= 'A' && *current < lim_A) {
3903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        d = *current - 'A' + 10;
3913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      } else {
3923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        done = true;
3933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        break;
3943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
3953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // Update the value of the part as long as the multiplier fits
3973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // in 32 bits. When we can't guarantee that the next iteration
3983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // will not overflow the multiplier, we stop parsing the part
3993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // by leaving the loop.
4003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      const unsigned int kMaximumMultiplier = 0xffffffffU / 36;
4013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      uint32_t m = multiplier * radix;
4023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (m > kMaximumMultiplier) break;
4033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      part = part * radix + d;
4043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      multiplier = m;
4053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ASSERT(multiplier > part);
4063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ++current;
4083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (current == end) {
4093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        done = true;
4103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        break;
4113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
4123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
4133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Update the value and skip the part in the string.
4153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    v = v * multiplier + part;
4163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } while (!done);
4173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (!allow_trailing_junk &&
4193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      AdvanceToNonspace(unicode_cache, &current, end)) {
4203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return JunkStringValue();
4213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
4223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return negative ? -v : v;
4243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
4253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// Converts a string to a double value. Assumes the Iterator supports
4283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// the following operations:
4293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// 1. current == end (other ops are not allowed), current != end.
4303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// 2. *current - gets the current character in the sequence.
4313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// 3. ++current (advances the position).
4323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochtemplate <class Iterator, class EndMark>
4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochdouble InternalStringToDouble(UnicodeCache* unicode_cache,
4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              Iterator current,
4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              EndMark end,
4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              int flags,
4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              double empty_string_val) {
4383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // To make sure that iterator dereferencing is valid the following
4393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // convention is used:
4403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // 1. Each '++current' statement is followed by check for equality to 'end'.
4413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // 2. If AdvanceToNonspace returned false then current == end.
4423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // 3. If 'current' becomes be equal to 'end' the function returns or goes to
4433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // 'parsing_done'.
4443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // 4. 'current' is not dereferenced after the 'parsing_done' label.
4453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // 5. Code before 'parsing_done' may rely on 'current != end'.
4463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (!AdvanceToNonspace(unicode_cache, &current, end)) {
4473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return empty_string_val;
4483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
4493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const bool allow_trailing_junk = (flags & ALLOW_TRAILING_JUNK) != 0;
4513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // The longest form of simplified number is: "-<significant digits>'.1eXXX\0".
4533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int kBufferSize = kMaxSignificantDigits + 10;
4543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  char buffer[kBufferSize];  // NOLINT: size is known at compile time.
4553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int buffer_pos = 0;
4563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Exponent will be adjusted if insignificant digits of the integer part
4583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // or insignificant leading zeros of the fractional part are dropped.
4593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int exponent = 0;
4603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int significant_digits = 0;
4613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int insignificant_digits = 0;
4623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bool nonzero_digit_dropped = false;
4633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bool negative = false;
4653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (*current == '+') {
4673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Ignore leading sign.
4683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ++current;
4693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (current == end) return JunkStringValue();
4703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else if (*current == '-') {
4713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ++current;
4723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (current == end) return JunkStringValue();
4733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    negative = true;
4743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
4753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  static const char kInfinitySymbol[] = "Infinity";
4773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (*current == kInfinitySymbol[0]) {
4783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (!SubStringEquals(&current, end, kInfinitySymbol)) {
4793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return JunkStringValue();
4803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
4813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (!allow_trailing_junk &&
4833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        AdvanceToNonspace(unicode_cache, &current, end)) {
4843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return JunkStringValue();
4853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
4863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ASSERT(buffer_pos == 0);
4883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return negative ? -V8_INFINITY : V8_INFINITY;
4893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
4903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bool leading_zero = false;
4923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (*current == '0') {
4933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ++current;
4943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (current == end) return SignedZero(negative);
4953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    leading_zero = true;
4973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // It could be hexadecimal value.
4993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if ((flags & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {
5003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ++current;
5013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (current == end || !isDigit(*current, 16)) {
5023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        return JunkStringValue();  // "0x".
5033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
5043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return InternalStringToIntDouble<4>(unicode_cache,
5063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                          current,
5073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                          end,
5083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                          negative,
5093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                          allow_trailing_junk);
5103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
5113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Ignore leading zeros in the integer part.
5133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    while (*current == '0') {
5143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ++current;
5153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (current == end) return SignedZero(negative);
5163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
5173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
5183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bool octal = leading_zero && (flags & ALLOW_OCTALS) != 0;
5203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Copy significant digits of the integer part (if any) to the buffer.
5223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  while (*current >= '0' && *current <= '9') {
5233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (significant_digits < kMaxSignificantDigits) {
5243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ASSERT(buffer_pos < kBufferSize);
5253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      buffer[buffer_pos++] = static_cast<char>(*current);
5263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      significant_digits++;
5273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // Will later check if it's an octal in the buffer.
5283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
5293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      insignificant_digits++;  // Move the digit into the exponential part.
5303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
5313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
5323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    octal = octal && *current < '8';
5333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ++current;
5343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (current == end) goto parsing_done;
5353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
5363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (significant_digits == 0) {
5383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    octal = false;
5393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
5403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (*current == '.') {
5423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (octal && !allow_trailing_junk) return JunkStringValue();
5433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (octal) goto parsing_done;
5443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ++current;
5463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (current == end) {
5473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (significant_digits == 0 && !leading_zero) {
5483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        return JunkStringValue();
5493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      } else {
5503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        goto parsing_done;
5513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
5523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
5533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (significant_digits == 0) {
5553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // octal = false;
5563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // Integer part consists of 0 or is absent. Significant digits start after
5573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // leading zeros (if any).
5583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      while (*current == '0') {
5593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        ++current;
5603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        if (current == end) return SignedZero(negative);
5613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        exponent--;  // Move this 0 into the exponent.
5623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
5633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
5643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // There is a fractional part.  We don't emit a '.', but adjust the exponent
5663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // instead.
5673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    while (*current >= '0' && *current <= '9') {
5683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (significant_digits < kMaxSignificantDigits) {
5693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        ASSERT(buffer_pos < kBufferSize);
5703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        buffer[buffer_pos++] = static_cast<char>(*current);
5713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        significant_digits++;
5723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        exponent--;
5733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      } else {
5743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        // Ignore insignificant digits in the fractional part.
5753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
5763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
5773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ++current;
5783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (current == end) goto parsing_done;
5793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
5803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
5813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (!leading_zero && exponent == 0 && significant_digits == 0) {
5833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // If leading_zeros is true then the string contains zeros.
5843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // If exponent < 0 then string was [+-]\.0*...
5853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // If significant_digits != 0 the string is not equal to 0.
5863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Otherwise there are no digits in the string.
5873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return JunkStringValue();
5883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
5893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Parse exponential part.
5913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (*current == 'e' || *current == 'E') {
5923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (octal) return JunkStringValue();
5933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ++current;
5943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (current == end) {
5953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (allow_trailing_junk) {
5963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        goto parsing_done;
5973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      } else {
5983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        return JunkStringValue();
5993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
6003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
6013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    char sign = '+';
6023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (*current == '+' || *current == '-') {
6033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      sign = static_cast<char>(*current);
6043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ++current;
6053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (current == end) {
6063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        if (allow_trailing_junk) {
6073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          goto parsing_done;
6083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        } else {
6093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          return JunkStringValue();
6103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        }
6113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
6123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
6133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (current == end || *current < '0' || *current > '9') {
6153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (allow_trailing_junk) {
6163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        goto parsing_done;
6173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      } else {
6183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        return JunkStringValue();
6193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
6203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
6213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    const int max_exponent = INT_MAX / 2;
6233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
6243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int num = 0;
6253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    do {
6263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // Check overflow.
6273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      int digit = *current - '0';
6283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (num >= max_exponent / 10
6293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          && !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
6303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        num = max_exponent;
6313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      } else {
6323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        num = num * 10 + digit;
6333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
6343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ++current;
6353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } while (current != end && *current >= '0' && *current <= '9');
6363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    exponent += (sign == '-' ? -num : num);
6383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
6393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (!allow_trailing_junk &&
6413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      AdvanceToNonspace(unicode_cache, &current, end)) {
6423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return JunkStringValue();
6433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
6443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  parsing_done:
6463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  exponent += insignificant_digits;
6473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (octal) {
6493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return InternalStringToIntDouble<3>(unicode_cache,
6503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                        buffer,
6513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                        buffer + buffer_pos,
6523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                        negative,
6533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                        allow_trailing_junk);
6543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
6553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (nonzero_digit_dropped) {
6573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    buffer[buffer_pos++] = '1';
6583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    exponent--;
6593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
6603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(buffer_pos < kBufferSize);
6623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  buffer[buffer_pos] = '\0';
6633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
6653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return negative ? -converted : converted;
6663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
6673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // V8_CONVERSIONS_INL_H_
671