|
1 // Copyright 2010 the V8 project authors. All rights reserved. |
|
2 // Redistribution and use in source and binary forms, with or without |
|
3 // modification, are permitted provided that the following conditions are |
|
4 // met: |
|
5 // |
|
6 // * Redistributions of source code must retain the above copyright |
|
7 // notice, this list of conditions and the following disclaimer. |
|
8 // * Redistributions in binary form must reproduce the above |
|
9 // copyright notice, this list of conditions and the following |
|
10 // disclaimer in the documentation and/or other materials provided |
|
11 // with the distribution. |
|
12 // * Neither the name of Google Inc. nor the names of its |
|
13 // contributors may be used to endorse or promote products derived |
|
14 // from this software without specific prior written permission. |
|
15 // |
|
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
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. |
|
27 |
|
28 #include <limits.h> |
|
29 #include <math.h> |
|
30 |
|
31 #include "double-conversion.h" |
|
32 |
|
33 #include "bignum-dtoa.h" |
|
34 #include "fast-dtoa.h" |
|
35 #include "fixed-dtoa.h" |
|
36 #include "ieee.h" |
|
37 #include "strtod.h" |
|
38 #include "utils.h" |
|
39 |
|
40 namespace double_conversion { |
|
41 |
|
42 const DoubleToStringConverter& DoubleToStringConverter::EcmaScriptConverter() { |
|
43 int flags = UNIQUE_ZERO | EMIT_POSITIVE_EXPONENT_SIGN; |
|
44 static DoubleToStringConverter converter(flags, |
|
45 "Infinity", |
|
46 "NaN", |
|
47 'e', |
|
48 -6, 21, |
|
49 6, 0); |
|
50 return converter; |
|
51 } |
|
52 |
|
53 |
|
54 bool DoubleToStringConverter::HandleSpecialValues( |
|
55 double value, |
|
56 StringBuilder* result_builder) const { |
|
57 Double double_inspect(value); |
|
58 if (double_inspect.IsInfinite()) { |
|
59 if (infinity_symbol_ == NULL) return false; |
|
60 if (value < 0) { |
|
61 result_builder->AddCharacter('-'); |
|
62 } |
|
63 result_builder->AddString(infinity_symbol_); |
|
64 return true; |
|
65 } |
|
66 if (double_inspect.IsNan()) { |
|
67 if (nan_symbol_ == NULL) return false; |
|
68 result_builder->AddString(nan_symbol_); |
|
69 return true; |
|
70 } |
|
71 return false; |
|
72 } |
|
73 |
|
74 |
|
75 void DoubleToStringConverter::CreateExponentialRepresentation( |
|
76 const char* decimal_digits, |
|
77 int length, |
|
78 int exponent, |
|
79 StringBuilder* result_builder) const { |
|
80 ASSERT(length != 0); |
|
81 result_builder->AddCharacter(decimal_digits[0]); |
|
82 if (length != 1) { |
|
83 result_builder->AddCharacter('.'); |
|
84 result_builder->AddSubstring(&decimal_digits[1], length-1); |
|
85 } |
|
86 result_builder->AddCharacter(exponent_character_); |
|
87 if (exponent < 0) { |
|
88 result_builder->AddCharacter('-'); |
|
89 exponent = -exponent; |
|
90 } else { |
|
91 if ((flags_ & EMIT_POSITIVE_EXPONENT_SIGN) != 0) { |
|
92 result_builder->AddCharacter('+'); |
|
93 } |
|
94 } |
|
95 if (exponent == 0) { |
|
96 result_builder->AddCharacter('0'); |
|
97 return; |
|
98 } |
|
99 ASSERT(exponent < 1e4); |
|
100 const int kMaxExponentLength = 5; |
|
101 char buffer[kMaxExponentLength + 1]; |
|
102 buffer[kMaxExponentLength] = '\0'; |
|
103 int first_char_pos = kMaxExponentLength; |
|
104 while (exponent > 0) { |
|
105 buffer[--first_char_pos] = '0' + (exponent % 10); |
|
106 exponent /= 10; |
|
107 } |
|
108 result_builder->AddSubstring(&buffer[first_char_pos], |
|
109 kMaxExponentLength - first_char_pos); |
|
110 } |
|
111 |
|
112 |
|
113 void DoubleToStringConverter::CreateDecimalRepresentation( |
|
114 const char* decimal_digits, |
|
115 int length, |
|
116 int decimal_point, |
|
117 int digits_after_point, |
|
118 StringBuilder* result_builder) const { |
|
119 // Create a representation that is padded with zeros if needed. |
|
120 if (decimal_point <= 0) { |
|
121 // "0.00000decimal_rep". |
|
122 result_builder->AddCharacter('0'); |
|
123 if (digits_after_point > 0) { |
|
124 result_builder->AddCharacter('.'); |
|
125 result_builder->AddPadding('0', -decimal_point); |
|
126 ASSERT(length <= digits_after_point - (-decimal_point)); |
|
127 result_builder->AddSubstring(decimal_digits, length); |
|
128 int remaining_digits = digits_after_point - (-decimal_point) - length; |
|
129 result_builder->AddPadding('0', remaining_digits); |
|
130 } |
|
131 } else if (decimal_point >= length) { |
|
132 // "decimal_rep0000.00000" or "decimal_rep.0000" |
|
133 result_builder->AddSubstring(decimal_digits, length); |
|
134 result_builder->AddPadding('0', decimal_point - length); |
|
135 if (digits_after_point > 0) { |
|
136 result_builder->AddCharacter('.'); |
|
137 result_builder->AddPadding('0', digits_after_point); |
|
138 } |
|
139 } else { |
|
140 // "decima.l_rep000" |
|
141 ASSERT(digits_after_point > 0); |
|
142 result_builder->AddSubstring(decimal_digits, decimal_point); |
|
143 result_builder->AddCharacter('.'); |
|
144 ASSERT(length - decimal_point <= digits_after_point); |
|
145 result_builder->AddSubstring(&decimal_digits[decimal_point], |
|
146 length - decimal_point); |
|
147 int remaining_digits = digits_after_point - (length - decimal_point); |
|
148 result_builder->AddPadding('0', remaining_digits); |
|
149 } |
|
150 if (digits_after_point == 0) { |
|
151 if ((flags_ & EMIT_TRAILING_DECIMAL_POINT) != 0) { |
|
152 result_builder->AddCharacter('.'); |
|
153 } |
|
154 if ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) { |
|
155 result_builder->AddCharacter('0'); |
|
156 } |
|
157 } |
|
158 } |
|
159 |
|
160 |
|
161 bool DoubleToStringConverter::ToShortestIeeeNumber( |
|
162 double value, |
|
163 StringBuilder* result_builder, |
|
164 DoubleToStringConverter::DtoaMode mode) const { |
|
165 ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE); |
|
166 if (Double(value).IsSpecial()) { |
|
167 return HandleSpecialValues(value, result_builder); |
|
168 } |
|
169 |
|
170 int decimal_point; |
|
171 bool sign; |
|
172 const int kDecimalRepCapacity = kBase10MaximalLength + 1; |
|
173 char decimal_rep[kDecimalRepCapacity]; |
|
174 int decimal_rep_length; |
|
175 |
|
176 DoubleToAscii(value, mode, 0, decimal_rep, kDecimalRepCapacity, |
|
177 &sign, &decimal_rep_length, &decimal_point); |
|
178 |
|
179 bool unique_zero = (flags_ & UNIQUE_ZERO) != 0; |
|
180 if (sign && (value != 0.0 || !unique_zero)) { |
|
181 result_builder->AddCharacter('-'); |
|
182 } |
|
183 |
|
184 int exponent = decimal_point - 1; |
|
185 if ((decimal_in_shortest_low_ <= exponent) && |
|
186 (exponent < decimal_in_shortest_high_)) { |
|
187 CreateDecimalRepresentation(decimal_rep, decimal_rep_length, |
|
188 decimal_point, |
|
189 Max(0, decimal_rep_length - decimal_point), |
|
190 result_builder); |
|
191 } else { |
|
192 CreateExponentialRepresentation(decimal_rep, decimal_rep_length, exponent, |
|
193 result_builder); |
|
194 } |
|
195 return true; |
|
196 } |
|
197 |
|
198 |
|
199 bool DoubleToStringConverter::ToFixed(double value, |
|
200 int requested_digits, |
|
201 StringBuilder* result_builder) const { |
|
202 ASSERT(kMaxFixedDigitsBeforePoint == 60); |
|
203 const double kFirstNonFixed = 1e60; |
|
204 |
|
205 if (Double(value).IsSpecial()) { |
|
206 return HandleSpecialValues(value, result_builder); |
|
207 } |
|
208 |
|
209 if (requested_digits > kMaxFixedDigitsAfterPoint) return false; |
|
210 if (value >= kFirstNonFixed || value <= -kFirstNonFixed) return false; |
|
211 |
|
212 // Find a sufficiently precise decimal representation of n. |
|
213 int decimal_point; |
|
214 bool sign; |
|
215 // Add space for the '\0' byte. |
|
216 const int kDecimalRepCapacity = |
|
217 kMaxFixedDigitsBeforePoint + kMaxFixedDigitsAfterPoint + 1; |
|
218 char decimal_rep[kDecimalRepCapacity]; |
|
219 int decimal_rep_length; |
|
220 DoubleToAscii(value, FIXED, requested_digits, |
|
221 decimal_rep, kDecimalRepCapacity, |
|
222 &sign, &decimal_rep_length, &decimal_point); |
|
223 |
|
224 bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0); |
|
225 if (sign && (value != 0.0 || !unique_zero)) { |
|
226 result_builder->AddCharacter('-'); |
|
227 } |
|
228 |
|
229 CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point, |
|
230 requested_digits, result_builder); |
|
231 return true; |
|
232 } |
|
233 |
|
234 |
|
235 bool DoubleToStringConverter::ToExponential( |
|
236 double value, |
|
237 int requested_digits, |
|
238 StringBuilder* result_builder) const { |
|
239 if (Double(value).IsSpecial()) { |
|
240 return HandleSpecialValues(value, result_builder); |
|
241 } |
|
242 |
|
243 if (requested_digits < -1) return false; |
|
244 if (requested_digits > kMaxExponentialDigits) return false; |
|
245 |
|
246 int decimal_point; |
|
247 bool sign; |
|
248 // Add space for digit before the decimal point and the '\0' character. |
|
249 const int kDecimalRepCapacity = kMaxExponentialDigits + 2; |
|
250 ASSERT(kDecimalRepCapacity > kBase10MaximalLength); |
|
251 char decimal_rep[kDecimalRepCapacity]; |
|
252 int decimal_rep_length; |
|
253 |
|
254 if (requested_digits == -1) { |
|
255 DoubleToAscii(value, SHORTEST, 0, |
|
256 decimal_rep, kDecimalRepCapacity, |
|
257 &sign, &decimal_rep_length, &decimal_point); |
|
258 } else { |
|
259 DoubleToAscii(value, PRECISION, requested_digits + 1, |
|
260 decimal_rep, kDecimalRepCapacity, |
|
261 &sign, &decimal_rep_length, &decimal_point); |
|
262 ASSERT(decimal_rep_length <= requested_digits + 1); |
|
263 |
|
264 for (int i = decimal_rep_length; i < requested_digits + 1; ++i) { |
|
265 decimal_rep[i] = '0'; |
|
266 } |
|
267 decimal_rep_length = requested_digits + 1; |
|
268 } |
|
269 |
|
270 bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0); |
|
271 if (sign && (value != 0.0 || !unique_zero)) { |
|
272 result_builder->AddCharacter('-'); |
|
273 } |
|
274 |
|
275 int exponent = decimal_point - 1; |
|
276 CreateExponentialRepresentation(decimal_rep, |
|
277 decimal_rep_length, |
|
278 exponent, |
|
279 result_builder); |
|
280 return true; |
|
281 } |
|
282 |
|
283 |
|
284 bool DoubleToStringConverter::ToPrecision(double value, |
|
285 int precision, |
|
286 bool* used_exponential_notation, |
|
287 StringBuilder* result_builder) const { |
|
288 *used_exponential_notation = false; |
|
289 if (Double(value).IsSpecial()) { |
|
290 return HandleSpecialValues(value, result_builder); |
|
291 } |
|
292 |
|
293 if (precision < kMinPrecisionDigits || precision > kMaxPrecisionDigits) { |
|
294 return false; |
|
295 } |
|
296 |
|
297 // Find a sufficiently precise decimal representation of n. |
|
298 int decimal_point; |
|
299 bool sign; |
|
300 // Add one for the terminating null character. |
|
301 const int kDecimalRepCapacity = kMaxPrecisionDigits + 1; |
|
302 char decimal_rep[kDecimalRepCapacity]; |
|
303 int decimal_rep_length; |
|
304 |
|
305 DoubleToAscii(value, PRECISION, precision, |
|
306 decimal_rep, kDecimalRepCapacity, |
|
307 &sign, &decimal_rep_length, &decimal_point); |
|
308 ASSERT(decimal_rep_length <= precision); |
|
309 |
|
310 bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0); |
|
311 if (sign && (value != 0.0 || !unique_zero)) { |
|
312 result_builder->AddCharacter('-'); |
|
313 } |
|
314 |
|
315 // The exponent if we print the number as x.xxeyyy. That is with the |
|
316 // decimal point after the first digit. |
|
317 int exponent = decimal_point - 1; |
|
318 |
|
319 int extra_zero = ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) ? 1 : 0; |
|
320 if ((-decimal_point + 1 > max_leading_padding_zeroes_in_precision_mode_) || |
|
321 (decimal_point - precision + extra_zero > |
|
322 max_trailing_padding_zeroes_in_precision_mode_)) { |
|
323 // Fill buffer to contain 'precision' digits. |
|
324 // Usually the buffer is already at the correct length, but 'DoubleToAscii' |
|
325 // is allowed to return less characters. |
|
326 for (int i = decimal_rep_length; i < precision; ++i) { |
|
327 decimal_rep[i] = '0'; |
|
328 } |
|
329 |
|
330 *used_exponential_notation = true; |
|
331 CreateExponentialRepresentation(decimal_rep, |
|
332 precision, |
|
333 exponent, |
|
334 result_builder); |
|
335 } else { |
|
336 CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point, |
|
337 Max(0, precision - decimal_point), |
|
338 result_builder); |
|
339 } |
|
340 return true; |
|
341 } |
|
342 |
|
343 |
|
344 static BignumDtoaMode DtoaToBignumDtoaMode( |
|
345 DoubleToStringConverter::DtoaMode dtoa_mode) { |
|
346 switch (dtoa_mode) { |
|
347 case DoubleToStringConverter::SHORTEST: return BIGNUM_DTOA_SHORTEST; |
|
348 case DoubleToStringConverter::SHORTEST_SINGLE: |
|
349 return BIGNUM_DTOA_SHORTEST_SINGLE; |
|
350 case DoubleToStringConverter::FIXED: return BIGNUM_DTOA_FIXED; |
|
351 case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISION; |
|
352 default: |
|
353 UNREACHABLE(); |
|
354 return BIGNUM_DTOA_SHORTEST; // To silence compiler. |
|
355 } |
|
356 } |
|
357 |
|
358 |
|
359 void DoubleToStringConverter::DoubleToAscii(double v, |
|
360 DtoaMode mode, |
|
361 int requested_digits, |
|
362 char* buffer, |
|
363 int buffer_length, |
|
364 bool* sign, |
|
365 int* length, |
|
366 int* point) { |
|
367 Vector<char> vector(buffer, buffer_length); |
|
368 ASSERT(!Double(v).IsSpecial()); |
|
369 ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE || requested_digits >= 0); |
|
370 |
|
371 if (Double(v).Sign() < 0) { |
|
372 *sign = true; |
|
373 v = -v; |
|
374 } else { |
|
375 *sign = false; |
|
376 } |
|
377 |
|
378 if (mode == PRECISION && requested_digits == 0) { |
|
379 vector[0] = '\0'; |
|
380 *length = 0; |
|
381 return; |
|
382 } |
|
383 |
|
384 if (v == 0) { |
|
385 vector[0] = '0'; |
|
386 vector[1] = '\0'; |
|
387 *length = 1; |
|
388 *point = 1; |
|
389 return; |
|
390 } |
|
391 |
|
392 bool fast_worked; |
|
393 switch (mode) { |
|
394 case SHORTEST: |
|
395 fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST, 0, vector, length, point); |
|
396 break; |
|
397 case SHORTEST_SINGLE: |
|
398 fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST_SINGLE, 0, |
|
399 vector, length, point); |
|
400 break; |
|
401 case FIXED: |
|
402 fast_worked = FastFixedDtoa(v, requested_digits, vector, length, point); |
|
403 break; |
|
404 case PRECISION: |
|
405 fast_worked = FastDtoa(v, FAST_DTOA_PRECISION, requested_digits, |
|
406 vector, length, point); |
|
407 break; |
|
408 default: |
|
409 UNREACHABLE(); |
|
410 fast_worked = false; |
|
411 } |
|
412 if (fast_worked) return; |
|
413 |
|
414 // If the fast dtoa didn't succeed use the slower bignum version. |
|
415 BignumDtoaMode bignum_mode = DtoaToBignumDtoaMode(mode); |
|
416 BignumDtoa(v, bignum_mode, requested_digits, vector, length, point); |
|
417 vector[*length] = '\0'; |
|
418 } |
|
419 |
|
420 |
|
421 // Consumes the given substring from the iterator. |
|
422 // Returns false, if the substring does not match. |
|
423 static bool ConsumeSubString(const char** current, |
|
424 const char* end, |
|
425 const char* substring) { |
|
426 ASSERT(**current == *substring); |
|
427 for (substring++; *substring != '\0'; substring++) { |
|
428 ++*current; |
|
429 if (*current == end || **current != *substring) return false; |
|
430 } |
|
431 ++*current; |
|
432 return true; |
|
433 } |
|
434 |
|
435 |
|
436 // Maximum number of significant digits in decimal representation. |
|
437 // The longest possible double in decimal representation is |
|
438 // (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074 |
|
439 // (768 digits). If we parse a number whose first digits are equal to a |
|
440 // mean of 2 adjacent doubles (that could have up to 769 digits) the result |
|
441 // must be rounded to the bigger one unless the tail consists of zeros, so |
|
442 // we don't need to preserve all the digits. |
|
443 const int kMaxSignificantDigits = 772; |
|
444 |
|
445 |
|
446 // Returns true if a nonspace found and false if the end has reached. |
|
447 static inline bool AdvanceToNonspace(const char** current, const char* end) { |
|
448 while (*current != end) { |
|
449 if (**current != ' ') return true; |
|
450 ++*current; |
|
451 } |
|
452 return false; |
|
453 } |
|
454 |
|
455 |
|
456 static bool isDigit(int x, int radix) { |
|
457 return (x >= '0' && x <= '9' && x < '0' + radix) |
|
458 || (radix > 10 && x >= 'a' && x < 'a' + radix - 10) |
|
459 || (radix > 10 && x >= 'A' && x < 'A' + radix - 10); |
|
460 } |
|
461 |
|
462 |
|
463 static double SignedZero(bool sign) { |
|
464 return sign ? -0.0 : 0.0; |
|
465 } |
|
466 |
|
467 |
|
468 // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end. |
|
469 template <int radix_log_2> |
|
470 static double RadixStringToIeee(const char* current, |
|
471 const char* end, |
|
472 bool sign, |
|
473 bool allow_trailing_junk, |
|
474 double junk_string_value, |
|
475 bool read_as_double, |
|
476 const char** trailing_pointer) { |
|
477 ASSERT(current != end); |
|
478 |
|
479 const int kDoubleSize = Double::kSignificandSize; |
|
480 const int kSingleSize = Single::kSignificandSize; |
|
481 const int kSignificandSize = read_as_double? kDoubleSize: kSingleSize; |
|
482 |
|
483 // Skip leading 0s. |
|
484 while (*current == '0') { |
|
485 ++current; |
|
486 if (current == end) { |
|
487 *trailing_pointer = end; |
|
488 return SignedZero(sign); |
|
489 } |
|
490 } |
|
491 |
|
492 int64_t number = 0; |
|
493 int exponent = 0; |
|
494 const int radix = (1 << radix_log_2); |
|
495 |
|
496 do { |
|
497 int digit; |
|
498 if (*current >= '0' && *current <= '9' && *current < '0' + radix) { |
|
499 digit = static_cast<char>(*current) - '0'; |
|
500 } else if (radix > 10 && *current >= 'a' && *current < 'a' + radix - 10) { |
|
501 digit = static_cast<char>(*current) - 'a' + 10; |
|
502 } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) { |
|
503 digit = static_cast<char>(*current) - 'A' + 10; |
|
504 } else { |
|
505 if (allow_trailing_junk || !AdvanceToNonspace(¤t, end)) { |
|
506 break; |
|
507 } else { |
|
508 return junk_string_value; |
|
509 } |
|
510 } |
|
511 |
|
512 number = number * radix + digit; |
|
513 int overflow = static_cast<int>(number >> kSignificandSize); |
|
514 if (overflow != 0) { |
|
515 // Overflow occurred. Need to determine which direction to round the |
|
516 // result. |
|
517 int overflow_bits_count = 1; |
|
518 while (overflow > 1) { |
|
519 overflow_bits_count++; |
|
520 overflow >>= 1; |
|
521 } |
|
522 |
|
523 int dropped_bits_mask = ((1 << overflow_bits_count) - 1); |
|
524 int dropped_bits = static_cast<int>(number) & dropped_bits_mask; |
|
525 number >>= overflow_bits_count; |
|
526 exponent = overflow_bits_count; |
|
527 |
|
528 bool zero_tail = true; |
|
529 while (true) { |
|
530 ++current; |
|
531 if (current == end || !isDigit(*current, radix)) break; |
|
532 zero_tail = zero_tail && *current == '0'; |
|
533 exponent += radix_log_2; |
|
534 } |
|
535 |
|
536 if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { |
|
537 return junk_string_value; |
|
538 } |
|
539 |
|
540 int middle_value = (1 << (overflow_bits_count - 1)); |
|
541 if (dropped_bits > middle_value) { |
|
542 number++; // Rounding up. |
|
543 } else if (dropped_bits == middle_value) { |
|
544 // Rounding to even to consistency with decimals: half-way case rounds |
|
545 // up if significant part is odd and down otherwise. |
|
546 if ((number & 1) != 0 || !zero_tail) { |
|
547 number++; // Rounding up. |
|
548 } |
|
549 } |
|
550 |
|
551 // Rounding up may cause overflow. |
|
552 if ((number & ((int64_t)1 << kSignificandSize)) != 0) { |
|
553 exponent++; |
|
554 number >>= 1; |
|
555 } |
|
556 break; |
|
557 } |
|
558 ++current; |
|
559 } while (current != end); |
|
560 |
|
561 ASSERT(number < ((int64_t)1 << kSignificandSize)); |
|
562 ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number); |
|
563 |
|
564 *trailing_pointer = current; |
|
565 |
|
566 if (exponent == 0) { |
|
567 if (sign) { |
|
568 if (number == 0) return -0.0; |
|
569 number = -number; |
|
570 } |
|
571 return static_cast<double>(number); |
|
572 } |
|
573 |
|
574 ASSERT(number != 0); |
|
575 return Double(DiyFp(number, exponent)).value(); |
|
576 } |
|
577 |
|
578 |
|
579 double StringToDoubleConverter::StringToIeee( |
|
580 const char* input, |
|
581 int length, |
|
582 int* processed_characters_count, |
|
583 bool read_as_double) const { |
|
584 const char* current = input; |
|
585 const char* end = input + length; |
|
586 |
|
587 *processed_characters_count = 0; |
|
588 |
|
589 const bool allow_trailing_junk = (flags_ & ALLOW_TRAILING_JUNK) != 0; |
|
590 const bool allow_leading_spaces = (flags_ & ALLOW_LEADING_SPACES) != 0; |
|
591 const bool allow_trailing_spaces = (flags_ & ALLOW_TRAILING_SPACES) != 0; |
|
592 const bool allow_spaces_after_sign = (flags_ & ALLOW_SPACES_AFTER_SIGN) != 0; |
|
593 |
|
594 // To make sure that iterator dereferencing is valid the following |
|
595 // convention is used: |
|
596 // 1. Each '++current' statement is followed by check for equality to 'end'. |
|
597 // 2. If AdvanceToNonspace returned false then current == end. |
|
598 // 3. If 'current' becomes equal to 'end' the function returns or goes to |
|
599 // 'parsing_done'. |
|
600 // 4. 'current' is not dereferenced after the 'parsing_done' label. |
|
601 // 5. Code before 'parsing_done' may rely on 'current != end'. |
|
602 if (current == end) return empty_string_value_; |
|
603 |
|
604 if (allow_leading_spaces || allow_trailing_spaces) { |
|
605 if (!AdvanceToNonspace(¤t, end)) { |
|
606 *processed_characters_count = current - input; |
|
607 return empty_string_value_; |
|
608 } |
|
609 if (!allow_leading_spaces && (input != current)) { |
|
610 // No leading spaces allowed, but AdvanceToNonspace moved forward. |
|
611 return junk_string_value_; |
|
612 } |
|
613 } |
|
614 |
|
615 // The longest form of simplified number is: "-<significant digits>.1eXXX\0". |
|
616 const int kBufferSize = kMaxSignificantDigits + 10; |
|
617 char buffer[kBufferSize]; // NOLINT: size is known at compile time. |
|
618 int buffer_pos = 0; |
|
619 |
|
620 // Exponent will be adjusted if insignificant digits of the integer part |
|
621 // or insignificant leading zeros of the fractional part are dropped. |
|
622 int exponent = 0; |
|
623 int significant_digits = 0; |
|
624 int insignificant_digits = 0; |
|
625 bool nonzero_digit_dropped = false; |
|
626 |
|
627 bool sign = false; |
|
628 |
|
629 if (*current == '+' || *current == '-') { |
|
630 sign = (*current == '-'); |
|
631 ++current; |
|
632 const char* next_non_space = current; |
|
633 // Skip following spaces (if allowed). |
|
634 if (!AdvanceToNonspace(&next_non_space, end)) return junk_string_value_; |
|
635 if (!allow_spaces_after_sign && (current != next_non_space)) { |
|
636 return junk_string_value_; |
|
637 } |
|
638 current = next_non_space; |
|
639 } |
|
640 |
|
641 if (infinity_symbol_ != NULL) { |
|
642 if (*current == infinity_symbol_[0]) { |
|
643 if (!ConsumeSubString(¤t, end, infinity_symbol_)) { |
|
644 return junk_string_value_; |
|
645 } |
|
646 |
|
647 if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) { |
|
648 return junk_string_value_; |
|
649 } |
|
650 if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { |
|
651 return junk_string_value_; |
|
652 } |
|
653 |
|
654 ASSERT(buffer_pos == 0); |
|
655 *processed_characters_count = current - input; |
|
656 return sign ? -Double::Infinity() : Double::Infinity(); |
|
657 } |
|
658 } |
|
659 |
|
660 if (nan_symbol_ != NULL) { |
|
661 if (*current == nan_symbol_[0]) { |
|
662 if (!ConsumeSubString(¤t, end, nan_symbol_)) { |
|
663 return junk_string_value_; |
|
664 } |
|
665 |
|
666 if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) { |
|
667 return junk_string_value_; |
|
668 } |
|
669 if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { |
|
670 return junk_string_value_; |
|
671 } |
|
672 |
|
673 ASSERT(buffer_pos == 0); |
|
674 *processed_characters_count = current - input; |
|
675 return sign ? -Double::NaN() : Double::NaN(); |
|
676 } |
|
677 } |
|
678 |
|
679 bool leading_zero = false; |
|
680 if (*current == '0') { |
|
681 ++current; |
|
682 if (current == end) { |
|
683 *processed_characters_count = current - input; |
|
684 return SignedZero(sign); |
|
685 } |
|
686 |
|
687 leading_zero = true; |
|
688 |
|
689 // It could be hexadecimal value. |
|
690 if ((flags_ & ALLOW_HEX) && (*current == 'x' || *current == 'X')) { |
|
691 ++current; |
|
692 if (current == end || !isDigit(*current, 16)) { |
|
693 return junk_string_value_; // "0x". |
|
694 } |
|
695 |
|
696 const char* tail_pointer = NULL; |
|
697 double result = RadixStringToIeee<4>(current, |
|
698 end, |
|
699 sign, |
|
700 allow_trailing_junk, |
|
701 junk_string_value_, |
|
702 read_as_double, |
|
703 &tail_pointer); |
|
704 if (tail_pointer != NULL) { |
|
705 if (allow_trailing_spaces) AdvanceToNonspace(&tail_pointer, end); |
|
706 *processed_characters_count = tail_pointer - input; |
|
707 } |
|
708 return result; |
|
709 } |
|
710 |
|
711 // Ignore leading zeros in the integer part. |
|
712 while (*current == '0') { |
|
713 ++current; |
|
714 if (current == end) { |
|
715 *processed_characters_count = current - input; |
|
716 return SignedZero(sign); |
|
717 } |
|
718 } |
|
719 } |
|
720 |
|
721 bool octal = leading_zero && (flags_ & ALLOW_OCTALS) != 0; |
|
722 |
|
723 // Copy significant digits of the integer part (if any) to the buffer. |
|
724 while (*current >= '0' && *current <= '9') { |
|
725 if (significant_digits < kMaxSignificantDigits) { |
|
726 ASSERT(buffer_pos < kBufferSize); |
|
727 buffer[buffer_pos++] = static_cast<char>(*current); |
|
728 significant_digits++; |
|
729 // Will later check if it's an octal in the buffer. |
|
730 } else { |
|
731 insignificant_digits++; // Move the digit into the exponential part. |
|
732 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0'; |
|
733 } |
|
734 octal = octal && *current < '8'; |
|
735 ++current; |
|
736 if (current == end) goto parsing_done; |
|
737 } |
|
738 |
|
739 if (significant_digits == 0) { |
|
740 octal = false; |
|
741 } |
|
742 |
|
743 if (*current == '.') { |
|
744 if (octal && !allow_trailing_junk) return junk_string_value_; |
|
745 if (octal) goto parsing_done; |
|
746 |
|
747 ++current; |
|
748 if (current == end) { |
|
749 if (significant_digits == 0 && !leading_zero) { |
|
750 return junk_string_value_; |
|
751 } else { |
|
752 goto parsing_done; |
|
753 } |
|
754 } |
|
755 |
|
756 if (significant_digits == 0) { |
|
757 // octal = false; |
|
758 // Integer part consists of 0 or is absent. Significant digits start after |
|
759 // leading zeros (if any). |
|
760 while (*current == '0') { |
|
761 ++current; |
|
762 if (current == end) { |
|
763 *processed_characters_count = current - input; |
|
764 return SignedZero(sign); |
|
765 } |
|
766 exponent--; // Move this 0 into the exponent. |
|
767 } |
|
768 } |
|
769 |
|
770 // There is a fractional part. |
|
771 // We don't emit a '.', but adjust the exponent instead. |
|
772 while (*current >= '0' && *current <= '9') { |
|
773 if (significant_digits < kMaxSignificantDigits) { |
|
774 ASSERT(buffer_pos < kBufferSize); |
|
775 buffer[buffer_pos++] = static_cast<char>(*current); |
|
776 significant_digits++; |
|
777 exponent--; |
|
778 } else { |
|
779 // Ignore insignificant digits in the fractional part. |
|
780 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0'; |
|
781 } |
|
782 ++current; |
|
783 if (current == end) goto parsing_done; |
|
784 } |
|
785 } |
|
786 |
|
787 if (!leading_zero && exponent == 0 && significant_digits == 0) { |
|
788 // If leading_zeros is true then the string contains zeros. |
|
789 // If exponent < 0 then string was [+-]\.0*... |
|
790 // If significant_digits != 0 the string is not equal to 0. |
|
791 // Otherwise there are no digits in the string. |
|
792 return junk_string_value_; |
|
793 } |
|
794 |
|
795 // Parse exponential part. |
|
796 if (*current == 'e' || *current == 'E') { |
|
797 if (octal && !allow_trailing_junk) return junk_string_value_; |
|
798 if (octal) goto parsing_done; |
|
799 ++current; |
|
800 if (current == end) { |
|
801 if (allow_trailing_junk) { |
|
802 goto parsing_done; |
|
803 } else { |
|
804 return junk_string_value_; |
|
805 } |
|
806 } |
|
807 char sign = '+'; |
|
808 if (*current == '+' || *current == '-') { |
|
809 sign = static_cast<char>(*current); |
|
810 ++current; |
|
811 if (current == end) { |
|
812 if (allow_trailing_junk) { |
|
813 goto parsing_done; |
|
814 } else { |
|
815 return junk_string_value_; |
|
816 } |
|
817 } |
|
818 } |
|
819 |
|
820 if (current == end || *current < '0' || *current > '9') { |
|
821 if (allow_trailing_junk) { |
|
822 goto parsing_done; |
|
823 } else { |
|
824 return junk_string_value_; |
|
825 } |
|
826 } |
|
827 |
|
828 const int max_exponent = INT_MAX / 2; |
|
829 ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2); |
|
830 int num = 0; |
|
831 do { |
|
832 // Check overflow. |
|
833 int digit = *current - '0'; |
|
834 if (num >= max_exponent / 10 |
|
835 && !(num == max_exponent / 10 && digit <= max_exponent % 10)) { |
|
836 num = max_exponent; |
|
837 } else { |
|
838 num = num * 10 + digit; |
|
839 } |
|
840 ++current; |
|
841 } while (current != end && *current >= '0' && *current <= '9'); |
|
842 |
|
843 exponent += (sign == '-' ? -num : num); |
|
844 } |
|
845 |
|
846 if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) { |
|
847 return junk_string_value_; |
|
848 } |
|
849 if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { |
|
850 return junk_string_value_; |
|
851 } |
|
852 if (allow_trailing_spaces) { |
|
853 AdvanceToNonspace(¤t, end); |
|
854 } |
|
855 |
|
856 parsing_done: |
|
857 exponent += insignificant_digits; |
|
858 |
|
859 if (octal) { |
|
860 double result; |
|
861 const char* tail_pointer = NULL; |
|
862 result = RadixStringToIeee<3>(buffer, |
|
863 buffer + buffer_pos, |
|
864 sign, |
|
865 allow_trailing_junk, |
|
866 junk_string_value_, |
|
867 read_as_double, |
|
868 &tail_pointer); |
|
869 ASSERT(tail_pointer != NULL); |
|
870 *processed_characters_count = current - input; |
|
871 return result; |
|
872 } |
|
873 |
|
874 if (nonzero_digit_dropped) { |
|
875 buffer[buffer_pos++] = '1'; |
|
876 exponent--; |
|
877 } |
|
878 |
|
879 ASSERT(buffer_pos < kBufferSize); |
|
880 buffer[buffer_pos] = '\0'; |
|
881 |
|
882 double converted; |
|
883 if (read_as_double) { |
|
884 converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent); |
|
885 } else { |
|
886 converted = Strtof(Vector<const char>(buffer, buffer_pos), exponent); |
|
887 } |
|
888 *processed_characters_count = current - input; |
|
889 return sign? -converted: converted; |
|
890 } |
|
891 |
|
892 } // namespace double_conversion |