18b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
56ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#include <limits.h>
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <stdarg.h>
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <cmath>
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8.h"
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/assert-scope.h"
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/conversions-inl.h"
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/conversions.h"
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/dtoa.h"
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/factory.h"
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/list-inl.h"
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/strtod.h"
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/utils.h"
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifndef _STLP_VENDOR_CSTD
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// STLPort doesn't import fpclassify into the std namespace.
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochusing std::fpclassify;
23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace {
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// C++-style iterator adaptor for StringCharacterStream
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// (unlike C++ iterators the end-marker has different type).
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass StringCharacterStreamIterator {
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  class EndMarker {};
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit StringCharacterStreamIterator(StringCharacterStream* stream);
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint16_t operator*() const;
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void operator++();
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool operator==(EndMarker const&) const { return end_; }
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool operator!=(EndMarker const& m) const { return !end_; }
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StringCharacterStream* const stream_;
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint16_t current_;
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool end_;
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochStringCharacterStreamIterator::StringCharacterStreamIterator(
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    StringCharacterStream* stream) : stream_(stream) {
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ++(*this);
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochuint16_t StringCharacterStreamIterator::operator*() const {
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return current_;
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid StringCharacterStreamIterator::operator++() {
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  end_ = !stream_->HasMore();
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!end_) {
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    current_ = stream_->GetNext();
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}  // End anonymous namespace.
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochdouble StringToDouble(UnicodeCache* unicode_cache,
718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      const char* str, int flags, double empty_string_val) {
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We cast to const uint8_t* here to avoid instantiating the
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // InternalStringToDouble() template for const char* as well.
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const uint8_t* start = reinterpret_cast<const uint8_t*>(str);
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const uint8_t* end = start + StrLength(str);
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return InternalStringToDouble(unicode_cache, start, end, flags,
7744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                empty_string_val);
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochdouble StringToDouble(UnicodeCache* unicode_cache,
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      Vector<const uint8_t> str,
8380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                      int flags,
8480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                      double empty_string_val) {
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We cast to const uint8_t* here to avoid instantiating the
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // InternalStringToDouble() template for const char* as well.
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const uint8_t* start = reinterpret_cast<const uint8_t*>(str.start());
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const uint8_t* end = start + str.length();
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return InternalStringToDouble(unicode_cache, start, end, flags,
9044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                empty_string_val);
9180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
9280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
94257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochdouble StringToDouble(UnicodeCache* unicode_cache,
95257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      Vector<const uc16> str,
96257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      int flags,
97257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      double empty_string_val) {
98257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const uc16* end = str.start() + str.length();
99257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return InternalStringToDouble(unicode_cache, str.start(), end, flags,
100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                empty_string_val);
101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Converts a string into an integer.
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdouble StringToInt(UnicodeCache* unicode_cache,
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   Vector<const uint8_t> vector,
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   int radix) {
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return InternalStringToInt(
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      unicode_cache, vector.start(), vector.start() + vector.length(), radix);
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdouble StringToInt(UnicodeCache* unicode_cache,
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   Vector<const uc16> vector,
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   int radix) {
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return InternalStringToInt(
117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      unicode_cache, vector.start(), vector.start() + vector.length(), radix);
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* DoubleToCString(double v, Vector<char> buffer) {
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (fpclassify(v)) {
1231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    case FP_NAN: return "NaN";
1241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    case FP_INFINITE: return (v < 0.0 ? "-Infinity" : "Infinity");
1251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    case FP_ZERO: return "0";
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default: {
1273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      SimpleStringBuilder builder(buffer.start(), buffer.length());
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int decimal_point;
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int sign;
13025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      const int kV8DtoaBufferCapacity = kBase10MaximalLength + 1;
1318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      char decimal_rep[kV8DtoaBufferCapacity];
1326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      int length;
13325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
1348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      DoubleToAscii(v, DTOA_SHORTEST, 0,
1358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                    Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
1368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                    &sign, &length, &decimal_point);
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (sign) builder.AddCharacter('-');
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (length <= decimal_point && decimal_point <= 21) {
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // ECMA-262 section 9.8.1 step 6.
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder.AddString(decimal_rep);
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder.AddPadding('0', decimal_point - length);
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (0 < decimal_point && decimal_point <= 21) {
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // ECMA-262 section 9.8.1 step 7.
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder.AddSubstring(decimal_rep, decimal_point);
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder.AddCharacter('.');
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder.AddString(decimal_rep + decimal_point);
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (decimal_point <= 0 && decimal_point > -6) {
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // ECMA-262 section 9.8.1 step 8.
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder.AddString("0.");
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder.AddPadding('0', -decimal_point);
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder.AddString(decimal_rep);
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // ECMA-262 section 9.8.1 step 9 and 10 combined.
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder.AddCharacter(decimal_rep[0]);
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (length != 1) {
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          builder.AddCharacter('.');
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          builder.AddString(decimal_rep + 1);
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder.AddCharacter('e');
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder.AddCharacter((decimal_point >= 0) ? '+' : '-');
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int exponent = decimal_point - 1;
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (exponent < 0) exponent = -exponent;
1683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        builder.AddDecimalInteger(exponent);
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return builder.Finalize();
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* IntToCString(int n, Vector<char> buffer) {
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool negative = false;
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (n < 0) {
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // We must not negate the most negative int.
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (n == kMinInt) return DoubleToCString(n, buffer);
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    negative = true;
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    n = -n;
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Build the string backwards from the least significant digit.
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int i = buffer.length();
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  buffer[--i] = '\0';
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  do {
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    buffer[--i] = '0' + (n % 10);
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    n /= 10;
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } while (n);
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (negative) buffer[--i] = '-';
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return buffer.start() + i;
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockchar* DoubleToFixedCString(double value, int f) {
1973e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  const int kMaxDigitsBeforePoint = 21;
19825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  const double kFirstNonFixed = 1e21;
19925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  const int kMaxDigitsAfterPoint = 20;
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(f >= 0);
201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(f <= kMaxDigitsAfterPoint);
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool negative = false;
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  double abs_value = value;
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (value < 0) {
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    abs_value = -value;
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    negative = true;
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // If abs_value has more than kMaxDigitsBeforePoint digits before the point
21125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // use the non-fixed conversion routine.
21225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  if (abs_value >= kFirstNonFixed) {
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    char arr[100];
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Vector<char> buffer(arr, arraysize(arr));
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return StrDup(DoubleToCString(value, buffer));
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Find a sufficiently precise decimal representation of n.
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int decimal_point;
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int sign;
2213e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // Add space for the '\0' byte.
22225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  const int kDecimalRepCapacity =
2233e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      kMaxDigitsBeforePoint + kMaxDigitsAfterPoint + 1;
22425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  char decimal_rep[kDecimalRepCapacity];
22525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  int decimal_rep_length;
2268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  DoubleToAscii(value, DTOA_FIXED, f,
2278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                Vector<char>(decimal_rep, kDecimalRepCapacity),
2288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                &sign, &decimal_rep_length, &decimal_point);
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a representation that is padded with zeros if needed.
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int zero_prefix_length = 0;
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int zero_postfix_length = 0;
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (decimal_point <= 0) {
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    zero_prefix_length = -decimal_point + 1;
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    decimal_point = 1;
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (zero_prefix_length + decimal_rep_length < decimal_point + f) {
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    zero_postfix_length = decimal_point + f - decimal_rep_length -
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          zero_prefix_length;
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  unsigned rep_length =
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      zero_prefix_length + decimal_rep_length + zero_postfix_length;
2463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  SimpleStringBuilder rep_builder(rep_length + 1);
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rep_builder.AddPadding('0', zero_prefix_length);
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rep_builder.AddString(decimal_rep);
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rep_builder.AddPadding('0', zero_postfix_length);
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char* rep = rep_builder.Finalize();
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create the result string by appending a minus and putting in a
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // decimal point if needed.
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  unsigned result_size = decimal_point + f + 2;
2553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  SimpleStringBuilder builder(result_size + 1);
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (negative) builder.AddCharacter('-');
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  builder.AddSubstring(rep, decimal_point);
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (f > 0) {
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    builder.AddCharacter('.');
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    builder.AddSubstring(rep + decimal_point, f);
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DeleteArray(rep);
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return builder.Finalize();
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic char* CreateExponentialRepresentation(char* decimal_rep,
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             int exponent,
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             bool negative,
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             int significant_digits) {
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool negative_exponent = false;
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (exponent < 0) {
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    negative_exponent = true;
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    exponent = -exponent;
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Leave room in the result for appending a minus, for a period, the
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // letter 'e', a minus or a plus depending on the exponent, and a
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // three digit exponent.
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  unsigned result_size = significant_digits + 7;
2813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  SimpleStringBuilder builder(result_size + 1);
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (negative) builder.AddCharacter('-');
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  builder.AddCharacter(decimal_rep[0]);
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (significant_digits != 1) {
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    builder.AddCharacter('.');
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    builder.AddString(decimal_rep + 1);
288d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    int rep_length = StrLength(decimal_rep);
289d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    builder.AddPadding('0', significant_digits - rep_length);
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  builder.AddCharacter('e');
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  builder.AddCharacter(negative_exponent ? '-' : '+');
2943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  builder.AddDecimalInteger(exponent);
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return builder.Finalize();
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockchar* DoubleToExponentialCString(double value, int f) {
3000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  const int kMaxDigitsAfterPoint = 20;
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // f might be -1 to signal that f was undefined in JavaScript.
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(f >= -1 && f <= kMaxDigitsAfterPoint);
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool negative = false;
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (value < 0) {
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    value = -value;
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    negative = true;
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Find a sufficiently precise decimal representation of n.
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int decimal_point;
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int sign;
3130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // f corresponds to the digits after the point. There is always one digit
3140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // before the point. The number of requested_digits equals hence f + 1.
3150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // And we have to add one character for the null-terminator.
3160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  const int kV8DtoaBufferCapacity = kMaxDigitsAfterPoint + 1 + 1;
3170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Make sure that the buffer is big enough, even if we fall back to the
3180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // shortest representation (which happens when f equals -1).
319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(kBase10MaximalLength <= kMaxDigitsAfterPoint + 1);
3208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  char decimal_rep[kV8DtoaBufferCapacity];
3210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int decimal_rep_length;
3220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (f == -1) {
3248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    DoubleToAscii(value, DTOA_SHORTEST, 0,
3258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                  Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
3268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                  &sign, &decimal_rep_length, &decimal_point);
3278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    f = decimal_rep_length - 1;
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
3298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    DoubleToAscii(value, DTOA_PRECISION, f + 1,
3308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                  Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
3318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                  &sign, &decimal_rep_length, &decimal_point);
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(decimal_rep_length > 0);
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(decimal_rep_length <= f + 1);
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int exponent = decimal_point - 1;
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char* result =
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CreateExponentialRepresentation(decimal_rep, exponent, negative, f+1);
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return result;
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockchar* DoubleToPrecisionCString(double value, int p) {
3450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  const int kMinimalDigits = 1;
3460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  const int kMaximalDigits = 21;
347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(p >= kMinimalDigits && p <= kMaximalDigits);
3480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  USE(kMinimalDigits);
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool negative = false;
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (value < 0) {
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    value = -value;
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    negative = true;
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Find a sufficiently precise decimal representation of n.
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int decimal_point;
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int sign;
3590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Add one for the terminating null character.
3600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  const int kV8DtoaBufferCapacity = kMaximalDigits + 1;
3618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  char decimal_rep[kV8DtoaBufferCapacity];
3620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int decimal_rep_length;
3630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  DoubleToAscii(value, DTOA_PRECISION, p,
3658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
3668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                &sign, &decimal_rep_length, &decimal_point);
367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(decimal_rep_length <= p);
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int exponent = decimal_point - 1;
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char* result = NULL;
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (exponent < -6 || exponent >= p) {
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    result =
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        CreateExponentialRepresentation(decimal_rep, exponent, negative, p);
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Use fixed notation.
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Leave room in the result for appending a minus, a period and in
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // the case where decimal_point is not positive for a zero in
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // front of the period.
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    unsigned result_size = (decimal_point <= 0)
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ? -decimal_point + p + 3
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        : p + 2;
3853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    SimpleStringBuilder builder(result_size + 1);
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (negative) builder.AddCharacter('-');
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (decimal_point <= 0) {
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      builder.AddString("0.");
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      builder.AddPadding('0', -decimal_point);
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      builder.AddString(decimal_rep);
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      builder.AddPadding('0', p - decimal_rep_length);
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      const int m = Min(decimal_rep_length, decimal_point);
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      builder.AddSubstring(decimal_rep, m);
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      builder.AddPadding('0', decimal_point - decimal_rep_length);
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (decimal_point < p) {
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder.AddCharacter('.');
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        const int extra = negative ? 2 : 1;
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (decimal_rep_length > decimal_point) {
400d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          const int len = StrLength(decimal_rep + decimal_point);
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          const int n = Min(len, p - (builder.position() - extra));
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          builder.AddSubstring(decimal_rep + decimal_point, n);
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder.AddPadding('0', extra + (p - builder.position()));
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    result = builder.Finalize();
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return result;
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockchar* DoubleToRadixCString(double value, int radix) {
415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(radix >= 2 && radix <= 36);
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Character array used for conversion.
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const char chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Buffer for the integer part of the result. 1024 chars is enough
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // for max integer value in radix 2.  We need room for a sign too.
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kBufferSize = 1100;
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char integer_buffer[kBufferSize];
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  integer_buffer[kBufferSize - 1] = '\0';
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Buffer for the decimal part of the result.  We only generate up
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to kBufferSize - 1 chars for the decimal part.
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char decimal_buffer[kBufferSize];
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  decimal_buffer[kBufferSize - 1] = '\0';
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure the value is positive.
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool is_negative = value < 0.0;
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (is_negative) value = -value;
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the integer part and the decimal part.
436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  double integer_part = std::floor(value);
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  double decimal_part = value - integer_part;
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Convert the integer part starting from the back.  Always generate
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // at least one digit.
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int integer_pos = kBufferSize - 2;
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  do {
443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    double remainder = std::fmod(integer_part, radix);
444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    integer_buffer[integer_pos--] = chars[static_cast<int>(remainder)];
445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    integer_part -= remainder;
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    integer_part /= radix;
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } while (integer_part >= 1.0);
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Sanity check.
449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(integer_pos > 0);
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Add sign if needed.
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (is_negative) integer_buffer[integer_pos--] = '-';
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Convert the decimal part.  Repeatedly multiply by the radix to
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // generate the next char.  Never generate more than kBufferSize - 1
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // chars.
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // TODO(1093998): We will often generate a full decimal_buffer of
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // chars because hitting zero will often not happen.  The right
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // solution would be to continue until the string representation can
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // be read back and yield the original value.  To implement this
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // efficiently, we probably have to modify dtoa.
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int decimal_pos = 0;
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while ((decimal_part > 0.0) && (decimal_pos < kBufferSize - 1)) {
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    decimal_part *= radix;
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    decimal_buffer[decimal_pos++] =
466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        chars[static_cast<int>(std::floor(decimal_part))];
467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    decimal_part -= std::floor(decimal_part);
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  decimal_buffer[decimal_pos] = '\0';
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compute the result size.
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int integer_part_size = kBufferSize - 2 - integer_pos;
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make room for zero termination.
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  unsigned result_size = integer_part_size + decimal_pos;
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the number has a decimal part, leave room for the period.
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (decimal_pos > 0) result_size++;
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate result and fill in the parts.
4783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  SimpleStringBuilder builder(result_size + 1);
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  builder.AddSubstring(integer_buffer + integer_pos + 1, integer_part_size);
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (decimal_pos > 0) builder.AddCharacter('.');
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  builder.AddSubstring(decimal_buffer, decimal_pos);
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return builder.Finalize();
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdouble StringToDouble(UnicodeCache* unicode_cache,
487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      String* string,
488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      int flags,
489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      double empty_string_val) {
490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DisallowHeapAllocation no_gc;
491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  String::FlatContent flat = string->GetFlatContent();
492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // ECMA-262 section 15.1.2.3, empty string is NaN
493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (flat.IsOneByte()) {
494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return StringToDouble(
495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        unicode_cache, flat.ToOneByteVector(), flags, empty_string_val);
496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return StringToDouble(
498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        unicode_cache, flat.ToUC16Vector(), flags, empty_string_val);
499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
504