1
// Copyright 2010 the V8 project authors. All rights reserved.
2
// Redistribution and use in source and binary forms, with or without
3
// modification, are permitted provided that the following conditions are
6
// * Redistributions of source code must retain the above copyright
7
// notice, this list of conditions and the following disclaimer.
8
// * Redistributions in binary form must reproduce the above
9
// copyright notice, this list of conditions and the following
10
// disclaimer in the documentation and/or other materials provided
11
// with the distribution.
12
// * Neither the name of Google Inc. nor the names of its
13
// contributors may be used to endorse or promote products derived
14
// from this software without specific prior written permission.
16
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
#include "double-conversion.h"
35
#include "bignum-dtoa.h"
37
#include "fast-dtoa.h"
38
#include "fixed-dtoa.h"
44
namespace double_conversion {
46
const DoubleToStringConverter& DoubleToStringConverter::EcmaScriptConverter() {
47
int flags = UNIQUE_ZERO | EMIT_POSITIVE_EXPONENT_SIGN;
48
static DoubleToStringConverter converter(flags,
58
bool DoubleToStringConverter::HandleSpecialValues(
60
StringBuilder* result_builder) const {
61
Double double_inspect(value);
62
if (double_inspect.IsInfinite()) {
63
if (infinity_symbol_ == NULL) return false;
65
result_builder->AddCharacter('-');
67
result_builder->AddString(infinity_symbol_);
70
if (double_inspect.IsNan()) {
71
if (nan_symbol_ == NULL) return false;
72
result_builder->AddString(nan_symbol_);
79
void DoubleToStringConverter::CreateExponentialRepresentation(
80
const char* decimal_digits,
83
StringBuilder* result_builder) const {
85
result_builder->AddCharacter(decimal_digits[0]);
87
result_builder->AddCharacter('.');
88
result_builder->AddSubstring(&decimal_digits[1], length-1);
90
result_builder->AddCharacter(exponent_character_);
92
result_builder->AddCharacter('-');
95
if ((flags_ & EMIT_POSITIVE_EXPONENT_SIGN) != 0) {
96
result_builder->AddCharacter('+');
100
result_builder->AddCharacter('0');
103
ASSERT(exponent < 1e4);
104
const int kMaxExponentLength = 5;
105
char buffer[kMaxExponentLength + 1];
106
int first_char_pos = kMaxExponentLength;
107
buffer[first_char_pos] = '\0';
108
while (exponent > 0) {
109
buffer[--first_char_pos] = '0' + (exponent % 10);
112
result_builder->AddSubstring(&buffer[first_char_pos],
113
kMaxExponentLength - first_char_pos);
117
void DoubleToStringConverter::CreateDecimalRepresentation(
118
const char* decimal_digits,
121
int digits_after_point,
122
StringBuilder* result_builder) const {
123
// Create a representation that is padded with zeros if needed.
124
if (decimal_point <= 0) {
125
// "0.00000decimal_rep".
126
result_builder->AddCharacter('0');
127
if (digits_after_point > 0) {
128
result_builder->AddCharacter('.');
129
result_builder->AddPadding('0', -decimal_point);
130
ASSERT(length <= digits_after_point - (-decimal_point));
131
result_builder->AddSubstring(decimal_digits, length);
132
int remaining_digits = digits_after_point - (-decimal_point) - length;
133
result_builder->AddPadding('0', remaining_digits);
135
} else if (decimal_point >= length) {
136
// "decimal_rep0000.00000" or "decimal_rep.0000"
137
result_builder->AddSubstring(decimal_digits, length);
138
result_builder->AddPadding('0', decimal_point - length);
139
if (digits_after_point > 0) {
140
result_builder->AddCharacter('.');
141
result_builder->AddPadding('0', digits_after_point);
145
ASSERT(digits_after_point > 0);
146
result_builder->AddSubstring(decimal_digits, decimal_point);
147
result_builder->AddCharacter('.');
148
ASSERT(length - decimal_point <= digits_after_point);
149
result_builder->AddSubstring(&decimal_digits[decimal_point],
150
length - decimal_point);
151
int remaining_digits = digits_after_point - (length - decimal_point);
152
result_builder->AddPadding('0', remaining_digits);
154
if (digits_after_point == 0) {
155
if ((flags_ & EMIT_TRAILING_DECIMAL_POINT) != 0) {
156
result_builder->AddCharacter('.');
158
if ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) {
159
result_builder->AddCharacter('0');
165
bool DoubleToStringConverter::ToShortest(double value,
166
StringBuilder* result_builder) const {
167
if (Double(value).IsSpecial()) {
168
return HandleSpecialValues(value, result_builder);
173
const int kDecimalRepCapacity = kBase10MaximalLength + 1;
174
char decimal_rep[kDecimalRepCapacity];
175
int decimal_rep_length;
177
DoubleToAscii(value, SHORTEST, 0, decimal_rep, kDecimalRepCapacity,
178
&sign, &decimal_rep_length, &decimal_point);
180
bool unique_zero = (flags_ & UNIQUE_ZERO) != 0;
181
if (sign && (value != 0.0 || !unique_zero)) {
182
result_builder->AddCharacter('-');
185
int exponent = decimal_point - 1;
186
if ((decimal_in_shortest_low_ <= exponent) &&
187
(exponent < decimal_in_shortest_high_)) {
188
CreateDecimalRepresentation(decimal_rep, decimal_rep_length,
190
Max(0, decimal_rep_length - decimal_point),
193
CreateExponentialRepresentation(decimal_rep, decimal_rep_length, exponent,
200
bool DoubleToStringConverter::ToFixed(double value,
201
int requested_digits,
202
StringBuilder* result_builder) const {
203
ASSERT(kMaxFixedDigitsBeforePoint == 60);
204
const double kFirstNonFixed = 1e60;
206
if (Double(value).IsSpecial()) {
207
return HandleSpecialValues(value, result_builder);
210
if (requested_digits > kMaxFixedDigitsAfterPoint) return false;
211
if (value >= kFirstNonFixed || value <= -kFirstNonFixed) return false;
213
// Find a sufficiently precise decimal representation of n.
216
// Add space for the '\0' byte.
217
const int kDecimalRepCapacity =
218
kMaxFixedDigitsBeforePoint + kMaxFixedDigitsAfterPoint + 1;
219
char decimal_rep[kDecimalRepCapacity];
220
int decimal_rep_length;
221
DoubleToAscii(value, FIXED, requested_digits,
222
decimal_rep, kDecimalRepCapacity,
223
&sign, &decimal_rep_length, &decimal_point);
225
bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
226
if (sign && (value != 0.0 || !unique_zero)) {
227
result_builder->AddCharacter('-');
230
CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
231
requested_digits, result_builder);
236
bool DoubleToStringConverter::ToExponential(
238
int requested_digits,
239
StringBuilder* result_builder) const {
240
if (Double(value).IsSpecial()) {
241
return HandleSpecialValues(value, result_builder);
244
if (requested_digits < -1) return false;
245
if (requested_digits > kMaxExponentialDigits) return false;
249
// Add space for digit before the decimal point and the '\0' character.
250
const int kDecimalRepCapacity = kMaxExponentialDigits + 2;
251
ASSERT(kDecimalRepCapacity > kBase10MaximalLength);
252
char decimal_rep[kDecimalRepCapacity];
253
int decimal_rep_length;
255
if (requested_digits == -1) {
256
DoubleToAscii(value, SHORTEST, 0,
257
decimal_rep, kDecimalRepCapacity,
258
&sign, &decimal_rep_length, &decimal_point);
260
DoubleToAscii(value, PRECISION, requested_digits + 1,
261
decimal_rep, kDecimalRepCapacity,
262
&sign, &decimal_rep_length, &decimal_point);
263
ASSERT(decimal_rep_length <= requested_digits + 1);
265
for (int i = decimal_rep_length; i < requested_digits + 1; ++i) {
266
decimal_rep[i] = '0';
268
decimal_rep_length = requested_digits + 1;
271
bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
272
if (sign && (value != 0.0 || !unique_zero)) {
273
result_builder->AddCharacter('-');
276
int exponent = decimal_point - 1;
277
CreateExponentialRepresentation(decimal_rep,
285
bool DoubleToStringConverter::ToPrecision(double value,
287
StringBuilder* result_builder) const {
288
if (Double(value).IsSpecial()) {
289
return HandleSpecialValues(value, result_builder);
292
if (precision < kMinPrecisionDigits || precision > kMaxPrecisionDigits) {
296
// Find a sufficiently precise decimal representation of n.
299
// Add one for the terminating null character.
300
const int kDecimalRepCapacity = kMaxPrecisionDigits + 1;
301
char decimal_rep[kDecimalRepCapacity];
302
int decimal_rep_length;
304
DoubleToAscii(value, PRECISION, precision,
305
decimal_rep, kDecimalRepCapacity,
306
&sign, &decimal_rep_length, &decimal_point);
307
ASSERT(decimal_rep_length <= precision);
309
bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
310
if (sign && (value != 0.0 || !unique_zero)) {
311
result_builder->AddCharacter('-');
314
// The exponent if we print the number as x.xxeyyy. That is with the
315
// decimal point after the first digit.
316
int exponent = decimal_point - 1;
318
int extra_zero = ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) ? 1 : 0;
319
if ((-decimal_point + 1 > max_leading_padding_zeroes_in_precision_mode_) ||
320
(decimal_point - precision + extra_zero >
321
max_trailing_padding_zeroes_in_precision_mode_)) {
322
// Fill buffer to contain 'precision' digits.
323
// Usually the buffer is already at the correct length, but 'DoubleToAscii'
324
// is allowed to return less characters.
325
for (int i = decimal_rep_length; i < precision; ++i) {
326
decimal_rep[i] = '0';
329
CreateExponentialRepresentation(decimal_rep,
334
CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
335
Max(0, precision - decimal_point),
342
static BignumDtoaMode DtoaToBignumDtoaMode(
343
DoubleToStringConverter::DtoaMode dtoa_mode) {
345
case DoubleToStringConverter::SHORTEST: return BIGNUM_DTOA_SHORTEST;
346
case DoubleToStringConverter::FIXED: return BIGNUM_DTOA_FIXED;
347
case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISION;
350
return BIGNUM_DTOA_SHORTEST; // To silence compiler.
355
void DoubleToStringConverter::DoubleToAscii(double v,
357
int requested_digits,
363
Vector<char> vector(buffer, buffer_length);
364
ASSERT(!Double(v).IsSpecial());
365
ASSERT(mode == SHORTEST || requested_digits >= 0);
367
if (Double(v).Sign() < 0) {
374
if (mode == PRECISION && requested_digits == 0) {
391
fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST, 0, vector, length, point);
394
fast_worked = FastFixedDtoa(v, requested_digits, vector, length, point);
397
fast_worked = FastDtoa(v, FAST_DTOA_PRECISION, requested_digits,
398
vector, length, point);
404
if (fast_worked) return;
406
// If the fast dtoa didn't succeed use the slower bignum version.
407
BignumDtoaMode bignum_mode = DtoaToBignumDtoaMode(mode);
408
BignumDtoa(v, bignum_mode, requested_digits, vector, length, point);
409
vector[*length] = '\0';
413
// Maximum number of significant digits in decimal representation.
414
// The longest possible double in decimal representation is
415
// (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074
416
// (768 digits). If we parse a number whose first digits are equal to a
417
// mean of 2 adjacent doubles (that could have up to 769 digits) the result
418
// must be rounded to the bigger one unless the tail consists of zeros, so
419
// we don't need to preserve all the digits.
420
const int kMaxSignificantDigits = 772;
423
static double SignedZero(bool sign) {
424
return sign ? -0.0 : 0.0;
428
double StringToDoubleConverter::StringToDouble(
431
size_t* processed_characters_count) {
432
const char* current = input;
433
const char* end = input + length;
435
*processed_characters_count = 0;
437
// To make sure that iterator dereferencing is valid the following
438
// convention is used:
439
// 1. Each '++current' statement is followed by check for equality to 'end'.
440
// 3. If 'current' becomes equal to 'end' the function returns or goes to
442
// 4. 'current' is not dereferenced after the 'parsing_done' label.
443
// 5. Code before 'parsing_done' may rely on 'current != end'.
444
if (current == end) return 0.0;
446
// The longest form of simplified number is: "-<significant digits>.1eXXX\0".
447
const int kBufferSize = kMaxSignificantDigits + 10;
448
char buffer[kBufferSize]; // NOLINT: size is known at compile time.
451
// Exponent will be adjusted if insignificant digits of the integer part
452
// or insignificant leading zeros of the fractional part are dropped.
454
int significant_digits = 0;
455
int insignificant_digits = 0;
456
bool nonzero_digit_dropped = false;
459
if (*current == '+' || *current == '-') {
460
sign = (*current == '-');
462
if (current == end) return 0.0;
465
bool leading_zero = false;
466
if (*current == '0') {
468
if (current == end) {
469
*processed_characters_count = current - input;
470
return SignedZero(sign);
475
// Ignore leading zeros in the integer part.
476
while (*current == '0') {
478
if (current == end) {
479
*processed_characters_count = current - input;
480
return SignedZero(sign);
485
// Copy significant digits of the integer part (if any) to the buffer.
486
while (*current >= '0' && *current <= '9') {
487
if (significant_digits < kMaxSignificantDigits) {
488
ASSERT(buffer_pos < kBufferSize);
489
buffer[buffer_pos++] = static_cast<char>(*current);
490
significant_digits++;
492
insignificant_digits++; // Move the digit into the exponential part.
493
nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
496
if (current == end) goto parsing_done;
499
if (*current == '.') {
501
if (current == end) {
502
if (significant_digits == 0 && !leading_zero) {
509
if (significant_digits == 0) {
510
// Integer part consists of 0 or is absent. Significant digits start after
511
// leading zeros (if any).
512
while (*current == '0') {
514
if (current == end) {
515
*processed_characters_count = current - input;
516
return SignedZero(sign);
518
exponent--; // Move this 0 into the exponent.
522
// There is a fractional part.
523
while (*current >= '0' && *current <= '9') {
524
if (significant_digits < kMaxSignificantDigits) {
525
ASSERT(buffer_pos < kBufferSize);
526
buffer[buffer_pos++] = static_cast<char>(*current);
527
significant_digits++;
530
// Ignore insignificant digits in the fractional part.
531
nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
534
if (current == end) goto parsing_done;
538
if (!leading_zero && exponent == 0 && significant_digits == 0) {
539
// If leading_zeros is true then the string contains zeros.
540
// If exponent < 0 then string was [+-]\.0*...
541
// If significant_digits != 0 the string is not equal to 0.
542
// Otherwise there are no digits in the string.
546
// Parse exponential part.
547
if (*current == 'e' || *current == 'E') {
549
if (current == end) {
554
if (*current == '+' || *current == '-') {
555
sign = static_cast<char>(*current);
557
if (current == end) {
563
if (*current < '0' || *current > '9') {
570
const int max_exponent = INT_MAX / 2;
571
ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
575
int digit = *current - '0';
576
if (num >= max_exponent / 10
577
&& !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
580
num = num * 10 + digit;
583
} while (current != end && *current >= '0' && *current <= '9');
585
exponent += (sign == '-' ? -num : num);
589
exponent += insignificant_digits;
591
if (nonzero_digit_dropped) {
592
buffer[buffer_pos++] = '1';
596
ASSERT(buffer_pos < kBufferSize);
597
buffer[buffer_pos] = '\0';
599
double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
600
*processed_characters_count = current - input;
601
return sign? -converted: converted;
604
} // namespace double_conversion