Line data Source code
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 8 : const DoubleToStringConverter& DoubleToStringConverter::EcmaScriptConverter() {
43 8 : int flags = UNIQUE_ZERO | EMIT_POSITIVE_EXPONENT_SIGN;
44 : static DoubleToStringConverter converter(flags,
45 : "Infinity",
46 : "NaN",
47 : 'e',
48 : -6, 21,
49 8 : 6, 0);
50 8 : return converter;
51 : }
52 :
53 :
54 0 : bool DoubleToStringConverter::HandleSpecialValues(
55 : double value,
56 : StringBuilder* result_builder) const {
57 0 : Double double_inspect(value);
58 0 : if (double_inspect.IsInfinite()) {
59 0 : if (infinity_symbol_ == NULL) return false;
60 0 : if (value < 0) {
61 0 : result_builder->AddCharacter('-');
62 : }
63 0 : result_builder->AddString(infinity_symbol_);
64 0 : return true;
65 : }
66 0 : if (double_inspect.IsNan()) {
67 0 : if (nan_symbol_ == NULL) return false;
68 0 : result_builder->AddString(nan_symbol_);
69 0 : return true;
70 : }
71 0 : return false;
72 : }
73 :
74 :
75 0 : void DoubleToStringConverter::CreateExponentialRepresentation(
76 : const char* decimal_digits,
77 : int length,
78 : int exponent,
79 : StringBuilder* result_builder) const {
80 0 : ASSERT(length != 0);
81 0 : result_builder->AddCharacter(decimal_digits[0]);
82 0 : if (length != 1) {
83 0 : result_builder->AddCharacter('.');
84 0 : result_builder->AddSubstring(&decimal_digits[1], length-1);
85 : }
86 0 : result_builder->AddCharacter(exponent_character_);
87 0 : if (exponent < 0) {
88 0 : result_builder->AddCharacter('-');
89 0 : exponent = -exponent;
90 : } else {
91 0 : if ((flags_ & EMIT_POSITIVE_EXPONENT_SIGN) != 0) {
92 0 : result_builder->AddCharacter('+');
93 : }
94 : }
95 0 : if (exponent == 0) {
96 0 : result_builder->AddCharacter('0');
97 0 : return;
98 : }
99 0 : ASSERT(exponent < 1e4);
100 0 : const int kMaxExponentLength = 5;
101 : char buffer[kMaxExponentLength + 1];
102 0 : buffer[kMaxExponentLength] = '\0';
103 0 : int first_char_pos = kMaxExponentLength;
104 0 : while (exponent > 0) {
105 0 : buffer[--first_char_pos] = '0' + (exponent % 10);
106 0 : exponent /= 10;
107 : }
108 0 : result_builder->AddSubstring(&buffer[first_char_pos],
109 0 : kMaxExponentLength - first_char_pos);
110 : }
111 :
112 :
113 8 : 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 8 : if (decimal_point <= 0) {
121 : // "0.00000decimal_rep" or "0.000decimal_rep00".
122 3 : result_builder->AddCharacter('0');
123 3 : if (digits_after_point > 0) {
124 3 : result_builder->AddCharacter('.');
125 3 : result_builder->AddPadding('0', -decimal_point);
126 3 : ASSERT(length <= digits_after_point - (-decimal_point));
127 3 : result_builder->AddSubstring(decimal_digits, length);
128 3 : int remaining_digits = digits_after_point - (-decimal_point) - length;
129 3 : result_builder->AddPadding('0', remaining_digits);
130 : }
131 5 : } else if (decimal_point >= length) {
132 : // "decimal_rep0000.00000" or "decimal_rep.0000".
133 1 : result_builder->AddSubstring(decimal_digits, length);
134 1 : result_builder->AddPadding('0', decimal_point - length);
135 1 : if (digits_after_point > 0) {
136 0 : result_builder->AddCharacter('.');
137 0 : result_builder->AddPadding('0', digits_after_point);
138 : }
139 : } else {
140 : // "decima.l_rep000".
141 4 : ASSERT(digits_after_point > 0);
142 4 : result_builder->AddSubstring(decimal_digits, decimal_point);
143 4 : result_builder->AddCharacter('.');
144 4 : ASSERT(length - decimal_point <= digits_after_point);
145 4 : result_builder->AddSubstring(&decimal_digits[decimal_point],
146 4 : length - decimal_point);
147 4 : int remaining_digits = digits_after_point - (length - decimal_point);
148 4 : result_builder->AddPadding('0', remaining_digits);
149 : }
150 8 : if (digits_after_point == 0) {
151 1 : if ((flags_ & EMIT_TRAILING_DECIMAL_POINT) != 0) {
152 0 : result_builder->AddCharacter('.');
153 : }
154 1 : if ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) {
155 0 : result_builder->AddCharacter('0');
156 : }
157 : }
158 8 : }
159 :
160 :
161 8 : bool DoubleToStringConverter::ToShortestIeeeNumber(
162 : double value,
163 : StringBuilder* result_builder,
164 : DoubleToStringConverter::DtoaMode mode) const {
165 8 : ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE);
166 8 : if (Double(value).IsSpecial()) {
167 0 : return HandleSpecialValues(value, result_builder);
168 : }
169 :
170 : int decimal_point;
171 : bool sign;
172 8 : 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 8 : &sign, &decimal_rep_length, &decimal_point);
178 :
179 8 : bool unique_zero = (flags_ & UNIQUE_ZERO) != 0;
180 8 : if (sign && (value != 0.0 || !unique_zero)) {
181 0 : result_builder->AddCharacter('-');
182 : }
183 :
184 8 : int exponent = decimal_point - 1;
185 16 : if ((decimal_in_shortest_low_ <= exponent) &&
186 8 : (exponent < decimal_in_shortest_high_)) {
187 8 : CreateDecimalRepresentation(decimal_rep, decimal_rep_length,
188 : decimal_point,
189 : Max(0, decimal_rep_length - decimal_point),
190 8 : result_builder);
191 : } else {
192 : CreateExponentialRepresentation(decimal_rep, decimal_rep_length, exponent,
193 0 : result_builder);
194 : }
195 8 : return true;
196 : }
197 :
198 :
199 0 : bool DoubleToStringConverter::ToFixed(double value,
200 : int requested_digits,
201 : StringBuilder* result_builder) const {
202 : ASSERT(kMaxFixedDigitsBeforePoint == 60);
203 0 : const double kFirstNonFixed = 1e60;
204 :
205 0 : if (Double(value).IsSpecial()) {
206 0 : return HandleSpecialValues(value, result_builder);
207 : }
208 :
209 0 : if (requested_digits > kMaxFixedDigitsAfterPoint) return false;
210 0 : 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 0 : kMaxFixedDigitsBeforePoint + kMaxFixedDigitsAfterPoint + 1;
218 : char decimal_rep[kDecimalRepCapacity];
219 : int decimal_rep_length;
220 : DoubleToAscii(value, FIXED, requested_digits,
221 : decimal_rep, kDecimalRepCapacity,
222 0 : &sign, &decimal_rep_length, &decimal_point);
223 :
224 0 : bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
225 0 : if (sign && (value != 0.0 || !unique_zero)) {
226 0 : result_builder->AddCharacter('-');
227 : }
228 :
229 : CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
230 0 : requested_digits, result_builder);
231 0 : return true;
232 : }
233 :
234 :
235 0 : bool DoubleToStringConverter::ToExponential(
236 : double value,
237 : int requested_digits,
238 : StringBuilder* result_builder) const {
239 0 : if (Double(value).IsSpecial()) {
240 0 : return HandleSpecialValues(value, result_builder);
241 : }
242 :
243 0 : if (requested_digits < -1) return false;
244 0 : 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 0 : const int kDecimalRepCapacity = kMaxExponentialDigits + 2;
250 : ASSERT(kDecimalRepCapacity > kBase10MaximalLength);
251 : char decimal_rep[kDecimalRepCapacity];
252 : int decimal_rep_length;
253 :
254 0 : if (requested_digits == -1) {
255 : DoubleToAscii(value, SHORTEST, 0,
256 : decimal_rep, kDecimalRepCapacity,
257 0 : &sign, &decimal_rep_length, &decimal_point);
258 : } else {
259 0 : DoubleToAscii(value, PRECISION, requested_digits + 1,
260 : decimal_rep, kDecimalRepCapacity,
261 0 : &sign, &decimal_rep_length, &decimal_point);
262 0 : ASSERT(decimal_rep_length <= requested_digits + 1);
263 :
264 0 : for (int i = decimal_rep_length; i < requested_digits + 1; ++i) {
265 0 : decimal_rep[i] = '0';
266 : }
267 0 : decimal_rep_length = requested_digits + 1;
268 : }
269 :
270 0 : bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
271 0 : if (sign && (value != 0.0 || !unique_zero)) {
272 0 : result_builder->AddCharacter('-');
273 : }
274 :
275 0 : int exponent = decimal_point - 1;
276 : CreateExponentialRepresentation(decimal_rep,
277 : decimal_rep_length,
278 : exponent,
279 0 : result_builder);
280 0 : return true;
281 : }
282 :
283 :
284 0 : bool DoubleToStringConverter::ToPrecision(double value,
285 : int precision,
286 : bool* used_exponential_notation,
287 : StringBuilder* result_builder) const {
288 0 : *used_exponential_notation = false;
289 0 : if (Double(value).IsSpecial()) {
290 0 : return HandleSpecialValues(value, result_builder);
291 : }
292 :
293 0 : if (precision < kMinPrecisionDigits || precision > kMaxPrecisionDigits) {
294 0 : 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 0 : 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 0 : &sign, &decimal_rep_length, &decimal_point);
308 0 : ASSERT(decimal_rep_length <= precision);
309 :
310 0 : bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
311 0 : if (sign && (value != 0.0 || !unique_zero)) {
312 0 : 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 0 : int exponent = decimal_point - 1;
318 :
319 0 : int extra_zero = ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) ? 1 : 0;
320 0 : if ((-decimal_point + 1 > max_leading_padding_zeroes_in_precision_mode_) ||
321 0 : (decimal_point - precision + extra_zero >
322 0 : 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 0 : for (int i = decimal_rep_length; i < precision; ++i) {
327 0 : decimal_rep[i] = '0';
328 : }
329 :
330 0 : *used_exponential_notation = true;
331 : CreateExponentialRepresentation(decimal_rep,
332 : precision,
333 : exponent,
334 0 : result_builder);
335 : } else {
336 0 : CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
337 : Max(0, precision - decimal_point),
338 0 : result_builder);
339 : }
340 0 : return true;
341 : }
342 :
343 :
344 0 : static BignumDtoaMode DtoaToBignumDtoaMode(
345 : DoubleToStringConverter::DtoaMode dtoa_mode) {
346 0 : switch (dtoa_mode) {
347 0 : case DoubleToStringConverter::SHORTEST: return BIGNUM_DTOA_SHORTEST;
348 : case DoubleToStringConverter::SHORTEST_SINGLE:
349 0 : return BIGNUM_DTOA_SHORTEST_SINGLE;
350 0 : case DoubleToStringConverter::FIXED: return BIGNUM_DTOA_FIXED;
351 0 : case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISION;
352 : default:
353 0 : UNREACHABLE();
354 : }
355 : }
356 :
357 :
358 8 : void DoubleToStringConverter::DoubleToAscii(double v,
359 : DtoaMode mode,
360 : int requested_digits,
361 : char* buffer,
362 : int buffer_length,
363 : bool* sign,
364 : int* length,
365 : int* point) {
366 8 : Vector<char> vector(buffer, buffer_length);
367 8 : ASSERT(!Double(v).IsSpecial());
368 8 : ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE || requested_digits >= 0);
369 :
370 8 : if (Double(v).Sign() < 0) {
371 0 : *sign = true;
372 0 : v = -v;
373 : } else {
374 8 : *sign = false;
375 : }
376 :
377 8 : if (mode == PRECISION && requested_digits == 0) {
378 0 : vector[0] = '\0';
379 0 : *length = 0;
380 8 : return;
381 : }
382 :
383 8 : if (v == 0) {
384 0 : vector[0] = '0';
385 0 : vector[1] = '\0';
386 0 : *length = 1;
387 0 : *point = 1;
388 0 : return;
389 : }
390 :
391 : bool fast_worked;
392 8 : switch (mode) {
393 : case SHORTEST:
394 8 : fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST, 0, vector, length, point);
395 8 : break;
396 : case SHORTEST_SINGLE:
397 : fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST_SINGLE, 0,
398 0 : vector, length, point);
399 0 : break;
400 : case FIXED:
401 0 : fast_worked = FastFixedDtoa(v, requested_digits, vector, length, point);
402 0 : break;
403 : case PRECISION:
404 : fast_worked = FastDtoa(v, FAST_DTOA_PRECISION, requested_digits,
405 0 : vector, length, point);
406 0 : break;
407 : default:
408 0 : fast_worked = false;
409 0 : UNREACHABLE();
410 : }
411 8 : if (fast_worked) return;
412 :
413 : // If the fast dtoa didn't succeed use the slower bignum version.
414 0 : BignumDtoaMode bignum_mode = DtoaToBignumDtoaMode(mode);
415 0 : BignumDtoa(v, bignum_mode, requested_digits, vector, length, point);
416 0 : vector[*length] = '\0';
417 : }
418 :
419 :
420 : // Consumes the given substring from the iterator.
421 : // Returns false, if the substring does not match.
422 : template <class Iterator>
423 0 : static bool ConsumeSubString(Iterator* current,
424 : Iterator end,
425 : const char* substring) {
426 0 : ASSERT(**current == *substring);
427 0 : for (substring++; *substring != '\0'; substring++) {
428 0 : ++*current;
429 0 : if (*current == end || **current != *substring) return false;
430 : }
431 0 : ++*current;
432 0 : 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 : static const char kWhitespaceTable7[] = { 32, 13, 10, 9, 11, 12 };
447 : static const int kWhitespaceTable7Length = ARRAY_SIZE(kWhitespaceTable7);
448 :
449 :
450 : static const uc16 kWhitespaceTable16[] = {
451 : 160, 8232, 8233, 5760, 6158, 8192, 8193, 8194, 8195,
452 : 8196, 8197, 8198, 8199, 8200, 8201, 8202, 8239, 8287, 12288, 65279
453 : };
454 : static const int kWhitespaceTable16Length = ARRAY_SIZE(kWhitespaceTable16);
455 :
456 :
457 0 : static bool isWhitespace(int x) {
458 0 : if (x < 128) {
459 0 : for (int i = 0; i < kWhitespaceTable7Length; i++) {
460 0 : if (kWhitespaceTable7[i] == x) return true;
461 : }
462 : } else {
463 0 : for (int i = 0; i < kWhitespaceTable16Length; i++) {
464 0 : if (kWhitespaceTable16[i] == x) return true;
465 : }
466 : }
467 0 : return false;
468 : }
469 :
470 :
471 : // Returns true if a nonspace found and false if the end has reached.
472 : template <class Iterator>
473 0 : static inline bool AdvanceToNonspace(Iterator* current, Iterator end) {
474 0 : while (*current != end) {
475 0 : if (!isWhitespace(**current)) return true;
476 0 : ++*current;
477 : }
478 0 : return false;
479 : }
480 :
481 :
482 0 : static bool isDigit(int x, int radix) {
483 0 : return (x >= '0' && x <= '9' && x < '0' + radix)
484 0 : || (radix > 10 && x >= 'a' && x < 'a' + radix - 10)
485 0 : || (radix > 10 && x >= 'A' && x < 'A' + radix - 10);
486 : }
487 :
488 :
489 0 : static double SignedZero(bool sign) {
490 0 : return sign ? -0.0 : 0.0;
491 : }
492 :
493 :
494 : // Returns true if 'c' is a decimal digit that is valid for the given radix.
495 : //
496 : // The function is small and could be inlined, but VS2012 emitted a warning
497 : // because it constant-propagated the radix and concluded that the last
498 : // condition was always true. By moving it into a separate function the
499 : // compiler wouldn't warn anymore.
500 : #if _MSC_VER
501 : #pragma optimize("",off)
502 : static bool IsDecimalDigitForRadix(int c, int radix) {
503 : return '0' <= c && c <= '9' && (c - '0') < radix;
504 : }
505 : #pragma optimize("",on)
506 : #else
507 0 : static bool inline IsDecimalDigitForRadix(int c, int radix) {
508 0 : return '0' <= c && c <= '9' && (c - '0') < radix;
509 : }
510 : #endif
511 : // Returns true if 'c' is a character digit that is valid for the given radix.
512 : // The 'a_character' should be 'a' or 'A'.
513 : //
514 : // The function is small and could be inlined, but VS2012 emitted a warning
515 : // because it constant-propagated the radix and concluded that the first
516 : // condition was always false. By moving it into a separate function the
517 : // compiler wouldn't warn anymore.
518 0 : static bool IsCharacterDigitForRadix(int c, int radix, char a_character) {
519 0 : return radix > 10 && c >= a_character && c < a_character + radix - 10;
520 : }
521 :
522 :
523 : // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
524 : template <int radix_log_2, class Iterator>
525 0 : static double RadixStringToIeee(Iterator* current,
526 : Iterator end,
527 : bool sign,
528 : bool allow_trailing_junk,
529 : double junk_string_value,
530 : bool read_as_double,
531 : bool* result_is_junk) {
532 0 : ASSERT(*current != end);
533 :
534 0 : const int kDoubleSize = Double::kSignificandSize;
535 0 : const int kSingleSize = Single::kSignificandSize;
536 0 : const int kSignificandSize = read_as_double? kDoubleSize: kSingleSize;
537 :
538 0 : *result_is_junk = true;
539 :
540 : // Skip leading 0s.
541 0 : while (**current == '0') {
542 0 : ++(*current);
543 0 : if (*current == end) {
544 0 : *result_is_junk = false;
545 0 : return SignedZero(sign);
546 : }
547 : }
548 :
549 0 : int64_t number = 0;
550 0 : int exponent = 0;
551 0 : const int radix = (1 << radix_log_2);
552 :
553 0 : do {
554 : int digit;
555 0 : if (IsDecimalDigitForRadix(**current, radix)) {
556 0 : digit = static_cast<char>(**current) - '0';
557 0 : } else if (IsCharacterDigitForRadix(**current, radix, 'a')) {
558 0 : digit = static_cast<char>(**current) - 'a' + 10;
559 0 : } else if (IsCharacterDigitForRadix(**current, radix, 'A')) {
560 0 : digit = static_cast<char>(**current) - 'A' + 10;
561 : } else {
562 0 : if (allow_trailing_junk || !AdvanceToNonspace(current, end)) {
563 0 : break;
564 : } else {
565 0 : return junk_string_value;
566 : }
567 : }
568 :
569 0 : number = number * radix + digit;
570 0 : int overflow = static_cast<int>(number >> kSignificandSize);
571 0 : if (overflow != 0) {
572 : // Overflow occurred. Need to determine which direction to round the
573 : // result.
574 0 : int overflow_bits_count = 1;
575 0 : while (overflow > 1) {
576 0 : overflow_bits_count++;
577 0 : overflow >>= 1;
578 : }
579 :
580 0 : int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
581 0 : int dropped_bits = static_cast<int>(number) & dropped_bits_mask;
582 0 : number >>= overflow_bits_count;
583 0 : exponent = overflow_bits_count;
584 :
585 0 : bool zero_tail = true;
586 : for (;;) {
587 0 : ++(*current);
588 0 : if (*current == end || !isDigit(**current, radix)) break;
589 0 : zero_tail = zero_tail && **current == '0';
590 0 : exponent += radix_log_2;
591 : }
592 :
593 0 : if (!allow_trailing_junk && AdvanceToNonspace(current, end)) {
594 0 : return junk_string_value;
595 : }
596 :
597 0 : int middle_value = (1 << (overflow_bits_count - 1));
598 0 : if (dropped_bits > middle_value) {
599 0 : number++; // Rounding up.
600 0 : } else if (dropped_bits == middle_value) {
601 : // Rounding to even to consistency with decimals: half-way case rounds
602 : // up if significant part is odd and down otherwise.
603 0 : if ((number & 1) != 0 || !zero_tail) {
604 0 : number++; // Rounding up.
605 : }
606 : }
607 :
608 : // Rounding up may cause overflow.
609 0 : if ((number & ((int64_t)1 << kSignificandSize)) != 0) {
610 0 : exponent++;
611 0 : number >>= 1;
612 : }
613 0 : break;
614 : }
615 0 : ++(*current);
616 0 : } while (*current != end);
617 :
618 0 : ASSERT(number < ((int64_t)1 << kSignificandSize));
619 0 : ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number);
620 :
621 0 : *result_is_junk = false;
622 :
623 0 : if (exponent == 0) {
624 0 : if (sign) {
625 0 : if (number == 0) return -0.0;
626 0 : number = -number;
627 : }
628 0 : return static_cast<double>(number);
629 : }
630 :
631 0 : ASSERT(number != 0);
632 0 : return Double(DiyFp(number, exponent)).value();
633 : }
634 :
635 :
636 : template <class Iterator>
637 0 : double StringToDoubleConverter::StringToIeee(
638 : Iterator input,
639 : int length,
640 : bool read_as_double,
641 : int* processed_characters_count) const {
642 0 : Iterator current = input;
643 0 : Iterator end = input + length;
644 :
645 0 : *processed_characters_count = 0;
646 :
647 0 : const bool allow_trailing_junk = (flags_ & ALLOW_TRAILING_JUNK) != 0;
648 0 : const bool allow_leading_spaces = (flags_ & ALLOW_LEADING_SPACES) != 0;
649 0 : const bool allow_trailing_spaces = (flags_ & ALLOW_TRAILING_SPACES) != 0;
650 0 : const bool allow_spaces_after_sign = (flags_ & ALLOW_SPACES_AFTER_SIGN) != 0;
651 :
652 : // To make sure that iterator dereferencing is valid the following
653 : // convention is used:
654 : // 1. Each '++current' statement is followed by check for equality to 'end'.
655 : // 2. If AdvanceToNonspace returned false then current == end.
656 : // 3. If 'current' becomes equal to 'end' the function returns or goes to
657 : // 'parsing_done'.
658 : // 4. 'current' is not dereferenced after the 'parsing_done' label.
659 : // 5. Code before 'parsing_done' may rely on 'current != end'.
660 0 : if (current == end) return empty_string_value_;
661 :
662 0 : if (allow_leading_spaces || allow_trailing_spaces) {
663 0 : if (!AdvanceToNonspace(¤t, end)) {
664 0 : *processed_characters_count = static_cast<int>(current - input);
665 0 : return empty_string_value_;
666 : }
667 0 : if (!allow_leading_spaces && (input != current)) {
668 : // No leading spaces allowed, but AdvanceToNonspace moved forward.
669 0 : return junk_string_value_;
670 : }
671 : }
672 :
673 : // The longest form of simplified number is: "-<significant digits>.1eXXX\0".
674 0 : const int kBufferSize = kMaxSignificantDigits + 10;
675 : char buffer[kBufferSize]; // NOLINT: size is known at compile time.
676 0 : int buffer_pos = 0;
677 :
678 : // Exponent will be adjusted if insignificant digits of the integer part
679 : // or insignificant leading zeros of the fractional part are dropped.
680 0 : int exponent = 0;
681 0 : int significant_digits = 0;
682 0 : int insignificant_digits = 0;
683 0 : bool nonzero_digit_dropped = false;
684 :
685 0 : bool sign = false;
686 :
687 0 : if (*current == '+' || *current == '-') {
688 0 : sign = (*current == '-');
689 0 : ++current;
690 0 : Iterator next_non_space = current;
691 : // Skip following spaces (if allowed).
692 0 : if (!AdvanceToNonspace(&next_non_space, end)) return junk_string_value_;
693 0 : if (!allow_spaces_after_sign && (current != next_non_space)) {
694 0 : return junk_string_value_;
695 : }
696 0 : current = next_non_space;
697 : }
698 :
699 0 : if (infinity_symbol_ != NULL) {
700 0 : if (*current == infinity_symbol_[0]) {
701 0 : if (!ConsumeSubString(¤t, end, infinity_symbol_)) {
702 0 : return junk_string_value_;
703 : }
704 :
705 0 : if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
706 0 : return junk_string_value_;
707 : }
708 0 : if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) {
709 0 : return junk_string_value_;
710 : }
711 :
712 0 : ASSERT(buffer_pos == 0);
713 0 : *processed_characters_count = static_cast<int>(current - input);
714 0 : return sign ? -Double::Infinity() : Double::Infinity();
715 : }
716 : }
717 :
718 0 : if (nan_symbol_ != NULL) {
719 0 : if (*current == nan_symbol_[0]) {
720 0 : if (!ConsumeSubString(¤t, end, nan_symbol_)) {
721 0 : return junk_string_value_;
722 : }
723 :
724 0 : if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
725 0 : return junk_string_value_;
726 : }
727 0 : if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) {
728 0 : return junk_string_value_;
729 : }
730 :
731 0 : ASSERT(buffer_pos == 0);
732 0 : *processed_characters_count = static_cast<int>(current - input);
733 0 : return sign ? -Double::NaN() : Double::NaN();
734 : }
735 : }
736 :
737 0 : bool leading_zero = false;
738 0 : if (*current == '0') {
739 0 : ++current;
740 0 : if (current == end) {
741 0 : *processed_characters_count = static_cast<int>(current - input);
742 0 : return SignedZero(sign);
743 : }
744 :
745 0 : leading_zero = true;
746 :
747 : // It could be hexadecimal value.
748 0 : if ((flags_ & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {
749 0 : ++current;
750 0 : if (current == end || !isDigit(*current, 16)) {
751 0 : return junk_string_value_; // "0x".
752 : }
753 :
754 : bool result_is_junk;
755 0 : double result = RadixStringToIeee<4>(¤t,
756 : end,
757 : sign,
758 : allow_trailing_junk,
759 0 : junk_string_value_,
760 : read_as_double,
761 0 : &result_is_junk);
762 0 : if (!result_is_junk) {
763 0 : if (allow_trailing_spaces) AdvanceToNonspace(¤t, end);
764 0 : *processed_characters_count = static_cast<int>(current - input);
765 : }
766 0 : return result;
767 : }
768 :
769 : // Ignore leading zeros in the integer part.
770 0 : while (*current == '0') {
771 0 : ++current;
772 0 : if (current == end) {
773 0 : *processed_characters_count = static_cast<int>(current - input);
774 0 : return SignedZero(sign);
775 : }
776 : }
777 : }
778 :
779 0 : bool octal = leading_zero && (flags_ & ALLOW_OCTALS) != 0;
780 :
781 : // Copy significant digits of the integer part (if any) to the buffer.
782 0 : while (*current >= '0' && *current <= '9') {
783 0 : if (significant_digits < kMaxSignificantDigits) {
784 0 : ASSERT(buffer_pos < kBufferSize);
785 0 : buffer[buffer_pos++] = static_cast<char>(*current);
786 0 : significant_digits++;
787 : // Will later check if it's an octal in the buffer.
788 : } else {
789 0 : insignificant_digits++; // Move the digit into the exponential part.
790 0 : nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
791 : }
792 0 : octal = octal && *current < '8';
793 0 : ++current;
794 0 : if (current == end) goto parsing_done;
795 : }
796 :
797 0 : if (significant_digits == 0) {
798 0 : octal = false;
799 : }
800 :
801 0 : if (*current == '.') {
802 0 : if (octal && !allow_trailing_junk) return junk_string_value_;
803 0 : if (octal) goto parsing_done;
804 :
805 0 : ++current;
806 0 : if (current == end) {
807 0 : if (significant_digits == 0 && !leading_zero) {
808 0 : return junk_string_value_;
809 : } else {
810 : goto parsing_done;
811 : }
812 : }
813 :
814 0 : if (significant_digits == 0) {
815 : // octal = false;
816 : // Integer part consists of 0 or is absent. Significant digits start after
817 : // leading zeros (if any).
818 0 : while (*current == '0') {
819 0 : ++current;
820 0 : if (current == end) {
821 0 : *processed_characters_count = static_cast<int>(current - input);
822 0 : return SignedZero(sign);
823 : }
824 0 : exponent--; // Move this 0 into the exponent.
825 : }
826 : }
827 :
828 : // There is a fractional part.
829 : // We don't emit a '.', but adjust the exponent instead.
830 0 : while (*current >= '0' && *current <= '9') {
831 0 : if (significant_digits < kMaxSignificantDigits) {
832 0 : ASSERT(buffer_pos < kBufferSize);
833 0 : buffer[buffer_pos++] = static_cast<char>(*current);
834 0 : significant_digits++;
835 0 : exponent--;
836 : } else {
837 : // Ignore insignificant digits in the fractional part.
838 0 : nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
839 : }
840 0 : ++current;
841 0 : if (current == end) goto parsing_done;
842 : }
843 : }
844 :
845 0 : if (!leading_zero && exponent == 0 && significant_digits == 0) {
846 : // If leading_zeros is true then the string contains zeros.
847 : // If exponent < 0 then string was [+-]\.0*...
848 : // If significant_digits != 0 the string is not equal to 0.
849 : // Otherwise there are no digits in the string.
850 0 : return junk_string_value_;
851 : }
852 :
853 : // Parse exponential part.
854 0 : if (*current == 'e' || *current == 'E') {
855 0 : if (octal && !allow_trailing_junk) return junk_string_value_;
856 0 : if (octal) goto parsing_done;
857 0 : ++current;
858 0 : if (current == end) {
859 0 : if (allow_trailing_junk) {
860 0 : goto parsing_done;
861 : } else {
862 0 : return junk_string_value_;
863 : }
864 : }
865 0 : char exponen_sign = '+';
866 0 : if (*current == '+' || *current == '-') {
867 0 : exponen_sign = static_cast<char>(*current);
868 0 : ++current;
869 0 : if (current == end) {
870 0 : if (allow_trailing_junk) {
871 0 : goto parsing_done;
872 : } else {
873 0 : return junk_string_value_;
874 : }
875 : }
876 : }
877 :
878 0 : if (current == end || *current < '0' || *current > '9') {
879 0 : if (allow_trailing_junk) {
880 0 : goto parsing_done;
881 : } else {
882 0 : return junk_string_value_;
883 : }
884 : }
885 :
886 0 : const int max_exponent = INT_MAX / 2;
887 0 : ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
888 0 : int num = 0;
889 0 : do {
890 : // Check overflow.
891 0 : int digit = *current - '0';
892 0 : if (num >= max_exponent / 10
893 0 : && !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
894 0 : num = max_exponent;
895 : } else {
896 0 : num = num * 10 + digit;
897 : }
898 0 : ++current;
899 0 : } while (current != end && *current >= '0' && *current <= '9');
900 :
901 0 : exponent += (exponen_sign == '-' ? -num : num);
902 : }
903 :
904 0 : if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
905 0 : return junk_string_value_;
906 : }
907 0 : if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) {
908 0 : return junk_string_value_;
909 : }
910 0 : if (allow_trailing_spaces) {
911 0 : AdvanceToNonspace(¤t, end);
912 : }
913 :
914 : parsing_done:
915 0 : exponent += insignificant_digits;
916 :
917 0 : if (octal) {
918 : double result;
919 : bool result_is_junk;
920 0 : char* start = buffer;
921 0 : result = RadixStringToIeee<3>(&start,
922 : buffer + buffer_pos,
923 : sign,
924 : allow_trailing_junk,
925 0 : junk_string_value_,
926 : read_as_double,
927 : &result_is_junk);
928 0 : ASSERT(!result_is_junk);
929 0 : *processed_characters_count = static_cast<int>(current - input);
930 0 : return result;
931 : }
932 :
933 0 : if (nonzero_digit_dropped) {
934 0 : buffer[buffer_pos++] = '1';
935 0 : exponent--;
936 : }
937 :
938 0 : ASSERT(buffer_pos < kBufferSize);
939 0 : buffer[buffer_pos] = '\0';
940 :
941 : double converted;
942 0 : if (read_as_double) {
943 0 : converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
944 : } else {
945 0 : converted = Strtof(Vector<const char>(buffer, buffer_pos), exponent);
946 : }
947 0 : *processed_characters_count = static_cast<int>(current - input);
948 0 : return sign? -converted: converted;
949 : }
950 :
951 :
952 0 : double StringToDoubleConverter::StringToDouble(
953 : const char* buffer,
954 : int length,
955 : int* processed_characters_count) const {
956 0 : return StringToIeee(buffer, length, true, processed_characters_count);
957 : }
958 :
959 :
960 0 : double StringToDoubleConverter::StringToDouble(
961 : const uc16* buffer,
962 : int length,
963 : int* processed_characters_count) const {
964 0 : return StringToIeee(buffer, length, true, processed_characters_count);
965 : }
966 :
967 :
968 0 : float StringToDoubleConverter::StringToFloat(
969 : const char* buffer,
970 : int length,
971 : int* processed_characters_count) const {
972 0 : return static_cast<float>(StringToIeee(buffer, length, false,
973 0 : processed_characters_count));
974 : }
975 :
976 :
977 0 : float StringToDoubleConverter::StringToFloat(
978 : const uc16* buffer,
979 : int length,
980 : int* processed_characters_count) const {
981 0 : return static_cast<float>(StringToIeee(buffer, length, false,
982 0 : processed_characters_count));
983 : }
984 :
985 : } // namespace double_conversion
|