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