Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(408)

Side by Side Diff: runtime/vm/double_conversion.cc

Issue 9113043: Implement Double.{toString, toStringAsExponential, toStringAsPrecision} (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Don't use NULL and rebase. Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/double_conversion.h" 5 #include "vm/double_conversion.h"
6 6
7 #include "third_party/double-conversion/src/double-conversion.h" 7 #include "third_party/double-conversion/src/double-conversion.h"
8 8
9 #include "vm/exceptions.h" 9 #include "vm/exceptions.h"
10 #include "vm/globals.h" 10 #include "vm/globals.h"
11 #include "vm/object.h" 11 #include "vm/object.h"
12 12
13 namespace dart { 13 namespace dart {
14 14
15 static const char kDoubleToStringCommonExponentChar = 'e'; 15 static const char kDoubleToStringCommonExponentChar = 'e';
16 static const char* kDoubleToStringCommonInfinitySymbol = "Infinity"; 16 static const char* kDoubleToStringCommonInfinitySymbol = "Infinity";
17 static const char* kDoubleToStringCommonNaNSymbol = "NaN"; 17 static const char* kDoubleToStringCommonNaNSymbol = "NaN";
18 18
19 bool DoubleToString(double d, String& result) { 19 bool DoubleToCString(double d, char* buffer, int buffer_size,
Ivan Posva 2012/02/27 14:47:14 Nit: We do either all parameters on new line or on
floitsch 2012/02/27 19:55:40 Done.
20 int* result_length) {
20 static const int kDecimalLow = -6; 21 static const int kDecimalLow = -6;
21 static const int kDecimalHigh = 21; 22 static const int kDecimalHigh = 21;
23
24 // The output contains the sign, at most kDecimalHigh - 1 digits,
25 // the decimal point followed by a 0 plus the \0.
26 ASSERT(buffer_size >= 1 + (kDecimalHigh - 1) + 1 + 1 + 1);
27 // Or it contains the sign, a 0, the decimal point, kDecimalLow '0's,
28 // 17 digits (the precision needed for doubles), plus the \0.
29 ASSERT(buffer_size >= 1 + 1 + 1 + kDecimalLow + 17 + 1);
30 // Alternatively it contains a sign, at most 17 digits (precision needed for
31 // any double), the decimal point, the exponent character, the exponent's
32 // sign, at most three exponent digits, plus the \0.
33 ASSERT(buffer_size >= 1 + 17 + 1 + 1 + 1 + 3 + 1);
34
22 static const int kConversionFlags = 35 static const int kConversionFlags =
23 double_conversion::DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN | 36 double_conversion::DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN |
24 double_conversion::DoubleToStringConverter::EMIT_TRAILING_DECIMAL_POINT | 37 double_conversion::DoubleToStringConverter::EMIT_TRAILING_DECIMAL_POINT |
25 double_conversion::DoubleToStringConverter::EMIT_TRAILING_ZERO_AFTER_POINT; 38 double_conversion::DoubleToStringConverter::EMIT_TRAILING_ZERO_AFTER_POINT;
26 const int kBufferSize = 128;
27 // The output contains the sign, at most kDecimalHigh - 1 digits,
28 // the decimal point followed by a 0 plus the \0.
29 ASSERT(kBufferSize >= 1 + (kDecimalHigh - 1) + 1 + 1 + 1);
30 // Or it contains the sign, a 0, the decimal point, kDecimalLow '0's,
31 // 17 digits (the precision needed for doubles), plus the \0.
32 ASSERT(kBufferSize >= 1 + 1 + 1 + kDecimalLow + 17 + 1);
33 // Alternatively it contains a sign, at most 17 digits (precision needed for
34 // any double), the decimal point, the exponent character, the exponent's
35 // sign, at most three exponent digits, plus the \0.
36 ASSERT(kBufferSize >= 1 + 17 + 1 + 1 + 1 + 3 + 1);
37 39
38 const double_conversion::DoubleToStringConverter converter( 40 const double_conversion::DoubleToStringConverter converter(
39 kConversionFlags, 41 kConversionFlags,
40 kDoubleToStringCommonInfinitySymbol, 42 kDoubleToStringCommonInfinitySymbol,
41 kDoubleToStringCommonNaNSymbol, 43 kDoubleToStringCommonNaNSymbol,
42 kDoubleToStringCommonExponentChar, 44 kDoubleToStringCommonExponentChar,
43 kDecimalLow, 45 kDecimalLow,
44 kDecimalHigh, 46 kDecimalHigh,
45 0, 0); // Last two values are ignored in shortest mode. 47 0, 0); // Last two values are ignored in shortest mode.
46 48
47 UNIMPLEMENTED(); 49 double_conversion::StringBuilder builder(buffer, buffer_size);
48 return false; 50 bool status = converter.ToShortest(d, &builder);
51 if (!status) return false;
52 *result_length = builder.position() + 1; // Include trailing \0 character.
53 char* result = builder.Finalize();
54 ASSERT(result == buffer);
55 return true;
49 } 56 }
50 57
51 bool DoubleToStringAsFixed(double d, int fraction_digits, String& result) { 58 RawString* DoubleToStringAsFixed(double d, int fraction_digits) {
52 static const int kMinFractionDigits = 0; 59 static const int kMinFractionDigits = 0;
53 static const int kMaxFractionDigits = 20; 60 static const int kMaxFractionDigits = 20;
54 static const int kMaxDigitsBeforePoint = 20; 61 static const int kMaxDigitsBeforePoint = 20;
55 // The boundaries are exclusive. 62 // The boundaries are exclusive.
56 static const double kLowerBoundary = -1e21; 63 static const double kLowerBoundary = -1e21;
57 static const double kUpperBoundary = 1e21; 64 static const double kUpperBoundary = 1e21;
58 // TODO(floitsch): remove the UNIQUE_ZERO flag when the test is updated. 65 // TODO(floitsch): remove the UNIQUE_ZERO flag when the test is updated.
59 static const int kConversionFlags = 66 static const int kConversionFlags =
60 double_conversion::DoubleToStringConverter::UNIQUE_ZERO; 67 double_conversion::DoubleToStringConverter::NO_FLAGS;
61 const int kBufferSize = 128; 68 const int kBufferSize = 128;
69
70 USE(kMaxDigitsBeforePoint);
71 USE(kMaxFractionDigits);
72 USE(kLowerBoundary);
73 USE(kUpperBoundary);
74 USE(kMinFractionDigits);
75 USE(kMaxFractionDigits);
62 // The output contains the sign, at most kMaxDigitsBeforePoint digits, 76 // The output contains the sign, at most kMaxDigitsBeforePoint digits,
63 // the decimal point followed by at most fraction_digits digits plus the \0. 77 // the decimal point followed by at most fraction_digits digits plus the \0.
64 ASSERT(kBufferSize >= 1 + kMaxDigitsBeforePoint + 1 + kMaxFractionDigits + 1); 78 ASSERT(kBufferSize >= 1 + kMaxDigitsBeforePoint + 1 + kMaxFractionDigits + 1);
65 79
66 if (d <= kLowerBoundary || d >= kUpperBoundary) { 80 ASSERT(kLowerBoundary < d && d < kUpperBoundary);
67 return false; 81
68 } 82 ASSERT(kMinFractionDigits <= fraction_digits &&
69 if (fraction_digits < kMinFractionDigits || 83 fraction_digits <= kMaxFractionDigits);
70 fraction_digits > kMaxFractionDigits) {
71 return false;
72 }
73 84
74 const double_conversion::DoubleToStringConverter converter( 85 const double_conversion::DoubleToStringConverter converter(
75 kConversionFlags, 86 kConversionFlags,
76 kDoubleToStringCommonInfinitySymbol, 87 kDoubleToStringCommonInfinitySymbol,
77 kDoubleToStringCommonNaNSymbol, 88 kDoubleToStringCommonNaNSymbol,
78 kDoubleToStringCommonExponentChar, 89 kDoubleToStringCommonExponentChar,
79 0, 0, 0, 0); // Last four values are ignored in fixed mode. 90 0, 0, 0, 0); // Last four values are ignored in fixed mode.
80 91
81 char buffer[kBufferSize]; 92 char buffer[kBufferSize];
82 double_conversion::StringBuilder builder(buffer, kBufferSize); 93 double_conversion::StringBuilder builder(buffer, kBufferSize);
83 bool status = converter.ToFixed(d, fraction_digits, &builder); 94 bool status = converter.ToFixed(d, fraction_digits, &builder);
84 if (!status) return false; 95 if (!status) return String::null();
85 int length = builder.position(); 96 int length = builder.position();
86 result ^= String::New(reinterpret_cast<uint8_t*>(builder.Finalize()), length); 97 return String::New(reinterpret_cast<uint8_t*>(builder.Finalize()), length);
87 return true;
88 } 98 }
89 99
90 100
91 bool DoubleToStringAsExponential(double d, 101 RawString* DoubleToStringAsExponential(double d, int fraction_digits) {
92 int fraction_digits, 102 static const int kMinFractionDigits = -1; // -1 represents shortest mode.
93 String& result) {
94 static const int kMinFractionDigits = 0;
95 static const int kMaxFractionDigits = 20; 103 static const int kMaxFractionDigits = 20;
96 static const int kConversionFlags = 104 static const int kConversionFlags =
97 double_conversion::DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN; 105 double_conversion::DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN;
98 const int kBufferSize = 128; 106 const int kBufferSize = 128;
107
108 USE(kMinFractionDigits);
109 USE(kMaxFractionDigits);
99 // The output contains the sign, at most 1 digits, the decimal point followed 110 // The output contains the sign, at most 1 digits, the decimal point followed
100 // by at most kMaxFractionDigits digits, the exponent-character, the 111 // by at most kMaxFractionDigits digits, the exponent-character, the
101 // exponent-sign and three exponent digits plus \0. 112 // exponent-sign and three exponent digits plus \0.
102 ASSERT(kBufferSize >= 1 + 1 + kMaxFractionDigits + 1 + 1 + 3 + 1); 113 ASSERT(kBufferSize >= 1 + 1 + kMaxFractionDigits + 1 + 1 + 3 + 1);
103 114
104 if (!(kMinFractionDigits <= fraction_digits && 115 ASSERT(kMinFractionDigits <= fraction_digits &&
105 fraction_digits <= kMaxFractionDigits)) { 116 fraction_digits <= kMaxFractionDigits);
106 return false;
107 }
108 117
109 const double_conversion::DoubleToStringConverter converter( 118 const double_conversion::DoubleToStringConverter converter(
110 kConversionFlags, 119 kConversionFlags,
111 kDoubleToStringCommonInfinitySymbol, 120 kDoubleToStringCommonInfinitySymbol,
112 kDoubleToStringCommonNaNSymbol, 121 kDoubleToStringCommonNaNSymbol,
113 kDoubleToStringCommonExponentChar, 122 kDoubleToStringCommonExponentChar,
114 0, 0, 0, 0); // Last four values are ignored in exponential mode. 123 0, 0, 0, 0); // Last four values are ignored in exponential mode.
115 124
116 UNIMPLEMENTED(); 125 char buffer[kBufferSize];
117 return false; 126 double_conversion::StringBuilder builder(buffer, kBufferSize);
127 bool status = converter.ToExponential(d, fraction_digits, &builder);
128 if (!status) return String::null();
129 int length = builder.position();
130 return String::New(reinterpret_cast<uint8_t*>(builder.Finalize()), length);
118 } 131 }
119 132
120 133
121 bool DoubleToStringAsPrecision(double d, int precision, String& result) { 134 RawString* DoubleToStringAsPrecision(double d, int precision) {
122 static const int kMinPrecisionDigits = 1; 135 static const int kMinPrecisionDigits = 1;
123 static const int kMaxPrecisionDigits = 21; 136 static const int kMaxPrecisionDigits = 21;
124 static const int kMaxLeadingPaddingZeroes = 6; 137 static const int kMaxLeadingPaddingZeroes = 6;
125 static const int kMaxTrailingPaddingZeroes = 0; 138 static const int kMaxTrailingPaddingZeroes = 0;
126 static const int kConversionFlags = 139 static const int kConversionFlags =
127 double_conversion::DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN; 140 double_conversion::DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN;
128 const int kBufferSize = 128; 141 const int kBufferSize = 128;
129 // The output contains the sign, the decimal point, precision digits, 142
143 USE(kMinPrecisionDigits);
144 USE(kMaxPrecisionDigits);
145 // The output contains the sign, a potential leading 0, the decimal point,
146 // at most kMax{Leading|Trailing} padding zeroes, precision digits,
130 // the exponent-character, the exponent-sign, three exponent digits 147 // the exponent-character, the exponent-sign, three exponent digits
131 // plus the \0. 148 // plus the \0.
132 ASSERT(kBufferSize >= 1 + 1 + kMaxPrecisionDigits + 1 + 1 + 3 + 1); 149 // Note that padding and exponent are exclusive. We still add them up.
150 ASSERT(kBufferSize >= 1 + 1 + 1 + kMaxLeadingPaddingZeroes +
151 kMaxTrailingPaddingZeroes + kMaxPrecisionDigits + 1 + 1 + 3 + 1);
133 152
134 if (!(kMinPrecisionDigits <= precision && precision <= kMaxPrecisionDigits)) { 153 ASSERT(kMinPrecisionDigits <= precision && precision <= kMaxPrecisionDigits);
135 return false;
136 }
137 154
138 const double_conversion::DoubleToStringConverter converter( 155 const double_conversion::DoubleToStringConverter converter(
139 kConversionFlags, 156 kConversionFlags,
140 kDoubleToStringCommonInfinitySymbol, 157 kDoubleToStringCommonInfinitySymbol,
141 kDoubleToStringCommonNaNSymbol, 158 kDoubleToStringCommonNaNSymbol,
142 kDoubleToStringCommonExponentChar, 159 kDoubleToStringCommonExponentChar,
143 0, 0, // Ignored in precision mode. 160 0, 0, // Ignored in precision mode.
144 kMaxLeadingPaddingZeroes, 161 kMaxLeadingPaddingZeroes,
145 kMaxTrailingPaddingZeroes); 162 kMaxTrailingPaddingZeroes);
146 163
147 UNIMPLEMENTED(); 164 char buffer[kBufferSize];
148 return false; 165 double_conversion::StringBuilder builder(buffer, kBufferSize);
166 bool status = converter.ToPrecision(d, precision, &builder);
167 if (!status) return String::null();
168 int length = builder.position();
169 return String::New(reinterpret_cast<uint8_t*>(builder.Finalize()), length);
149 } 170 }
150 171
151 } // namespace dart 172 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698