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, |
| 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; |
| 56 } |
| 57 |
| 58 bool DoubleToString(double d, String& result) { |
| 59 const int kBufferSize = 128; |
| 60 char buffer[kBufferSize]; |
| 61 int length; |
| 62 bool status = DoubleToCString(d, buffer, kBufferSize, &length); |
| 63 if (!status) return false; |
| 64 result ^= String::New(reinterpret_cast<uint8_t*>(buffer), length); |
| 65 return true; |
49 } | 66 } |
50 | 67 |
51 bool DoubleToStringAsFixed(double d, int fraction_digits, String& result) { | 68 bool DoubleToStringAsFixed(double d, int fraction_digits, String& result) { |
52 static const int kMinFractionDigits = 0; | 69 static const int kMinFractionDigits = 0; |
53 static const int kMaxFractionDigits = 20; | 70 static const int kMaxFractionDigits = 20; |
54 static const int kMaxDigitsBeforePoint = 20; | 71 static const int kMaxDigitsBeforePoint = 20; |
55 // The boundaries are exclusive. | 72 // The boundaries are exclusive. |
56 static const double kLowerBoundary = -1e21; | 73 static const double kLowerBoundary = -1e21; |
57 static const double kUpperBoundary = 1e21; | 74 static const double kUpperBoundary = 1e21; |
58 // TODO(floitsch): remove the UNIQUE_ZERO flag when the test is updated. | 75 // TODO(floitsch): remove the UNIQUE_ZERO flag when the test is updated. |
59 static const int kConversionFlags = | 76 static const int kConversionFlags = |
60 double_conversion::DoubleToStringConverter::UNIQUE_ZERO; | 77 double_conversion::DoubleToStringConverter::NO_FLAGS; |
61 const int kBufferSize = 128; | 78 const int kBufferSize = 128; |
62 // The output contains the sign, at most kMaxDigitsBeforePoint digits, | 79 // The output contains the sign, at most kMaxDigitsBeforePoint digits, |
63 // the decimal point followed by at most fraction_digits digits plus the \0. | 80 // the decimal point followed by at most fraction_digits digits plus the \0. |
64 ASSERT(kBufferSize >= 1 + kMaxDigitsBeforePoint + 1 + kMaxFractionDigits + 1); | 81 ASSERT(kBufferSize >= 1 + kMaxDigitsBeforePoint + 1 + kMaxFractionDigits + 1); |
65 | 82 |
66 if (d <= kLowerBoundary || d >= kUpperBoundary) { | 83 if (d <= kLowerBoundary || d >= kUpperBoundary) { |
67 return false; | 84 return false; |
68 } | 85 } |
69 if (fraction_digits < kMinFractionDigits || | 86 if (fraction_digits < kMinFractionDigits || |
70 fraction_digits > kMaxFractionDigits) { | 87 fraction_digits > kMaxFractionDigits) { |
(...skipping 13 matching lines...) Expand all Loading... |
84 if (!status) return false; | 101 if (!status) return false; |
85 int length = builder.position(); | 102 int length = builder.position(); |
86 result ^= String::New(reinterpret_cast<uint8_t*>(builder.Finalize()), length); | 103 result ^= String::New(reinterpret_cast<uint8_t*>(builder.Finalize()), length); |
87 return true; | 104 return true; |
88 } | 105 } |
89 | 106 |
90 | 107 |
91 bool DoubleToStringAsExponential(double d, | 108 bool DoubleToStringAsExponential(double d, |
92 int fraction_digits, | 109 int fraction_digits, |
93 String& result) { | 110 String& result) { |
94 static const int kMinFractionDigits = 0; | 111 static const int kMinFractionDigits = -1; // -1 represents shortest mode. |
95 static const int kMaxFractionDigits = 20; | 112 static const int kMaxFractionDigits = 20; |
96 static const int kConversionFlags = | 113 static const int kConversionFlags = |
97 double_conversion::DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN; | 114 double_conversion::DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN; |
98 const int kBufferSize = 128; | 115 const int kBufferSize = 128; |
99 // The output contains the sign, at most 1 digits, the decimal point followed | 116 // The output contains the sign, at most 1 digits, the decimal point followed |
100 // by at most kMaxFractionDigits digits, the exponent-character, the | 117 // by at most kMaxFractionDigits digits, the exponent-character, the |
101 // exponent-sign and three exponent digits plus \0. | 118 // exponent-sign and three exponent digits plus \0. |
102 ASSERT(kBufferSize >= 1 + 1 + kMaxFractionDigits + 1 + 1 + 3 + 1); | 119 ASSERT(kBufferSize >= 1 + 1 + kMaxFractionDigits + 1 + 1 + 3 + 1); |
103 | 120 |
104 if (!(kMinFractionDigits <= fraction_digits && | 121 if (fraction_digits < kMinFractionDigits || |
105 fraction_digits <= kMaxFractionDigits)) { | 122 fraction_digits > kMaxFractionDigits) { |
106 return false; | 123 return false; |
107 } | 124 } |
108 | 125 |
109 const double_conversion::DoubleToStringConverter converter( | 126 const double_conversion::DoubleToStringConverter converter( |
110 kConversionFlags, | 127 kConversionFlags, |
111 kDoubleToStringCommonInfinitySymbol, | 128 kDoubleToStringCommonInfinitySymbol, |
112 kDoubleToStringCommonNaNSymbol, | 129 kDoubleToStringCommonNaNSymbol, |
113 kDoubleToStringCommonExponentChar, | 130 kDoubleToStringCommonExponentChar, |
114 0, 0, 0, 0); // Last four values are ignored in exponential mode. | 131 0, 0, 0, 0); // Last four values are ignored in exponential mode. |
115 | 132 |
116 UNIMPLEMENTED(); | 133 char buffer[kBufferSize]; |
117 return false; | 134 double_conversion::StringBuilder builder(buffer, kBufferSize); |
| 135 bool status = converter.ToExponential(d, fraction_digits, &builder); |
| 136 if (!status) return false; |
| 137 int length = builder.position(); |
| 138 result ^= String::New(reinterpret_cast<uint8_t*>(builder.Finalize()), length); |
| 139 return true; |
118 } | 140 } |
119 | 141 |
120 | 142 |
121 bool DoubleToStringAsPrecision(double d, int precision, String& result) { | 143 bool DoubleToStringAsPrecision(double d, int precision, String& result) { |
122 static const int kMinPrecisionDigits = 1; | 144 static const int kMinPrecisionDigits = 1; |
123 static const int kMaxPrecisionDigits = 21; | 145 static const int kMaxPrecisionDigits = 21; |
124 static const int kMaxLeadingPaddingZeroes = 6; | 146 static const int kMaxLeadingPaddingZeroes = 6; |
125 static const int kMaxTrailingPaddingZeroes = 0; | 147 static const int kMaxTrailingPaddingZeroes = 0; |
126 static const int kConversionFlags = | 148 static const int kConversionFlags = |
127 double_conversion::DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN; | 149 double_conversion::DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN; |
128 const int kBufferSize = 128; | 150 const int kBufferSize = 128; |
129 // The output contains the sign, the decimal point, precision digits, | 151 // The output contains the sign, the decimal point, precision digits, |
130 // the exponent-character, the exponent-sign, three exponent digits | 152 // the exponent-character, the exponent-sign, three exponent digits |
131 // plus the \0. | 153 // plus the \0. |
132 ASSERT(kBufferSize >= 1 + 1 + kMaxPrecisionDigits + 1 + 1 + 3 + 1); | 154 ASSERT(kBufferSize >= 1 + 1 + kMaxPrecisionDigits + 1 + 1 + 3 + 1); |
133 | 155 |
134 if (!(kMinPrecisionDigits <= precision && precision <= kMaxPrecisionDigits)) { | 156 if (!(kMinPrecisionDigits <= precision && precision <= kMaxPrecisionDigits)) { |
135 return false; | 157 return false; |
136 } | 158 } |
137 | 159 |
138 const double_conversion::DoubleToStringConverter converter( | 160 const double_conversion::DoubleToStringConverter converter( |
139 kConversionFlags, | 161 kConversionFlags, |
140 kDoubleToStringCommonInfinitySymbol, | 162 kDoubleToStringCommonInfinitySymbol, |
141 kDoubleToStringCommonNaNSymbol, | 163 kDoubleToStringCommonNaNSymbol, |
142 kDoubleToStringCommonExponentChar, | 164 kDoubleToStringCommonExponentChar, |
143 0, 0, // Ignored in precision mode. | 165 0, 0, // Ignored in precision mode. |
144 kMaxLeadingPaddingZeroes, | 166 kMaxLeadingPaddingZeroes, |
145 kMaxTrailingPaddingZeroes); | 167 kMaxTrailingPaddingZeroes); |
146 | 168 |
147 UNIMPLEMENTED(); | 169 char buffer[kBufferSize]; |
148 return false; | 170 double_conversion::StringBuilder builder(buffer, kBufferSize); |
| 171 bool status = converter.ToPrecision(d, precision, &builder); |
| 172 if (!status) return false; |
| 173 int length = builder.position(); |
| 174 result ^= String::New(reinterpret_cast<uint8_t*>(builder.Finalize()), length); |
| 175 return true; |
149 } | 176 } |
150 | 177 |
151 } // namespace dart | 178 } // namespace dart |
OLD | NEW |