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

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: Address comment 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
« no previous file with comments | « runtime/vm/double_conversion.h ('k') | runtime/vm/object.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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,
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(kMinFractionDigits);
73 USE(kMaxFractionDigits);
62 // The output contains the sign, at most kMaxDigitsBeforePoint digits, 74 // The output contains the sign, at most kMaxDigitsBeforePoint digits,
63 // the decimal point followed by at most fraction_digits digits plus the \0. 75 // the decimal point followed by at most fraction_digits digits plus the \0.
64 ASSERT(kBufferSize >= 1 + kMaxDigitsBeforePoint + 1 + kMaxFractionDigits + 1); 76 ASSERT(kBufferSize >= 1 + kMaxDigitsBeforePoint + 1 + kMaxFractionDigits + 1);
65 77
66 if (d <= kLowerBoundary || d >= kUpperBoundary) { 78 if (d <= kLowerBoundary || d >= kUpperBoundary) {
67 return false; 79 return NULL;
Ivan Posva 2012/02/06 18:25:44 I am sorry I missed this on the first read of this
floitsch 2012/02/11 22:42:30 done. Changed this occurrence to an ASSERT.
68 } 80 }
69 if (fraction_digits < kMinFractionDigits || 81 assert(kMinFractionDigits <= fraction_digits &&
70 fraction_digits > kMaxFractionDigits) { 82 fraction_digits <= kMaxFractionDigits);
71 return false;
72 }
73 83
74 const double_conversion::DoubleToStringConverter converter( 84 const double_conversion::DoubleToStringConverter converter(
75 kConversionFlags, 85 kConversionFlags,
76 kDoubleToStringCommonInfinitySymbol, 86 kDoubleToStringCommonInfinitySymbol,
77 kDoubleToStringCommonNaNSymbol, 87 kDoubleToStringCommonNaNSymbol,
78 kDoubleToStringCommonExponentChar, 88 kDoubleToStringCommonExponentChar,
79 0, 0, 0, 0); // Last four values are ignored in fixed mode. 89 0, 0, 0, 0); // Last four values are ignored in fixed mode.
80 90
81 char buffer[kBufferSize]; 91 char buffer[kBufferSize];
82 double_conversion::StringBuilder builder(buffer, kBufferSize); 92 double_conversion::StringBuilder builder(buffer, kBufferSize);
83 bool status = converter.ToFixed(d, fraction_digits, &builder); 93 bool status = converter.ToFixed(d, fraction_digits, &builder);
84 if (!status) return false; 94 if (!status) return NULL;
floitsch 2012/02/11 22:42:30 changed to String::null(). status is supposed to a
Ivan Posva 2012/02/27 14:47:14 What will happen in production when the status is
floitsch 2012/02/27 19:55:40 The string builder only wraps the raw char-array t
85 int length = builder.position(); 95 int length = builder.position();
86 result ^= String::New(reinterpret_cast<uint8_t*>(builder.Finalize()), length); 96 return String::New(reinterpret_cast<uint8_t*>(builder.Finalize()), length);
87 return true;
88 } 97 }
89 98
90 99
91 bool DoubleToStringAsExponential(double d, 100 RawString* DoubleToStringAsExponential(double d, int fraction_digits) {
92 int fraction_digits, 101 static const int kMinFractionDigits = -1; // -1 represents shortest mode.
93 String& result) {
94 static const int kMinFractionDigits = 0;
95 static const int kMaxFractionDigits = 20; 102 static const int kMaxFractionDigits = 20;
96 static const int kConversionFlags = 103 static const int kConversionFlags =
97 double_conversion::DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN; 104 double_conversion::DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN;
98 const int kBufferSize = 128; 105 const int kBufferSize = 128;
106
107 USE(kMinFractionDigits);
108 USE(kMaxFractionDigits);
99 // The output contains the sign, at most 1 digits, the decimal point followed 109 // The output contains the sign, at most 1 digits, the decimal point followed
100 // by at most kMaxFractionDigits digits, the exponent-character, the 110 // by at most kMaxFractionDigits digits, the exponent-character, the
101 // exponent-sign and three exponent digits plus \0. 111 // exponent-sign and three exponent digits plus \0.
102 ASSERT(kBufferSize >= 1 + 1 + kMaxFractionDigits + 1 + 1 + 3 + 1); 112 ASSERT(kBufferSize >= 1 + 1 + kMaxFractionDigits + 1 + 1 + 3 + 1);
103 113
104 if (!(kMinFractionDigits <= fraction_digits && 114 assert(kMinFractionDigits <= fraction_digits &&
105 fraction_digits <= kMaxFractionDigits)) { 115 fraction_digits <= kMaxFractionDigits);
106 return false;
107 }
108 116
109 const double_conversion::DoubleToStringConverter converter( 117 const double_conversion::DoubleToStringConverter converter(
110 kConversionFlags, 118 kConversionFlags,
111 kDoubleToStringCommonInfinitySymbol, 119 kDoubleToStringCommonInfinitySymbol,
112 kDoubleToStringCommonNaNSymbol, 120 kDoubleToStringCommonNaNSymbol,
113 kDoubleToStringCommonExponentChar, 121 kDoubleToStringCommonExponentChar,
114 0, 0, 0, 0); // Last four values are ignored in exponential mode. 122 0, 0, 0, 0); // Last four values are ignored in exponential mode.
115 123
116 UNIMPLEMENTED(); 124 char buffer[kBufferSize];
117 return false; 125 double_conversion::StringBuilder builder(buffer, kBufferSize);
126 bool status = converter.ToExponential(d, fraction_digits, &builder);
127 if (!status) return NULL;
128 int length = builder.position();
129 return String::New(reinterpret_cast<uint8_t*>(builder.Finalize()), length);
118 } 130 }
119 131
120 132
121 bool DoubleToStringAsPrecision(double d, int precision, String& result) { 133 RawString* DoubleToStringAsPrecision(double d, int precision) {
122 static const int kMinPrecisionDigits = 1; 134 static const int kMinPrecisionDigits = 1;
123 static const int kMaxPrecisionDigits = 21; 135 static const int kMaxPrecisionDigits = 21;
124 static const int kMaxLeadingPaddingZeroes = 6; 136 static const int kMaxLeadingPaddingZeroes = 6;
125 static const int kMaxTrailingPaddingZeroes = 0; 137 static const int kMaxTrailingPaddingZeroes = 0;
126 static const int kConversionFlags = 138 static const int kConversionFlags =
127 double_conversion::DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN; 139 double_conversion::DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN;
128 const int kBufferSize = 128; 140 const int kBufferSize = 128;
141
142 USE(kMinPrecisionDigits);
143 USE(kMaxPrecisionDigits);
129 // The output contains the sign, the decimal point, precision digits, 144 // The output contains the sign, the decimal point, precision digits,
130 // the exponent-character, the exponent-sign, three exponent digits 145 // the exponent-character, the exponent-sign, three exponent digits
131 // plus the \0. 146 // plus the \0.
132 ASSERT(kBufferSize >= 1 + 1 + kMaxPrecisionDigits + 1 + 1 + 3 + 1); 147 ASSERT(kBufferSize >= 1 + 1 + kMaxPrecisionDigits + 1 + 1 + 3 + 1);
133 148
134 if (!(kMinPrecisionDigits <= precision && precision <= kMaxPrecisionDigits)) { 149 assert(kMinPrecisionDigits <= precision && precision <= kMaxPrecisionDigits);
135 return false;
136 }
137 150
138 const double_conversion::DoubleToStringConverter converter( 151 const double_conversion::DoubleToStringConverter converter(
139 kConversionFlags, 152 kConversionFlags,
140 kDoubleToStringCommonInfinitySymbol, 153 kDoubleToStringCommonInfinitySymbol,
141 kDoubleToStringCommonNaNSymbol, 154 kDoubleToStringCommonNaNSymbol,
142 kDoubleToStringCommonExponentChar, 155 kDoubleToStringCommonExponentChar,
143 0, 0, // Ignored in precision mode. 156 0, 0, // Ignored in precision mode.
144 kMaxLeadingPaddingZeroes, 157 kMaxLeadingPaddingZeroes,
145 kMaxTrailingPaddingZeroes); 158 kMaxTrailingPaddingZeroes);
146 159
147 UNIMPLEMENTED(); 160 char buffer[kBufferSize];
148 return false; 161 double_conversion::StringBuilder builder(buffer, kBufferSize);
162 bool status = converter.ToPrecision(d, precision, &builder);
163 if (!status) return NULL;
164 int length = builder.position();
165 return String::New(reinterpret_cast<uint8_t*>(builder.Finalize()), length);
149 } 166 }
150 167
151 } // namespace dart 168 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/double_conversion.h ('k') | runtime/vm/object.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698