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