OLD | NEW |
---|---|
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 |
OLD | NEW |