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

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: Updated status files. Created 8 years, 9 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 void DoubleToCString(double d, char* buffer, int buffer_size) {
20 static const int kDecimalLow = -6; 20 static const int kDecimalLow = -6;
21 static const int kDecimalHigh = 21; 21 static const int kDecimalHigh = 21;
22
23 // The output contains the sign, at most kDecimalHigh - 1 digits,
24 // the decimal point followed by a 0 plus the \0.
25 ASSERT(buffer_size >= 1 + (kDecimalHigh - 1) + 1 + 1 + 1);
26 // Or it contains the sign, a 0, the decimal point, kDecimalLow '0's,
27 // 17 digits (the precision needed for doubles), plus the \0.
28 ASSERT(buffer_size >= 1 + 1 + 1 + kDecimalLow + 17 + 1);
29 // Alternatively it contains a sign, at most 17 digits (precision needed for
30 // any double), the decimal point, the exponent character, the exponent's
31 // sign, at most three exponent digits, plus the \0.
32 ASSERT(buffer_size >= 1 + 17 + 1 + 1 + 1 + 3 + 1);
33
22 static const int kConversionFlags = 34 static const int kConversionFlags =
23 double_conversion::DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN | 35 double_conversion::DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN |
24 double_conversion::DoubleToStringConverter::EMIT_TRAILING_DECIMAL_POINT | 36 double_conversion::DoubleToStringConverter::EMIT_TRAILING_DECIMAL_POINT |
25 double_conversion::DoubleToStringConverter::EMIT_TRAILING_ZERO_AFTER_POINT; 37 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 38
38 const double_conversion::DoubleToStringConverter converter( 39 const double_conversion::DoubleToStringConverter converter(
39 kConversionFlags, 40 kConversionFlags,
40 kDoubleToStringCommonInfinitySymbol, 41 kDoubleToStringCommonInfinitySymbol,
41 kDoubleToStringCommonNaNSymbol, 42 kDoubleToStringCommonNaNSymbol,
42 kDoubleToStringCommonExponentChar, 43 kDoubleToStringCommonExponentChar,
43 kDecimalLow, 44 kDecimalLow,
44 kDecimalHigh, 45 kDecimalHigh,
45 0, 0); // Last two values are ignored in shortest mode. 46 0, 0); // Last two values are ignored in shortest mode.
46 47
47 UNIMPLEMENTED(); 48 double_conversion::StringBuilder builder(buffer, buffer_size);
48 return false; 49 bool status = converter.ToShortest(d, &builder);
50 ASSERT(status);
51 char* result = builder.Finalize();
52 ASSERT(result == buffer);
49 } 53 }
50 54
51 bool DoubleToStringAsFixed(double d, int fraction_digits, String& result) { 55 RawString* DoubleToStringAsFixed(double d, int fraction_digits) {
52 static const int kMinFractionDigits = 0; 56 static const int kMinFractionDigits = 0;
53 static const int kMaxFractionDigits = 20; 57 static const int kMaxFractionDigits = 20;
54 static const int kMaxDigitsBeforePoint = 20; 58 static const int kMaxDigitsBeforePoint = 20;
55 // The boundaries are exclusive. 59 // The boundaries are exclusive.
56 static const double kLowerBoundary = -1e21; 60 static const double kLowerBoundary = -1e21;
57 static const double kUpperBoundary = 1e21; 61 static const double kUpperBoundary = 1e21;
58 // TODO(floitsch): remove the UNIQUE_ZERO flag when the test is updated. 62 // TODO(floitsch): remove the UNIQUE_ZERO flag when the test is updated.
59 static const int kConversionFlags = 63 static const int kConversionFlags =
60 double_conversion::DoubleToStringConverter::UNIQUE_ZERO; 64 double_conversion::DoubleToStringConverter::NO_FLAGS;
61 const int kBufferSize = 128; 65 const int kBufferSize = 128;
66
67 USE(kMaxDigitsBeforePoint);
68 USE(kMaxFractionDigits);
69 USE(kLowerBoundary);
70 USE(kUpperBoundary);
71 USE(kMinFractionDigits);
72 USE(kMaxFractionDigits);
62 // The output contains the sign, at most kMaxDigitsBeforePoint digits, 73 // The output contains the sign, at most kMaxDigitsBeforePoint digits,
63 // the decimal point followed by at most fraction_digits digits plus the \0. 74 // the decimal point followed by at most fraction_digits digits plus the \0.
64 ASSERT(kBufferSize >= 1 + kMaxDigitsBeforePoint + 1 + kMaxFractionDigits + 1); 75 ASSERT(kBufferSize >= 1 + kMaxDigitsBeforePoint + 1 + kMaxFractionDigits + 1);
65 76
66 if (d <= kLowerBoundary || d >= kUpperBoundary) { 77 ASSERT(kLowerBoundary < d && d < kUpperBoundary);
67 return false; 78
68 } 79 ASSERT(kMinFractionDigits <= fraction_digits &&
69 if (fraction_digits < kMinFractionDigits || 80 fraction_digits <= kMaxFractionDigits);
70 fraction_digits > kMaxFractionDigits) {
71 return false;
72 }
73 81
74 const double_conversion::DoubleToStringConverter converter( 82 const double_conversion::DoubleToStringConverter converter(
75 kConversionFlags, 83 kConversionFlags,
76 kDoubleToStringCommonInfinitySymbol, 84 kDoubleToStringCommonInfinitySymbol,
77 kDoubleToStringCommonNaNSymbol, 85 kDoubleToStringCommonNaNSymbol,
78 kDoubleToStringCommonExponentChar, 86 kDoubleToStringCommonExponentChar,
79 0, 0, 0, 0); // Last four values are ignored in fixed mode. 87 0, 0, 0, 0); // Last four values are ignored in fixed mode.
80 88
81 char buffer[kBufferSize]; 89 char* buffer = reinterpret_cast<char*>(
90 Isolate::Current()->current_zone()->Allocate(kBufferSize));
91 buffer[kBufferSize - 1] = '\0';
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 ASSERT(status);
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 = reinterpret_cast<char*>(
117 return false; 125 Isolate::Current()->current_zone()->Allocate(kBufferSize));
126 buffer[kBufferSize - 1] = '\0';
127 double_conversion::StringBuilder builder(buffer, kBufferSize);
128 bool status = converter.ToExponential(d, fraction_digits, &builder);
129 ASSERT(status);
130 int length = builder.position();
131 return String::New(reinterpret_cast<uint8_t*>(builder.Finalize()), length);
118 } 132 }
119 133
120 134
121 bool DoubleToStringAsPrecision(double d, int precision, String& result) { 135 RawString* DoubleToStringAsPrecision(double d, int precision) {
122 static const int kMinPrecisionDigits = 1; 136 static const int kMinPrecisionDigits = 1;
123 static const int kMaxPrecisionDigits = 21; 137 static const int kMaxPrecisionDigits = 21;
124 static const int kMaxLeadingPaddingZeroes = 6; 138 static const int kMaxLeadingPaddingZeroes = 6;
125 static const int kMaxTrailingPaddingZeroes = 0; 139 static const int kMaxTrailingPaddingZeroes = 0;
126 static const int kConversionFlags = 140 static const int kConversionFlags =
127 double_conversion::DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN; 141 double_conversion::DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN;
128 const int kBufferSize = 128; 142 const int kBufferSize = 128;
129 // The output contains the sign, the decimal point, precision digits, 143
144 USE(kMinPrecisionDigits);
145 USE(kMaxPrecisionDigits);
146 // The output contains the sign, a potential leading 0, the decimal point,
147 // at most kMax{Leading|Trailing} padding zeroes, precision digits,
130 // the exponent-character, the exponent-sign, three exponent digits 148 // the exponent-character, the exponent-sign, three exponent digits
131 // plus the \0. 149 // plus the \0.
132 ASSERT(kBufferSize >= 1 + 1 + kMaxPrecisionDigits + 1 + 1 + 3 + 1); 150 // Note that padding and exponent are exclusive. We still add them up.
151 ASSERT(kBufferSize >= 1 + 1 + 1 + kMaxLeadingPaddingZeroes +
152 kMaxTrailingPaddingZeroes + kMaxPrecisionDigits + 1 + 1 + 3 + 1);
133 153
134 if (!(kMinPrecisionDigits <= precision && precision <= kMaxPrecisionDigits)) { 154 ASSERT(kMinPrecisionDigits <= precision && precision <= kMaxPrecisionDigits);
135 return false;
136 }
137 155
138 const double_conversion::DoubleToStringConverter converter( 156 const double_conversion::DoubleToStringConverter converter(
139 kConversionFlags, 157 kConversionFlags,
140 kDoubleToStringCommonInfinitySymbol, 158 kDoubleToStringCommonInfinitySymbol,
141 kDoubleToStringCommonNaNSymbol, 159 kDoubleToStringCommonNaNSymbol,
142 kDoubleToStringCommonExponentChar, 160 kDoubleToStringCommonExponentChar,
143 0, 0, // Ignored in precision mode. 161 0, 0, // Ignored in precision mode.
144 kMaxLeadingPaddingZeroes, 162 kMaxLeadingPaddingZeroes,
145 kMaxTrailingPaddingZeroes); 163 kMaxTrailingPaddingZeroes);
146 164
147 UNIMPLEMENTED(); 165 char* buffer = reinterpret_cast<char*>(
148 return false; 166 Isolate::Current()->current_zone()->Allocate(kBufferSize));
167 buffer[kBufferSize - 1] = '\0';
168 double_conversion::StringBuilder builder(buffer, kBufferSize);
169 bool status = converter.ToPrecision(d, precision, &builder);
170 ASSERT(status);
171 int length = builder.position();
172 return String::New(reinterpret_cast<uint8_t*>(builder.Finalize()), length);
149 } 173 }
150 174
151 } // namespace dart 175 } // 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