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

Side by Side Diff: third_party/WebKit/Source/wtf/dtoa/double-conversion.cc

Issue 2700123003: DO NOT COMMIT: Results of running old (current) clang-format on Blink (Closed)
Patch Set: Created 3 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
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution. 11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its 12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived 13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission. 14 // from this software without specific prior written permission.
15 // 15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "double-conversion.h" 28 #include "double-conversion.h"
29 29
30 #include <limits.h>
31 #include <math.h>
30 #include "bignum-dtoa.h" 32 #include "bignum-dtoa.h"
31 #include "double.h" 33 #include "double.h"
32 #include "fast-dtoa.h" 34 #include "fast-dtoa.h"
33 #include "fixed-dtoa.h" 35 #include "fixed-dtoa.h"
34 #include "strtod.h" 36 #include "strtod.h"
35 #include "utils.h" 37 #include "utils.h"
36 #include <limits.h>
37 #include <math.h>
38 38
39 namespace WTF { 39 namespace WTF {
40 40
41 namespace double_conversion { 41 namespace double_conversion {
42 42
43 const DoubleToStringConverter& DoubleToStringConverter::EcmaScriptConverter( ) { 43 const DoubleToStringConverter& DoubleToStringConverter::EcmaScriptConverter() {
44 int flags = UNIQUE_ZERO | EMIT_POSITIVE_EXPONENT_SIGN; 44 int flags = UNIQUE_ZERO | EMIT_POSITIVE_EXPONENT_SIGN;
45 static DoubleToStringConverter converter(flags, 45 static DoubleToStringConverter converter(flags, "Infinity", "NaN", 'e', -6,
46 "Infinity", 46 21, 6, 0);
47 "NaN", 47 return converter;
48 'e', 48 }
49 -6, 21, 49
50 6, 0); 50 bool DoubleToStringConverter::HandleSpecialValues(
51 return converter; 51 double value,
52 } 52 StringBuilder* result_builder) const {
53 53 Double double_inspect(value);
54 54 if (double_inspect.IsInfinite()) {
55 bool DoubleToStringConverter::HandleSpecialValues( 55 if (infinity_symbol_ == NULL)
56 double value, 56 return false;
57 StringBuilder* result_buil der) const { 57 if (value < 0) {
58 Double double_inspect(value); 58 result_builder->AddCharacter('-');
59 if (double_inspect.IsInfinite()) { 59 }
60 if (infinity_symbol_ == NULL) return false; 60 result_builder->AddString(infinity_symbol_);
61 if (value < 0) { 61 return true;
62 result_builder->AddCharacter('-'); 62 }
63 } 63 if (double_inspect.IsNan()) {
64 result_builder->AddString(infinity_symbol_); 64 if (nan_symbol_ == NULL)
65 return true; 65 return false;
66 result_builder->AddString(nan_symbol_);
67 return true;
68 }
69 return false;
70 }
71
72 void DoubleToStringConverter::CreateExponentialRepresentation(
73 const char* decimal_digits,
74 int length,
75 int exponent,
76 StringBuilder* result_builder) const {
77 ASSERT(length != 0);
78 result_builder->AddCharacter(decimal_digits[0]);
79 if (length != 1) {
80 result_builder->AddCharacter('.');
81 result_builder->AddSubstring(&decimal_digits[1], length - 1);
82 }
83 result_builder->AddCharacter(exponent_character_);
84 if (exponent < 0) {
85 result_builder->AddCharacter('-');
86 exponent = -exponent;
87 } else {
88 if ((flags_ & EMIT_POSITIVE_EXPONENT_SIGN) != 0) {
89 result_builder->AddCharacter('+');
90 }
91 }
92 if (exponent == 0) {
93 result_builder->AddCharacter('0');
94 return;
95 }
96 ASSERT(exponent < 1e4);
97 const int kMaxExponentLength = 5;
98 char buffer[kMaxExponentLength + 1];
99 int first_char_pos = kMaxExponentLength;
100 buffer[first_char_pos] = '\0';
101 while (exponent > 0) {
102 buffer[--first_char_pos] = '0' + (exponent % 10);
103 exponent /= 10;
104 }
105 result_builder->AddSubstring(&buffer[first_char_pos],
106 kMaxExponentLength - first_char_pos);
107 }
108
109 void DoubleToStringConverter::CreateDecimalRepresentation(
110 const char* decimal_digits,
111 int length,
112 int decimal_point,
113 int digits_after_point,
114 StringBuilder* result_builder) const {
115 // Create a representation that is padded with zeros if needed.
116 if (decimal_point <= 0) {
117 // "0.00000decimal_rep".
118 result_builder->AddCharacter('0');
119 if (digits_after_point > 0) {
120 result_builder->AddCharacter('.');
121 result_builder->AddPadding('0', -decimal_point);
122 ASSERT(length <= digits_after_point - (-decimal_point));
123 result_builder->AddSubstring(decimal_digits, length);
124 int remaining_digits = digits_after_point - (-decimal_point) - length;
125 result_builder->AddPadding('0', remaining_digits);
126 }
127 } else if (decimal_point >= length) {
128 // "decimal_rep0000.00000" or "decimal_rep.0000"
129 result_builder->AddSubstring(decimal_digits, length);
130 result_builder->AddPadding('0', decimal_point - length);
131 if (digits_after_point > 0) {
132 result_builder->AddCharacter('.');
133 result_builder->AddPadding('0', digits_after_point);
134 }
135 } else {
136 // "decima.l_rep000"
137 ASSERT(digits_after_point > 0);
138 result_builder->AddSubstring(decimal_digits, decimal_point);
139 result_builder->AddCharacter('.');
140 ASSERT(length - decimal_point <= digits_after_point);
141 result_builder->AddSubstring(&decimal_digits[decimal_point],
142 length - decimal_point);
143 int remaining_digits = digits_after_point - (length - decimal_point);
144 result_builder->AddPadding('0', remaining_digits);
145 }
146 if (digits_after_point == 0) {
147 if ((flags_ & EMIT_TRAILING_DECIMAL_POINT) != 0) {
148 result_builder->AddCharacter('.');
149 }
150 if ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) {
151 result_builder->AddCharacter('0');
152 }
153 }
154 }
155
156 bool DoubleToStringConverter::ToShortest(double value,
157 StringBuilder* result_builder) const {
158 if (Double(value).IsSpecial()) {
159 return HandleSpecialValues(value, result_builder);
160 }
161
162 int decimal_point;
163 bool sign;
164 const int kDecimalRepCapacity = kBase10MaximalLength + 1;
165 char decimal_rep[kDecimalRepCapacity];
166 int decimal_rep_length;
167
168 DoubleToAscii(value, SHORTEST, 0, decimal_rep, kDecimalRepCapacity, &sign,
169 &decimal_rep_length, &decimal_point);
170
171 bool unique_zero = (flags_ & UNIQUE_ZERO) != 0;
172 if (sign && (value != 0.0 || !unique_zero)) {
173 result_builder->AddCharacter('-');
174 }
175
176 int exponent = decimal_point - 1;
177 if ((decimal_in_shortest_low_ <= exponent) &&
178 (exponent < decimal_in_shortest_high_)) {
179 CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
180 Max(0, decimal_rep_length - decimal_point),
181 result_builder);
182 } else {
183 CreateExponentialRepresentation(decimal_rep, decimal_rep_length, exponent,
184 result_builder);
185 }
186 return true;
187 }
188
189 bool DoubleToStringConverter::ToFixed(double value,
190 int requested_digits,
191 StringBuilder* result_builder) const {
192 ASSERT(kMaxFixedDigitsBeforePoint == 60);
193 const double kFirstNonFixed = 1e60;
194
195 if (Double(value).IsSpecial()) {
196 return HandleSpecialValues(value, result_builder);
197 }
198
199 if (requested_digits > kMaxFixedDigitsAfterPoint)
200 return false;
201 if (value >= kFirstNonFixed || value <= -kFirstNonFixed)
202 return false;
203
204 // Find a sufficiently precise decimal representation of n.
205 int decimal_point;
206 bool sign;
207 // Add space for the '\0' byte.
208 const int kDecimalRepCapacity =
209 kMaxFixedDigitsBeforePoint + kMaxFixedDigitsAfterPoint + 1;
210 char decimal_rep[kDecimalRepCapacity];
211 int decimal_rep_length;
212 DoubleToAscii(value, FIXED, requested_digits, decimal_rep,
213 kDecimalRepCapacity, &sign, &decimal_rep_length,
214 &decimal_point);
215
216 bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
217 if (sign && (value != 0.0 || !unique_zero)) {
218 result_builder->AddCharacter('-');
219 }
220
221 CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
222 requested_digits, result_builder);
223 return true;
224 }
225
226 bool DoubleToStringConverter::ToExponential(
227 double value,
228 int requested_digits,
229 StringBuilder* result_builder) const {
230 if (Double(value).IsSpecial()) {
231 return HandleSpecialValues(value, result_builder);
232 }
233
234 if (requested_digits < -1)
235 return false;
236 if (requested_digits > kMaxExponentialDigits)
237 return false;
238
239 int decimal_point;
240 bool sign;
241 // Add space for digit before the decimal point and the '\0' character.
242 const int kDecimalRepCapacity = kMaxExponentialDigits + 2;
243 ASSERT(kDecimalRepCapacity > kBase10MaximalLength);
244 char decimal_rep[kDecimalRepCapacity];
245 int decimal_rep_length;
246
247 if (requested_digits == -1) {
248 DoubleToAscii(value, SHORTEST, 0, decimal_rep, kDecimalRepCapacity, &sign,
249 &decimal_rep_length, &decimal_point);
250 } else {
251 DoubleToAscii(value, PRECISION, requested_digits + 1, decimal_rep,
252 kDecimalRepCapacity, &sign, &decimal_rep_length,
253 &decimal_point);
254 ASSERT(decimal_rep_length <= requested_digits + 1);
255
256 for (int i = decimal_rep_length; i < requested_digits + 1; ++i) {
257 decimal_rep[i] = '0';
258 }
259 decimal_rep_length = requested_digits + 1;
260 }
261
262 bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
263 if (sign && (value != 0.0 || !unique_zero)) {
264 result_builder->AddCharacter('-');
265 }
266
267 int exponent = decimal_point - 1;
268 CreateExponentialRepresentation(decimal_rep, decimal_rep_length, exponent,
269 result_builder);
270 return true;
271 }
272
273 bool DoubleToStringConverter::ToPrecision(double value,
274 int precision,
275 StringBuilder* result_builder) const {
276 if (Double(value).IsSpecial()) {
277 return HandleSpecialValues(value, result_builder);
278 }
279
280 if (precision < kMinPrecisionDigits || precision > kMaxPrecisionDigits) {
281 return false;
282 }
283
284 // Find a sufficiently precise decimal representation of n.
285 int decimal_point;
286 bool sign;
287 // Add one for the terminating null character.
288 const int kDecimalRepCapacity = kMaxPrecisionDigits + 1;
289 char decimal_rep[kDecimalRepCapacity];
290 int decimal_rep_length;
291
292 DoubleToAscii(value, PRECISION, precision, decimal_rep, kDecimalRepCapacity,
293 &sign, &decimal_rep_length, &decimal_point);
294 ASSERT(decimal_rep_length <= precision);
295
296 bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
297 if (sign && (value != 0.0 || !unique_zero)) {
298 result_builder->AddCharacter('-');
299 }
300
301 // The exponent if we print the number as x.xxeyyy. That is with the
302 // decimal point after the first digit.
303 int exponent = decimal_point - 1;
304
305 int extra_zero = ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) ? 1 : 0;
306 if ((-decimal_point + 1 > max_leading_padding_zeroes_in_precision_mode_) ||
307 (decimal_point - precision + extra_zero >
308 max_trailing_padding_zeroes_in_precision_mode_)) {
309 // Fill buffer to contain 'precision' digits.
310 // Usually the buffer is already at the correct length, but 'DoubleToAscii'
311 // is allowed to return less characters.
312 for (int i = decimal_rep_length; i < precision; ++i) {
313 decimal_rep[i] = '0';
314 }
315
316 CreateExponentialRepresentation(decimal_rep, precision, exponent,
317 result_builder);
318 } else {
319 CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
320 Max(0, precision - decimal_point),
321 result_builder);
322 }
323 return true;
324 }
325
326 static BignumDtoaMode DtoaToBignumDtoaMode(
327 DoubleToStringConverter::DtoaMode dtoa_mode) {
328 switch (dtoa_mode) {
329 case DoubleToStringConverter::SHORTEST:
330 return BIGNUM_DTOA_SHORTEST;
331 case DoubleToStringConverter::FIXED:
332 return BIGNUM_DTOA_FIXED;
333 case DoubleToStringConverter::PRECISION:
334 return BIGNUM_DTOA_PRECISION;
335 default:
336 UNREACHABLE();
337 return BIGNUM_DTOA_SHORTEST; // To silence compiler.
338 }
339 }
340
341 void DoubleToStringConverter::DoubleToAscii(double v,
342 DtoaMode mode,
343 int requested_digits,
344 char* buffer,
345 int buffer_length,
346 bool* sign,
347 int* length,
348 int* point) {
349 Vector<char> vector(buffer, buffer_length);
350 ASSERT(!Double(v).IsSpecial());
351 ASSERT(mode == SHORTEST || requested_digits >= 0);
352
353 if (Double(v).Sign() < 0) {
354 *sign = true;
355 v = -v;
356 } else {
357 *sign = false;
358 }
359
360 if (mode == PRECISION && requested_digits == 0) {
361 vector[0] = '\0';
362 *length = 0;
363 return;
364 }
365
366 if (v == 0) {
367 vector[0] = '0';
368 vector[1] = '\0';
369 *length = 1;
370 *point = 1;
371 return;
372 }
373
374 bool fast_worked;
375 switch (mode) {
376 case SHORTEST:
377 fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST, 0, vector, length, point);
378 break;
379 case FIXED:
380 fast_worked = FastFixedDtoa(v, requested_digits, vector, length, point);
381 break;
382 case PRECISION:
383 fast_worked = FastDtoa(v, FAST_DTOA_PRECISION, requested_digits, vector,
384 length, point);
385 break;
386 default:
387 UNREACHABLE();
388 fast_worked = false;
389 }
390 if (fast_worked)
391 return;
392
393 // If the fast dtoa didn't succeed use the slower bignum version.
394 BignumDtoaMode bignum_mode = DtoaToBignumDtoaMode(mode);
395 BignumDtoa(v, bignum_mode, requested_digits, vector, length, point);
396 vector[*length] = '\0';
397 }
398
399 // Maximum number of significant digits in decimal representation.
400 // The longest possible double in decimal representation is
401 // (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074
402 // (768 digits). If we parse a number whose first digits are equal to a
403 // mean of 2 adjacent doubles (that could have up to 769 digits) the result
404 // must be rounded to the bigger one unless the tail consists of zeros, so
405 // we don't need to preserve all the digits.
406 const int kMaxSignificantDigits = 772;
407
408 static double SignedZero(bool sign) {
409 return sign ? -0.0 : 0.0;
410 }
411
412 double StringToDoubleConverter::StringToDouble(
413 const char* input,
414 size_t length,
415 size_t* processed_characters_count) {
416 const char* current = input;
417 const char* end = input + length;
418
419 *processed_characters_count = 0;
420
421 // To make sure that iterator dereferencing is valid the following
422 // convention is used:
423 // 1. Each '++current' statement is followed by check for equality to 'end'.
424 // 3. If 'current' becomes equal to 'end' the function returns or goes to
425 // 'parsing_done'.
426 // 4. 'current' is not dereferenced after the 'parsing_done' label.
427 // 5. Code before 'parsing_done' may rely on 'current != end'.
428 if (current == end)
429 return 0.0;
430
431 // The longest form of simplified number is: "-<significant digits>.1eXXX\0".
432 const int kBufferSize = kMaxSignificantDigits + 10;
433 char buffer[kBufferSize]; // NOLINT: size is known at compile time.
434 int buffer_pos = 0;
435
436 // Exponent will be adjusted if insignificant digits of the integer part
437 // or insignificant leading zeros of the fractional part are dropped.
438 int exponent = 0;
439 int significant_digits = 0;
440 int insignificant_digits = 0;
441 bool nonzero_digit_dropped = false;
442 bool sign = false;
443
444 if (*current == '+' || *current == '-') {
445 sign = (*current == '-');
446 ++current;
447 if (current == end)
448 return 0.0;
449 }
450
451 bool leading_zero = false;
452 if (*current == '0') {
453 ++current;
454 if (current == end) {
455 *processed_characters_count = current - input;
456 return SignedZero(sign);
457 }
458
459 leading_zero = true;
460
461 // Ignore leading zeros in the integer part.
462 while (*current == '0') {
463 ++current;
464 if (current == end) {
465 *processed_characters_count = current - input;
466 return SignedZero(sign);
467 }
468 }
469 }
470
471 // Copy significant digits of the integer part (if any) to the buffer.
472 while (*current >= '0' && *current <= '9') {
473 if (significant_digits < kMaxSignificantDigits) {
474 ASSERT(buffer_pos < kBufferSize);
475 buffer[buffer_pos++] = static_cast<char>(*current);
476 significant_digits++;
477 } else {
478 insignificant_digits++; // Move the digit into the exponential part.
479 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
480 }
481 ++current;
482 if (current == end)
483 goto parsing_done;
484 }
485
486 if (*current == '.') {
487 ++current;
488 if (current == end) {
489 if (significant_digits == 0 && !leading_zero) {
490 return 0.0;
491 } else {
492 goto parsing_done;
493 }
494 }
495
496 if (significant_digits == 0) {
497 // Integer part consists of 0 or is absent. Significant digits start after
498 // leading zeros (if any).
499 while (*current == '0') {
500 ++current;
501 if (current == end) {
502 *processed_characters_count = current - input;
503 return SignedZero(sign);
66 } 504 }
67 if (double_inspect.IsNan()) { 505 exponent--; // Move this 0 into the exponent.
68 if (nan_symbol_ == NULL) return false; 506 }
69 result_builder->AddString(nan_symbol_); 507 }
70 return true; 508
71 } 509 // There is a fractional part.
72 return false; 510 while (*current >= '0' && *current <= '9') {
73 } 511 if (significant_digits < kMaxSignificantDigits) {
74
75
76 void DoubleToStringConverter::CreateExponentialRepresentation(
77 const char* de cimal_digits,
78 int length,
79 int exponent,
80 StringBuilder* result_builder) const {
81 ASSERT(length != 0);
82 result_builder->AddCharacter(decimal_digits[0]);
83 if (length != 1) {
84 result_builder->AddCharacter('.');
85 result_builder->AddSubstring(&decimal_digits[1], length-1);
86 }
87 result_builder->AddCharacter(exponent_character_);
88 if (exponent < 0) {
89 result_builder->AddCharacter('-');
90 exponent = -exponent;
91 } else {
92 if ((flags_ & EMIT_POSITIVE_EXPONENT_SIGN) != 0) {
93 result_builder->AddCharacter('+');
94 }
95 }
96 if (exponent == 0) {
97 result_builder->AddCharacter('0');
98 return;
99 }
100 ASSERT(exponent < 1e4);
101 const int kMaxExponentLength = 5;
102 char buffer[kMaxExponentLength + 1];
103 int first_char_pos = kMaxExponentLength;
104 buffer[first_char_pos] = '\0';
105 while (exponent > 0) {
106 buffer[--first_char_pos] = '0' + (exponent % 10);
107 exponent /= 10;
108 }
109 result_builder->AddSubstring(&buffer[first_char_pos],
110 kMaxExponentLength - first_char_pos);
111 }
112
113
114 void DoubleToStringConverter::CreateDecimalRepresentation(
115 const char* decima l_digits,
116 int length,
117 int decimal_point,
118 int digits_after_p oint,
119 StringBuilder* res ult_builder) const {
120 // Create a representation that is padded with zeros if needed.
121 if (decimal_point <= 0) {
122 // "0.00000decimal_rep".
123 result_builder->AddCharacter('0');
124 if (digits_after_point > 0) {
125 result_builder->AddCharacter('.');
126 result_builder->AddPadding('0', -decimal_point);
127 ASSERT(length <= digits_after_point - (-decimal_point));
128 result_builder->AddSubstring(decimal_digits, length);
129 int remaining_digits = digits_after_point - (-decimal_point) - l ength;
130 result_builder->AddPadding('0', remaining_digits);
131 }
132 } else if (decimal_point >= length) {
133 // "decimal_rep0000.00000" or "decimal_rep.0000"
134 result_builder->AddSubstring(decimal_digits, length);
135 result_builder->AddPadding('0', decimal_point - length);
136 if (digits_after_point > 0) {
137 result_builder->AddCharacter('.');
138 result_builder->AddPadding('0', digits_after_point);
139 }
140 } else {
141 // "decima.l_rep000"
142 ASSERT(digits_after_point > 0);
143 result_builder->AddSubstring(decimal_digits, decimal_point);
144 result_builder->AddCharacter('.');
145 ASSERT(length - decimal_point <= digits_after_point);
146 result_builder->AddSubstring(&decimal_digits[decimal_point],
147 length - decimal_point);
148 int remaining_digits = digits_after_point - (length - decimal_point) ;
149 result_builder->AddPadding('0', remaining_digits);
150 }
151 if (digits_after_point == 0) {
152 if ((flags_ & EMIT_TRAILING_DECIMAL_POINT) != 0) {
153 result_builder->AddCharacter('.');
154 }
155 if ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) {
156 result_builder->AddCharacter('0');
157 }
158 }
159 }
160
161
162 bool DoubleToStringConverter::ToShortest(double value,
163 StringBuilder* result_builder) cons t {
164 if (Double(value).IsSpecial()) {
165 return HandleSpecialValues(value, result_builder);
166 }
167
168 int decimal_point;
169 bool sign;
170 const int kDecimalRepCapacity = kBase10MaximalLength + 1;
171 char decimal_rep[kDecimalRepCapacity];
172 int decimal_rep_length;
173
174 DoubleToAscii(value, SHORTEST, 0, decimal_rep, kDecimalRepCapacity,
175 &sign, &decimal_rep_length, &decimal_point);
176
177 bool unique_zero = (flags_ & UNIQUE_ZERO) != 0;
178 if (sign && (value != 0.0 || !unique_zero)) {
179 result_builder->AddCharacter('-');
180 }
181
182 int exponent = decimal_point - 1;
183 if ((decimal_in_shortest_low_ <= exponent) &&
184 (exponent < decimal_in_shortest_high_)) {
185 CreateDecimalRepresentation(decimal_rep, decimal_rep_length,
186 decimal_point,
187 Max(0, decimal_rep_length - decimal_poin t),
188 result_builder);
189 } else {
190 CreateExponentialRepresentation(decimal_rep, decimal_rep_length, exp onent,
191 result_builder);
192 }
193 return true;
194 }
195
196
197 bool DoubleToStringConverter::ToFixed(double value,
198 int requested_digits,
199 StringBuilder* result_builder) const {
200 ASSERT(kMaxFixedDigitsBeforePoint == 60);
201 const double kFirstNonFixed = 1e60;
202
203 if (Double(value).IsSpecial()) {
204 return HandleSpecialValues(value, result_builder);
205 }
206
207 if (requested_digits > kMaxFixedDigitsAfterPoint) return false;
208 if (value >= kFirstNonFixed || value <= -kFirstNonFixed) return false;
209
210 // Find a sufficiently precise decimal representation of n.
211 int decimal_point;
212 bool sign;
213 // Add space for the '\0' byte.
214 const int kDecimalRepCapacity =
215 kMaxFixedDigitsBeforePoint + kMaxFixedDigitsAfterPoint + 1;
216 char decimal_rep[kDecimalRepCapacity];
217 int decimal_rep_length;
218 DoubleToAscii(value, FIXED, requested_digits,
219 decimal_rep, kDecimalRepCapacity,
220 &sign, &decimal_rep_length, &decimal_point);
221
222 bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
223 if (sign && (value != 0.0 || !unique_zero)) {
224 result_builder->AddCharacter('-');
225 }
226
227 CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_poi nt,
228 requested_digits, result_builder);
229 return true;
230 }
231
232
233 bool DoubleToStringConverter::ToExponential(
234 double value,
235 int requested_digits,
236 StringBuilder* result_builder) c onst {
237 if (Double(value).IsSpecial()) {
238 return HandleSpecialValues(value, result_builder);
239 }
240
241 if (requested_digits < -1) return false;
242 if (requested_digits > kMaxExponentialDigits) return false;
243
244 int decimal_point;
245 bool sign;
246 // Add space for digit before the decimal point and the '\0' character.
247 const int kDecimalRepCapacity = kMaxExponentialDigits + 2;
248 ASSERT(kDecimalRepCapacity > kBase10MaximalLength);
249 char decimal_rep[kDecimalRepCapacity];
250 int decimal_rep_length;
251
252 if (requested_digits == -1) {
253 DoubleToAscii(value, SHORTEST, 0,
254 decimal_rep, kDecimalRepCapacity,
255 &sign, &decimal_rep_length, &decimal_point);
256 } else {
257 DoubleToAscii(value, PRECISION, requested_digits + 1,
258 decimal_rep, kDecimalRepCapacity,
259 &sign, &decimal_rep_length, &decimal_point);
260 ASSERT(decimal_rep_length <= requested_digits + 1);
261
262 for (int i = decimal_rep_length; i < requested_digits + 1; ++i) {
263 decimal_rep[i] = '0';
264 }
265 decimal_rep_length = requested_digits + 1;
266 }
267
268 bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
269 if (sign && (value != 0.0 || !unique_zero)) {
270 result_builder->AddCharacter('-');
271 }
272
273 int exponent = decimal_point - 1;
274 CreateExponentialRepresentation(decimal_rep,
275 decimal_rep_length,
276 exponent,
277 result_builder);
278 return true;
279 }
280
281
282 bool DoubleToStringConverter::ToPrecision(double value,
283 int precision,
284 StringBuilder* result_builder) con st {
285 if (Double(value).IsSpecial()) {
286 return HandleSpecialValues(value, result_builder);
287 }
288
289 if (precision < kMinPrecisionDigits || precision > kMaxPrecisionDigits) {
290 return false;
291 }
292
293 // Find a sufficiently precise decimal representation of n.
294 int decimal_point;
295 bool sign;
296 // Add one for the terminating null character.
297 const int kDecimalRepCapacity = kMaxPrecisionDigits + 1;
298 char decimal_rep[kDecimalRepCapacity];
299 int decimal_rep_length;
300
301 DoubleToAscii(value, PRECISION, precision,
302 decimal_rep, kDecimalRepCapacity,
303 &sign, &decimal_rep_length, &decimal_point);
304 ASSERT(decimal_rep_length <= precision);
305
306 bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
307 if (sign && (value != 0.0 || !unique_zero)) {
308 result_builder->AddCharacter('-');
309 }
310
311 // The exponent if we print the number as x.xxeyyy. That is with the
312 // decimal point after the first digit.
313 int exponent = decimal_point - 1;
314
315 int extra_zero = ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) ? 1 : 0;
316 if ((-decimal_point + 1 > max_leading_padding_zeroes_in_precision_mode_) ||
317 (decimal_point - precision + extra_zero >
318 max_trailing_padding_zeroes_in_precision_mode_)) {
319 // Fill buffer to contain 'precision' digits.
320 // Usually the buffer is already at the correct length, but 'Dou bleToAscii'
321 // is allowed to return less characters.
322 for (int i = decimal_rep_length; i < precision; ++i) {
323 decimal_rep[i] = '0';
324 }
325
326 CreateExponentialRepresentation(decimal_rep,
327 precision,
328 exponent,
329 result_builder);
330 } else {
331 CreateDecimalRepresentation(decimal_rep, decimal_rep_length, dec imal_point,
332 Max(0, precision - decimal_point),
333 result_builder);
334 }
335 return true;
336 }
337
338
339 static BignumDtoaMode DtoaToBignumDtoaMode(
340 DoubleToStringConverter::DtoaMode dtoa_mode) {
341 switch (dtoa_mode) {
342 case DoubleToStringConverter::SHORTEST: return BIGNUM_DTOA_SHORTEST ;
343 case DoubleToStringConverter::FIXED: return BIGNUM_DTOA_FIXED;
344 case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISIO N;
345 default:
346 UNREACHABLE();
347 return BIGNUM_DTOA_SHORTEST; // To silence compiler.
348 }
349 }
350
351
352 void DoubleToStringConverter::DoubleToAscii(double v,
353 DtoaMode mode,
354 int requested_digits,
355 char* buffer,
356 int buffer_length,
357 bool* sign,
358 int* length,
359 int* point) {
360 Vector<char> vector(buffer, buffer_length);
361 ASSERT(!Double(v).IsSpecial());
362 ASSERT(mode == SHORTEST || requested_digits >= 0);
363
364 if (Double(v).Sign() < 0) {
365 *sign = true;
366 v = -v;
367 } else {
368 *sign = false;
369 }
370
371 if (mode == PRECISION && requested_digits == 0) {
372 vector[0] = '\0';
373 *length = 0;
374 return;
375 }
376
377 if (v == 0) {
378 vector[0] = '0';
379 vector[1] = '\0';
380 *length = 1;
381 *point = 1;
382 return;
383 }
384
385 bool fast_worked;
386 switch (mode) {
387 case SHORTEST:
388 fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST, 0, vector, length, point);
389 break;
390 case FIXED:
391 fast_worked = FastFixedDtoa(v, requested_digits, vector, length, point);
392 break;
393 case PRECISION:
394 fast_worked = FastDtoa(v, FAST_DTOA_PRECISION, requested_digits,
395 vector, length, point);
396 break;
397 default:
398 UNREACHABLE();
399 fast_worked = false;
400 }
401 if (fast_worked) return;
402
403 // If the fast dtoa didn't succeed use the slower bignum version.
404 BignumDtoaMode bignum_mode = DtoaToBignumDtoaMode(mode);
405 BignumDtoa(v, bignum_mode, requested_digits, vector, length, point);
406 vector[*length] = '\0';
407 }
408
409
410 // Maximum number of significant digits in decimal representation.
411 // The longest possible double in decimal representation is
412 // (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074
413 // (768 digits). If we parse a number whose first digits are equal to a
414 // mean of 2 adjacent doubles (that could have up to 769 digits) the result
415 // must be rounded to the bigger one unless the tail consists of zeros, so
416 // we don't need to preserve all the digits.
417 const int kMaxSignificantDigits = 772;
418
419
420 static double SignedZero(bool sign) {
421 return sign ? -0.0 : 0.0;
422 }
423
424
425 double StringToDoubleConverter::StringToDouble(
426 const char* input,
427 size_t length,
428 size_t* processed_characters_ count) {
429 const char* current = input;
430 const char* end = input + length;
431
432 *processed_characters_count = 0;
433
434 // To make sure that iterator dereferencing is valid the following
435 // convention is used:
436 // 1. Each '++current' statement is followed by check for equality to 'e nd'.
437 // 3. If 'current' becomes equal to 'end' the function returns or goes t o
438 // 'parsing_done'.
439 // 4. 'current' is not dereferenced after the 'parsing_done' label.
440 // 5. Code before 'parsing_done' may rely on 'current != end'.
441 if (current == end) return 0.0;
442
443 // The longest form of simplified number is: "-<significant digits>.1eXX X\0".
444 const int kBufferSize = kMaxSignificantDigits + 10;
445 char buffer[kBufferSize]; // NOLINT: size is known at compile time.
446 int buffer_pos = 0;
447
448 // Exponent will be adjusted if insignificant digits of the integer part
449 // or insignificant leading zeros of the fractional part are dropped.
450 int exponent = 0;
451 int significant_digits = 0;
452 int insignificant_digits = 0;
453 bool nonzero_digit_dropped = false;
454 bool sign = false;
455
456 if (*current == '+' || *current == '-') {
457 sign = (*current == '-');
458 ++current;
459 if (current == end) return 0.0;
460 }
461
462 bool leading_zero = false;
463 if (*current == '0') {
464 ++current;
465 if (current == end) {
466 *processed_characters_count = current - input;
467 return SignedZero(sign);
468 }
469
470 leading_zero = true;
471
472 // Ignore leading zeros in the integer part.
473 while (*current == '0') {
474 ++current;
475 if (current == end) {
476 *processed_characters_count = current - input;
477 return SignedZero(sign);
478 }
479 }
480 }
481
482 // Copy significant digits of the integer part (if any) to the buffer.
483 while (*current >= '0' && *current <= '9') {
484 if (significant_digits < kMaxSignificantDigits) {
485 ASSERT(buffer_pos < kBufferSize);
486 buffer[buffer_pos++] = static_cast<char>(*current);
487 significant_digits++;
488 } else {
489 insignificant_digits++; // Move the digit into the exponential part.
490 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0' ;
491 }
492 ++current;
493 if (current == end) goto parsing_done;
494 }
495
496 if (*current == '.') {
497 ++current;
498 if (current == end) {
499 if (significant_digits == 0 && !leading_zero) {
500 return 0.0;
501 } else {
502 goto parsing_done;
503 }
504 }
505
506 if (significant_digits == 0) {
507 // Integer part consists of 0 or is absent. Significant digits s tart after
508 // leading zeros (if any).
509 while (*current == '0') {
510 ++current;
511 if (current == end) {
512 *processed_characters_count = current - input;
513 return SignedZero(sign);
514 }
515 exponent--; // Move this 0 into the exponent.
516 }
517 }
518
519 // There is a fractional part.
520 while (*current >= '0' && *current <= '9') {
521 if (significant_digits < kMaxSignificantDigits) {
522 ASSERT(buffer_pos < kBufferSize);
523 buffer[buffer_pos++] = static_cast<char>(*current);
524 significant_digits++;
525 exponent--;
526 } else {
527 // Ignore insignificant digits in the fractional part.
528 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
529 }
530 ++current;
531 if (current == end) goto parsing_done;
532 }
533 }
534
535 if (!leading_zero && exponent == 0 && significant_digits == 0) {
536 // If leading_zeros is true then the string contains zeros.
537 // If exponent < 0 then string was [+-]\.0*...
538 // If significant_digits != 0 the string is not equal to 0.
539 // Otherwise there are no digits in the string.
540 return 0.0;
541 }
542
543 // Parse exponential part.
544 if (*current == 'e' || *current == 'E') {
545 ++current;
546 if (current == end) {
547 --current;
548 goto parsing_done;
549 }
550 char sign = 0;
551 if (*current == '+' || *current == '-') {
552 sign = static_cast<char>(*current);
553 ++current;
554 if (current == end) {
555 current -= 2;
556 goto parsing_done;
557 }
558 }
559
560 if (*current < '0' || *current > '9') {
561 if (sign)
562 --current;
563 --current;
564 goto parsing_done;
565 }
566
567 const int max_exponent = INT_MAX / 2;
568 ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2 );
569 int num = 0;
570 do {
571 // Check overflow.
572 int digit = *current - '0';
573 if (num >= max_exponent / 10
574 && !(num == max_exponent / 10 && digit <= max_exponent % 10) ) {
575 num = max_exponent;
576 } else {
577 num = num * 10 + digit;
578 }
579 ++current;
580 } while (current != end && *current >= '0' && *current <= '9');
581
582 exponent += (sign == '-' ? -num : num);
583 }
584
585 parsing_done:
586 exponent += insignificant_digits;
587
588 if (nonzero_digit_dropped) {
589 buffer[buffer_pos++] = '1';
590 exponent--;
591 }
592
593 ASSERT(buffer_pos < kBufferSize); 512 ASSERT(buffer_pos < kBufferSize);
594 buffer[buffer_pos] = '\0'; 513 buffer[buffer_pos++] = static_cast<char>(*current);
595 514 significant_digits++;
596 double converted = Strtod(Vector<const char>(buffer, buffer_pos), expone nt); 515 exponent--;
597 *processed_characters_count = current - input; 516 } else {
598 return sign? -converted: converted; 517 // Ignore insignificant digits in the fractional part.
599 } 518 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
519 }
520 ++current;
521 if (current == end)
522 goto parsing_done;
523 }
524 }
525
526 if (!leading_zero && exponent == 0 && significant_digits == 0) {
527 // If leading_zeros is true then the string contains zeros.
528 // If exponent < 0 then string was [+-]\.0*...
529 // If significant_digits != 0 the string is not equal to 0.
530 // Otherwise there are no digits in the string.
531 return 0.0;
532 }
533
534 // Parse exponential part.
535 if (*current == 'e' || *current == 'E') {
536 ++current;
537 if (current == end) {
538 --current;
539 goto parsing_done;
540 }
541 char sign = 0;
542 if (*current == '+' || *current == '-') {
543 sign = static_cast<char>(*current);
544 ++current;
545 if (current == end) {
546 current -= 2;
547 goto parsing_done;
548 }
549 }
550
551 if (*current < '0' || *current > '9') {
552 if (sign)
553 --current;
554 --current;
555 goto parsing_done;
556 }
557
558 const int max_exponent = INT_MAX / 2;
559 ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
560 int num = 0;
561 do {
562 // Check overflow.
563 int digit = *current - '0';
564 if (num >= max_exponent / 10 &&
565 !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
566 num = max_exponent;
567 } else {
568 num = num * 10 + digit;
569 }
570 ++current;
571 } while (current != end && *current >= '0' && *current <= '9');
572
573 exponent += (sign == '-' ? -num : num);
574 }
575
576 parsing_done:
577 exponent += insignificant_digits;
578
579 if (nonzero_digit_dropped) {
580 buffer[buffer_pos++] = '1';
581 exponent--;
582 }
583
584 ASSERT(buffer_pos < kBufferSize);
585 buffer[buffer_pos] = '\0';
586
587 double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
588 *processed_characters_count = current - input;
589 return sign ? -converted : converted;
590 }
600 591
601 } // namespace double_conversion 592 } // namespace double_conversion
602 593
603 } // namespace WTF 594 } // namespace WTF
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/wtf/dtoa/diy-fp.cc ('k') | third_party/WebKit/Source/wtf/dtoa/fast-dtoa.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698