1a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org// Copyright 2011 the V8 project authors. All rights reserved.
23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be
33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file.
443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
5b26c50a70863498de657ad44be2cffa49ccdcbeaager@chromium.org#include <limits.h>
64b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org#include <stdarg.h>
777ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org#include <cmath>
843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
9196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h"
10196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org
11196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/assert-scope.h"
12196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/conversions-inl.h"
134b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org#include "src/conversions.h"
14196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/dtoa.h"
15196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/factory.h"
16196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/list-inl.h"
17196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/strtod.h"
18196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/utils.h"
1943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2077ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org#ifndef _STLP_VENDOR_CSTD
2177ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org// STLPort doesn't import fpclassify into the std namespace.
2277ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.orgusing std::fpclassify;
2377ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org#endif
2477ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org
2571affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace v8 {
2671affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace internal {
2743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2825156ded31ef771a2d799ed902483d83b3ebcbdclrn@chromium.org
29a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.orgnamespace {
30a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org
31a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org// C++-style iterator adaptor for StringCharacterStream
32a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org// (unlike C++ iterators the end-marker has different type).
33a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.orgclass StringCharacterStreamIterator {
34a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org public:
35a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org  class EndMarker {};
36a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org
37a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org  explicit StringCharacterStreamIterator(StringCharacterStream* stream);
38a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org
39a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org  uint16_t operator*() const;
40a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org  void operator++();
41a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org  bool operator==(EndMarker const&) const { return end_; }
42a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org  bool operator!=(EndMarker const& m) const { return !end_; }
43a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org
44a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org private:
45a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org  StringCharacterStream* const stream_;
46a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org  uint16_t current_;
47a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org  bool end_;
48a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org};
49a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org
50a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org
51a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.orgStringCharacterStreamIterator::StringCharacterStreamIterator(
52a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org    StringCharacterStream* stream) : stream_(stream) {
53a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org  ++(*this);
54a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org}
55a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org
56a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.orguint16_t StringCharacterStreamIterator::operator*() const {
57a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org  return current_;
58a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org}
59a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org
60a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org
61a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.orgvoid StringCharacterStreamIterator::operator++() {
62a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org  end_ = !stream_->HasMore();
63a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org  if (!end_) {
64a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org    current_ = stream_->GetNext();
65a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org  }
66a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org}
67a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org}  // End anonymous namespace.
68a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org
69a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org
70a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.orgdouble StringToDouble(UnicodeCache* unicode_cache,
71a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org                      const char* str, int flags, double empty_string_val) {
72ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  // We cast to const uint8_t* here to avoid instantiating the
73ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  // InternalStringToDouble() template for const char* as well.
74ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  const uint8_t* start = reinterpret_cast<const uint8_t*>(str);
75ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  const uint8_t* end = start + StrLength(str);
76ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  return InternalStringToDouble(unicode_cache, start, end, flags,
77ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org                                empty_string_val);
7843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
7943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
8043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
81a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.orgdouble StringToDouble(UnicodeCache* unicode_cache,
822ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org                      Vector<const uint8_t> str,
8365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                      int flags,
8465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                      double empty_string_val) {
85ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  // We cast to const uint8_t* here to avoid instantiating the
86ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  // InternalStringToDouble() template for const char* as well.
87ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  const uint8_t* start = reinterpret_cast<const uint8_t*>(str.start());
88ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  const uint8_t* end = start + str.length();
89ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org  return InternalStringToDouble(unicode_cache, start, end, flags,
90ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org                                empty_string_val);
9165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
9265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
93ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org
9440cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.orgdouble StringToDouble(UnicodeCache* unicode_cache,
9540cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                      Vector<const uc16> str,
9640cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                      int flags,
9740cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                      double empty_string_val) {
9840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  const uc16* end = str.start() + str.length();
9940cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  return InternalStringToDouble(unicode_cache, str.start(), end, flags,
10040cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                                empty_string_val);
10140cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org}
10240cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org
10365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
1042ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org// Converts a string into an integer.
1052ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.orgdouble StringToInt(UnicodeCache* unicode_cache,
1062ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org                   Vector<const uint8_t> vector,
1072ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org                   int radix) {
1082ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org  return InternalStringToInt(
1092ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org      unicode_cache, vector.start(), vector.start() + vector.length(), radix);
1102ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org}
1112ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org
1122ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org
1132ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.orgdouble StringToInt(UnicodeCache* unicode_cache,
1142ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org                   Vector<const uc16> vector,
1152ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org                   int radix) {
1162ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org  return InternalStringToInt(
1172ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org      unicode_cache, vector.start(), vector.start() + vector.length(), radix);
1182ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org}
1192ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org
1202ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org
12143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenconst char* DoubleToCString(double v, Vector<char> buffer) {
12243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  switch (fpclassify(v)) {
12383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    case FP_NAN: return "NaN";
12483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    case FP_INFINITE: return (v < 0.0 ? "-Infinity" : "Infinity");
12583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    case FP_ZERO: return "0";
12643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    default: {
127ddda9e81d3175130f2029c0e1205d265a00c32edjkummerow@chromium.org      SimpleStringBuilder builder(buffer.start(), buffer.length());
12843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      int decimal_point;
12943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      int sign;
130720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org      const int kV8DtoaBufferCapacity = kBase10MaximalLength + 1;
1314a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com      char decimal_rep[kV8DtoaBufferCapacity];
132cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org      int length;
133720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org
1344a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com      DoubleToAscii(v, DTOA_SHORTEST, 0,
1354a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com                    Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
1364a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com                    &sign, &length, &decimal_point);
13743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
13843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      if (sign) builder.AddCharacter('-');
13943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
14043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      if (length <= decimal_point && decimal_point <= 21) {
14143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        // ECMA-262 section 9.8.1 step 6.
14243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        builder.AddString(decimal_rep);
14343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        builder.AddPadding('0', decimal_point - length);
14443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
14543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      } else if (0 < decimal_point && decimal_point <= 21) {
14643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        // ECMA-262 section 9.8.1 step 7.
14743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        builder.AddSubstring(decimal_rep, decimal_point);
14843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        builder.AddCharacter('.');
14943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        builder.AddString(decimal_rep + decimal_point);
15043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
15143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      } else if (decimal_point <= 0 && decimal_point > -6) {
15243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        // ECMA-262 section 9.8.1 step 8.
15343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        builder.AddString("0.");
15443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        builder.AddPadding('0', -decimal_point);
15543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        builder.AddString(decimal_rep);
15643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
15743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      } else {
15843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        // ECMA-262 section 9.8.1 step 9 and 10 combined.
15943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        builder.AddCharacter(decimal_rep[0]);
16043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        if (length != 1) {
16143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          builder.AddCharacter('.');
16243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          builder.AddString(decimal_rep + 1);
16343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        }
16443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        builder.AddCharacter('e');
16543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        builder.AddCharacter((decimal_point >= 0) ? '+' : '-');
16643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        int exponent = decimal_point - 1;
16743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        if (exponent < 0) exponent = -exponent;
168ddda9e81d3175130f2029c0e1205d265a00c32edjkummerow@chromium.org        builder.AddDecimalInteger(exponent);
16943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
17083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    return builder.Finalize();
17143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
17243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
17343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
17443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
17543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
17643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenconst char* IntToCString(int n, Vector<char> buffer) {
17743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  bool negative = false;
17843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (n < 0) {
17943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // We must not negate the most negative int.
18043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (n == kMinInt) return DoubleToCString(n, buffer);
18143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    negative = true;
18243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    n = -n;
18343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
18443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Build the string backwards from the least significant digit.
18543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int i = buffer.length();
18643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  buffer[--i] = '\0';
18743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  do {
18843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    buffer[--i] = '0' + (n % 10);
18943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    n /= 10;
19043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  } while (n);
19143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (negative) buffer[--i] = '-';
19243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return buffer.start() + i;
19343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
19443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
19543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
19643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenchar* DoubleToFixedCString(double value, int f) {
197f0ac72dfa39ec827de605aafc57d4834237aa7f3whesse@chromium.org  const int kMaxDigitsBeforePoint = 21;
198720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org  const double kFirstNonFixed = 1e21;
199720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org  const int kMaxDigitsAfterPoint = 20;
200e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(f >= 0);
201e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(f <= kMaxDigitsAfterPoint);
20243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
20343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  bool negative = false;
20443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  double abs_value = value;
20543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (value < 0) {
20643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    abs_value = -value;
20743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    negative = true;
20843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
20943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
210720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org  // If abs_value has more than kMaxDigitsBeforePoint digits before the point
211720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org  // use the non-fixed conversion routine.
212720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org  if (abs_value >= kFirstNonFixed) {
21343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    char arr[100];
214fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org    Vector<char> buffer(arr, arraysize(arr));
21543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return StrDup(DoubleToCString(value, buffer));
21643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
21743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
21843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Find a sufficiently precise decimal representation of n.
21943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int decimal_point;
22043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int sign;
221f0ac72dfa39ec827de605aafc57d4834237aa7f3whesse@chromium.org  // Add space for the '\0' byte.
222720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org  const int kDecimalRepCapacity =
223f0ac72dfa39ec827de605aafc57d4834237aa7f3whesse@chromium.org      kMaxDigitsBeforePoint + kMaxDigitsAfterPoint + 1;
224720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org  char decimal_rep[kDecimalRepCapacity];
225720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org  int decimal_rep_length;
2264a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  DoubleToAscii(value, DTOA_FIXED, f,
2274a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com                Vector<char>(decimal_rep, kDecimalRepCapacity),
2284a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com                &sign, &decimal_rep_length, &decimal_point);
22943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
23043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Create a representation that is padded with zeros if needed.
23143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int zero_prefix_length = 0;
23243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int zero_postfix_length = 0;
23343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
23443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (decimal_point <= 0) {
23543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    zero_prefix_length = -decimal_point + 1;
23643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    decimal_point = 1;
23743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
23843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
23943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (zero_prefix_length + decimal_rep_length < decimal_point + f) {
24043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    zero_postfix_length = decimal_point + f - decimal_rep_length -
24143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                          zero_prefix_length;
24243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
24343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
24443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  unsigned rep_length =
24543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      zero_prefix_length + decimal_rep_length + zero_postfix_length;
246ddda9e81d3175130f2029c0e1205d265a00c32edjkummerow@chromium.org  SimpleStringBuilder rep_builder(rep_length + 1);
24743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  rep_builder.AddPadding('0', zero_prefix_length);
24843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  rep_builder.AddString(decimal_rep);
24943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  rep_builder.AddPadding('0', zero_postfix_length);
25043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  char* rep = rep_builder.Finalize();
25143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
25243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Create the result string by appending a minus and putting in a
25343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // decimal point if needed.
25443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  unsigned result_size = decimal_point + f + 2;
255ddda9e81d3175130f2029c0e1205d265a00c32edjkummerow@chromium.org  SimpleStringBuilder builder(result_size + 1);
25643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (negative) builder.AddCharacter('-');
25743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  builder.AddSubstring(rep, decimal_point);
25843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (f > 0) {
25943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    builder.AddCharacter('.');
26043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    builder.AddSubstring(rep + decimal_point, f);
26143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
26243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  DeleteArray(rep);
26343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return builder.Finalize();
26443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
26543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
26643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
26743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenstatic char* CreateExponentialRepresentation(char* decimal_rep,
26843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                                             int exponent,
26943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                                             bool negative,
27043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                                             int significant_digits) {
27143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  bool negative_exponent = false;
27243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (exponent < 0) {
27343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    negative_exponent = true;
27443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    exponent = -exponent;
27543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
27643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
27743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Leave room in the result for appending a minus, for a period, the
27843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // letter 'e', a minus or a plus depending on the exponent, and a
27943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // three digit exponent.
28043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  unsigned result_size = significant_digits + 7;
281ddda9e81d3175130f2029c0e1205d265a00c32edjkummerow@chromium.org  SimpleStringBuilder builder(result_size + 1);
28243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
28343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (negative) builder.AddCharacter('-');
28443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  builder.AddCharacter(decimal_rep[0]);
28543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (significant_digits != 1) {
28643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    builder.AddCharacter('.');
28743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    builder.AddString(decimal_rep + 1);
288c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org    int rep_length = StrLength(decimal_rep);
289c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org    builder.AddPadding('0', significant_digits - rep_length);
29043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
29143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
29243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  builder.AddCharacter('e');
29343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  builder.AddCharacter(negative_exponent ? '-' : '+');
294ddda9e81d3175130f2029c0e1205d265a00c32edjkummerow@chromium.org  builder.AddDecimalInteger(exponent);
29543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return builder.Finalize();
29643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
29743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
29843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
29943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenchar* DoubleToExponentialCString(double value, int f) {
300c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  const int kMaxDigitsAfterPoint = 20;
30143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // f might be -1 to signal that f was undefined in JavaScript.
302e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(f >= -1 && f <= kMaxDigitsAfterPoint);
30343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
30443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  bool negative = false;
30543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (value < 0) {
30643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    value = -value;
30743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    negative = true;
30843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
30943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
31043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Find a sufficiently precise decimal representation of n.
31143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int decimal_point;
31243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int sign;
313c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  // f corresponds to the digits after the point. There is always one digit
314c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  // before the point. The number of requested_digits equals hence f + 1.
315c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  // And we have to add one character for the null-terminator.
316c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  const int kV8DtoaBufferCapacity = kMaxDigitsAfterPoint + 1 + 1;
317c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  // Make sure that the buffer is big enough, even if we fall back to the
318c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  // shortest representation (which happens when f equals -1).
319e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(kBase10MaximalLength <= kMaxDigitsAfterPoint + 1);
3204a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  char decimal_rep[kV8DtoaBufferCapacity];
321c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  int decimal_rep_length;
322c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org
32343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (f == -1) {
3244a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com    DoubleToAscii(value, DTOA_SHORTEST, 0,
3254a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com                  Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
3264a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com                  &sign, &decimal_rep_length, &decimal_point);
3274a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com    f = decimal_rep_length - 1;
32843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  } else {
3294a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com    DoubleToAscii(value, DTOA_PRECISION, f + 1,
3304a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com                  Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
3314a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com                  &sign, &decimal_rep_length, &decimal_point);
33243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
333e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(decimal_rep_length > 0);
334e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(decimal_rep_length <= f + 1);
33543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
33643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int exponent = decimal_point - 1;
33743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  char* result =
33843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      CreateExponentialRepresentation(decimal_rep, exponent, negative, f+1);
33943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
34043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return result;
34143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
34243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
34343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
34443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenchar* DoubleToPrecisionCString(double value, int p) {
345c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  const int kMinimalDigits = 1;
346c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  const int kMaximalDigits = 21;
347e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(p >= kMinimalDigits && p <= kMaximalDigits);
348c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  USE(kMinimalDigits);
34943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
35043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  bool negative = false;
35143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (value < 0) {
35243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    value = -value;
35343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    negative = true;
35443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
35543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
35643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Find a sufficiently precise decimal representation of n.
35743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int decimal_point;
35843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int sign;
359c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  // Add one for the terminating null character.
360c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  const int kV8DtoaBufferCapacity = kMaximalDigits + 1;
3614a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  char decimal_rep[kV8DtoaBufferCapacity];
362c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  int decimal_rep_length;
363c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org
3644a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  DoubleToAscii(value, DTOA_PRECISION, p,
3654a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com                Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
3664a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com                &sign, &decimal_rep_length, &decimal_point);
367e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(decimal_rep_length <= p);
36843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
36943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int exponent = decimal_point - 1;
37043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
37143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  char* result = NULL;
37243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
37343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (exponent < -6 || exponent >= p) {
37443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    result =
37543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        CreateExponentialRepresentation(decimal_rep, exponent, negative, p);
37643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  } else {
37743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // Use fixed notation.
37843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //
37943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // Leave room in the result for appending a minus, a period and in
38043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // the case where decimal_point is not positive for a zero in
38143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // front of the period.
38243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    unsigned result_size = (decimal_point <= 0)
38343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        ? -decimal_point + p + 3
38443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        : p + 2;
385ddda9e81d3175130f2029c0e1205d265a00c32edjkummerow@chromium.org    SimpleStringBuilder builder(result_size + 1);
38643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (negative) builder.AddCharacter('-');
38743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (decimal_point <= 0) {
38843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      builder.AddString("0.");
38943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      builder.AddPadding('0', -decimal_point);
39043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      builder.AddString(decimal_rep);
39143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      builder.AddPadding('0', p - decimal_rep_length);
39243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    } else {
39343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      const int m = Min(decimal_rep_length, decimal_point);
39443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      builder.AddSubstring(decimal_rep, m);
39543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      builder.AddPadding('0', decimal_point - decimal_rep_length);
39643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      if (decimal_point < p) {
39743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        builder.AddCharacter('.');
39843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        const int extra = negative ? 2 : 1;
39943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        if (decimal_rep_length > decimal_point) {
400c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org          const int len = StrLength(decimal_rep + decimal_point);
40143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          const int n = Min(len, p - (builder.position() - extra));
40243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          builder.AddSubstring(decimal_rep + decimal_point, n);
40343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        }
40443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        builder.AddPadding('0', extra + (p - builder.position()));
40543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
40643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
40743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    result = builder.Finalize();
40843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
40943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
41043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return result;
41143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
41243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
41343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
41443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenchar* DoubleToRadixCString(double value, int radix) {
415e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(radix >= 2 && radix <= 36);
41643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
41743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Character array used for conversion.
41843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  static const char chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
41943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
42043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Buffer for the integer part of the result. 1024 chars is enough
42143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // for max integer value in radix 2.  We need room for a sign too.
42243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  static const int kBufferSize = 1100;
42343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  char integer_buffer[kBufferSize];
42443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  integer_buffer[kBufferSize - 1] = '\0';
42543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
42643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Buffer for the decimal part of the result.  We only generate up
42743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // to kBufferSize - 1 chars for the decimal part.
42843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  char decimal_buffer[kBufferSize];
42943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  decimal_buffer[kBufferSize - 1] = '\0';
43043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
43143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Make sure the value is positive.
43243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  bool is_negative = value < 0.0;
43343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (is_negative) value = -value;
43443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
43543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Get the integer part and the decimal part.
436e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org  double integer_part = std::floor(value);
43743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  double decimal_part = value - integer_part;
43843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
43943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Convert the integer part starting from the back.  Always generate
44043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // at least one digit.
44143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int integer_pos = kBufferSize - 2;
44243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  do {
443e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org    double remainder = std::fmod(integer_part, radix);
444c86e8c29eea534916f0d6a2a285b65a86d1b3b67machenbach@chromium.org    integer_buffer[integer_pos--] = chars[static_cast<int>(remainder)];
445c86e8c29eea534916f0d6a2a285b65a86d1b3b67machenbach@chromium.org    integer_part -= remainder;
44643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    integer_part /= radix;
44743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  } while (integer_part >= 1.0);
44843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Sanity check.
449e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(integer_pos > 0);
45043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Add sign if needed.
45143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (is_negative) integer_buffer[integer_pos--] = '-';
45243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
45343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Convert the decimal part.  Repeatedly multiply by the radix to
45443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // generate the next char.  Never generate more than kBufferSize - 1
45543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // chars.
45643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //
45743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // TODO(1093998): We will often generate a full decimal_buffer of
45843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // chars because hitting zero will often not happen.  The right
45943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // solution would be to continue until the string representation can
46043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // be read back and yield the original value.  To implement this
46143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // efficiently, we probably have to modify dtoa.
46243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int decimal_pos = 0;
46343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  while ((decimal_part > 0.0) && (decimal_pos < kBufferSize - 1)) {
46443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    decimal_part *= radix;
46543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    decimal_buffer[decimal_pos++] =
466e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org        chars[static_cast<int>(std::floor(decimal_part))];
467e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org    decimal_part -= std::floor(decimal_part);
46843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
46943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  decimal_buffer[decimal_pos] = '\0';
47043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
47143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Compute the result size.
47243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int integer_part_size = kBufferSize - 2 - integer_pos;
47343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Make room for zero termination.
47443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  unsigned result_size = integer_part_size + decimal_pos;
47543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // If the number has a decimal part, leave room for the period.
47643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (decimal_pos > 0) result_size++;
47743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Allocate result and fill in the parts.
478ddda9e81d3175130f2029c0e1205d265a00c32edjkummerow@chromium.org  SimpleStringBuilder builder(result_size + 1);
47943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  builder.AddSubstring(integer_buffer + integer_pos + 1, integer_part_size);
48043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (decimal_pos > 0) builder.AddCharacter('.');
48143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  builder.AddSubstring(decimal_buffer, decimal_pos);
48243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return builder.Finalize();
48343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
48443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
485a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org
486a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.orgdouble StringToDouble(UnicodeCache* unicode_cache,
487a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org                      String* string,
488a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org                      int flags,
489a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org                      double empty_string_val) {
490a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org  DisallowHeapAllocation no_gc;
491a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org  String::FlatContent flat = string->GetFlatContent();
492a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org  // ECMA-262 section 15.1.2.3, empty string is NaN
4932c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  if (flat.IsOneByte()) {
494a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org    return StringToDouble(
495a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org        unicode_cache, flat.ToOneByteVector(), flags, empty_string_val);
496a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org  } else {
497a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org    return StringToDouble(
498a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org        unicode_cache, flat.ToUC16Vector(), flags, empty_string_val);
499a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org  }
500a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org}
501a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org
502a70700b91bc28abeed6373b856017f7f9cc8273bmachenbach@chromium.org
50343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} }  // namespace v8::internal
504