Flutter Engine
The Flutter Engine
string-to-double.cc
Go to the documentation of this file.
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 <climits>
29#include <locale>
30#include <cmath>
31
32#include "string-to-double.h"
33
34#include "ieee.h"
35#include "strtod.h"
36#include "utils.h"
37
38#ifdef _MSC_VER
39# if _MSC_VER >= 1900
40// Fix MSVC >= 2015 (_MSC_VER == 1900) warning
41// C4244: 'argument': conversion from 'const uc16' to 'char', possible loss of data
42// against Advance and friends, when instantiated with **it as char, not uc16.
43 __pragma(warning(disable: 4244))
44# endif
45# if _MSC_VER <= 1700 // VS2012, see IsDecimalDigitForRadix warning fix, below
46# define VS2012_RADIXWARN
47# endif
48#endif
49
50namespace double_conversion {
51
52namespace {
53
54inline char ToLower(char ch) {
55 static const std::ctype<char>& cType =
56 std::use_facet<std::ctype<char> >(std::locale::classic());
57 return cType.tolower(ch);
58}
59
60inline char Pass(char ch) {
61 return ch;
62}
63
64template <class Iterator, class Converter>
65static inline bool ConsumeSubStringImpl(Iterator* current,
66 Iterator end,
67 const char* substring,
68 Converter converter) {
69 DOUBLE_CONVERSION_ASSERT(converter(**current) == *substring);
70 for (substring++; *substring != '\0'; substring++) {
71 ++*current;
72 if (*current == end || converter(**current) != *substring) {
73 return false;
74 }
75 }
76 ++*current;
77 return true;
78}
79
80// Consumes the given substring from the iterator.
81// Returns false, if the substring does not match.
82template <class Iterator>
83static bool ConsumeSubString(Iterator* current,
84 Iterator end,
85 const char* substring,
86 bool allow_case_insensitivity) {
87 if (allow_case_insensitivity) {
88 return ConsumeSubStringImpl(current, end, substring, ToLower);
89 } else {
90 return ConsumeSubStringImpl(current, end, substring, Pass);
91 }
92}
93
94// Consumes first character of the str is equal to ch
95inline bool ConsumeFirstCharacter(char ch,
96 const char* str,
97 bool case_insensitivity) {
98 return case_insensitivity ? ToLower(ch) == str[0] : ch == str[0];
99}
100} // namespace
101
102// Maximum number of significant digits in decimal representation.
103// The longest possible double in decimal representation is
104// (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074
105// (768 digits). If we parse a number whose first digits are equal to a
106// mean of 2 adjacent doubles (that could have up to 769 digits) the result
107// must be rounded to the bigger one unless the tail consists of zeros, so
108// we don't need to preserve all the digits.
109const int kMaxSignificantDigits = 772;
110
111
112static const char kWhitespaceTable7[] = { 32, 13, 10, 9, 11, 12 };
114
115
116static const uc16 kWhitespaceTable16[] = {
117 160, 8232, 8233, 5760, 6158, 8192, 8193, 8194, 8195,
118 8196, 8197, 8198, 8199, 8200, 8201, 8202, 8239, 8287, 12288, 65279
119};
121
122
123static bool isWhitespace(int x) {
124 if (x < 128) {
125 for (int i = 0; i < kWhitespaceTable7Length; i++) {
126 if (kWhitespaceTable7[i] == x) return true;
127 }
128 } else {
129 for (int i = 0; i < kWhitespaceTable16Length; i++) {
130 if (kWhitespaceTable16[i] == x) return true;
131 }
132 }
133 return false;
134}
135
136
137// Returns true if a nonspace found and false if the end has reached.
138template <class Iterator>
139static inline bool AdvanceToNonspace(Iterator* current, Iterator end) {
140 while (*current != end) {
141 if (!isWhitespace(**current)) return true;
142 ++*current;
143 }
144 return false;
145}
146
147
148static bool isDigit(int x, int radix) {
149 return (x >= '0' && x <= '9' && x < '0' + radix)
150 || (radix > 10 && x >= 'a' && x < 'a' + radix - 10)
151 || (radix > 10 && x >= 'A' && x < 'A' + radix - 10);
152}
153
154
155static double SignedZero(bool sign) {
156 return sign ? -0.0 : 0.0;
157}
158
159
160// Returns true if 'c' is a decimal digit that is valid for the given radix.
161//
162// The function is small and could be inlined, but VS2012 emitted a warning
163// because it constant-propagated the radix and concluded that the last
164// condition was always true. Moving it into a separate function and
165// suppressing optimisation keeps the compiler from warning.
166#ifdef VS2012_RADIXWARN
167#pragma optimize("",off)
168static bool IsDecimalDigitForRadix(int c, int radix) {
169 return '0' <= c && c <= '9' && (c - '0') < radix;
170}
171#pragma optimize("",on)
172#else
173static bool inline IsDecimalDigitForRadix(int c, int radix) {
174 return '0' <= c && c <= '9' && (c - '0') < radix;
175}
176#endif
177// Returns true if 'c' is a character digit that is valid for the given radix.
178// The 'a_character' should be 'a' or 'A'.
179//
180// The function is small and could be inlined, but VS2012 emitted a warning
181// because it constant-propagated the radix and concluded that the first
182// condition was always false. By moving it into a separate function the
183// compiler wouldn't warn anymore.
184static bool IsCharacterDigitForRadix(int c, int radix, char a_character) {
185 return radix > 10 && c >= a_character && c < a_character + radix - 10;
186}
187
188// Returns true, when the iterator is equal to end.
189template<class Iterator>
190static bool Advance (Iterator* it, uc16 separator, int base, Iterator& end) {
191 if (separator == StringToDoubleConverter::kNoSeparator) {
192 ++(*it);
193 return *it == end;
194 }
195 if (!isDigit(**it, base)) {
196 ++(*it);
197 return *it == end;
198 }
199 ++(*it);
200 if (*it == end) return true;
201 if (*it + 1 == end) return false;
202 if (**it == separator && isDigit(*(*it + 1), base)) {
203 ++(*it);
204 }
205 return *it == end;
206}
207
208// Checks whether the string in the range start-end is a hex-float string.
209// This function assumes that the leading '0x'/'0X' is already consumed.
210//
211// Hex float strings are of one of the following forms:
212// - hex_digits+ 'p' ('+'|'-')? exponent_digits+
213// - hex_digits* '.' hex_digits+ 'p' ('+'|'-')? exponent_digits+
214// - hex_digits+ '.' 'p' ('+'|'-')? exponent_digits+
215template<class Iterator>
216static bool IsHexFloatString(Iterator start,
217 Iterator end,
218 uc16 separator,
219 bool allow_trailing_junk) {
221
222 Iterator current = start;
223
224 bool saw_digit = false;
225 while (isDigit(*current, 16)) {
226 saw_digit = true;
227 if (Advance(&current, separator, 16, end)) return false;
228 }
229 if (*current == '.') {
230 if (Advance(&current, separator, 16, end)) return false;
231 while (isDigit(*current, 16)) {
232 saw_digit = true;
233 if (Advance(&current, separator, 16, end)) return false;
234 }
235 }
236 if (!saw_digit) return false;
237 if (*current != 'p' && *current != 'P') return false;
238 if (Advance(&current, separator, 16, end)) return false;
239 if (*current == '+' || *current == '-') {
240 if (Advance(&current, separator, 16, end)) return false;
241 }
242 if (!isDigit(*current, 10)) return false;
243 if (Advance(&current, separator, 16, end)) return true;
244 while (isDigit(*current, 10)) {
245 if (Advance(&current, separator, 16, end)) return true;
246 }
247 return allow_trailing_junk || !AdvanceToNonspace(&current, end);
248}
249
250
251// Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
252//
253// If parse_as_hex_float is true, then the string must be a valid
254// hex-float.
255template <int radix_log_2, class Iterator>
256static double RadixStringToIeee(Iterator* current,
257 Iterator end,
258 bool sign,
259 uc16 separator,
260 bool parse_as_hex_float,
261 bool allow_trailing_junk,
262 double junk_string_value,
263 bool read_as_double,
264 bool* result_is_junk) {
265 DOUBLE_CONVERSION_ASSERT(*current != end);
266 DOUBLE_CONVERSION_ASSERT(!parse_as_hex_float ||
267 IsHexFloatString(*current, end, separator, allow_trailing_junk));
268
270 const int kSingleSize = Single::kSignificandSize;
271 const int kSignificandSize = read_as_double? kDoubleSize: kSingleSize;
272
273 *result_is_junk = true;
274
275 int64_t number = 0;
276 int exponent = 0;
277 const int radix = (1 << radix_log_2);
278 // Whether we have encountered a '.' and are parsing the decimal digits.
279 // Only relevant if parse_as_hex_float is true.
280 bool post_decimal = false;
281
282 // Skip leading 0s.
283 while (**current == '0') {
284 if (Advance(current, separator, radix, end)) {
285 *result_is_junk = false;
286 return SignedZero(sign);
287 }
288 }
289
290 while (true) {
291 int digit;
292 if (IsDecimalDigitForRadix(**current, radix)) {
293 digit = static_cast<char>(**current) - '0';
294 if (post_decimal) exponent -= radix_log_2;
295 } else if (IsCharacterDigitForRadix(**current, radix, 'a')) {
296 digit = static_cast<char>(**current) - 'a' + 10;
297 if (post_decimal) exponent -= radix_log_2;
298 } else if (IsCharacterDigitForRadix(**current, radix, 'A')) {
299 digit = static_cast<char>(**current) - 'A' + 10;
300 if (post_decimal) exponent -= radix_log_2;
301 } else if (parse_as_hex_float && **current == '.') {
302 post_decimal = true;
303 Advance(current, separator, radix, end);
304 DOUBLE_CONVERSION_ASSERT(*current != end);
305 continue;
306 } else if (parse_as_hex_float && (**current == 'p' || **current == 'P')) {
307 break;
308 } else {
309 if (allow_trailing_junk || !AdvanceToNonspace(current, end)) {
310 break;
311 } else {
312 return junk_string_value;
313 }
314 }
315
316 number = number * radix + digit;
317 int overflow = static_cast<int>(number >> kSignificandSize);
318 if (overflow != 0) {
319 // Overflow occurred. Need to determine which direction to round the
320 // result.
321 int overflow_bits_count = 1;
322 while (overflow > 1) {
323 overflow_bits_count++;
324 overflow >>= 1;
325 }
326
327 int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
328 int dropped_bits = static_cast<int>(number) & dropped_bits_mask;
329 number >>= overflow_bits_count;
330 exponent += overflow_bits_count;
331
332 bool zero_tail = true;
333 for (;;) {
334 if (Advance(current, separator, radix, end)) break;
335 if (parse_as_hex_float && **current == '.') {
336 // Just run over the '.'. We are just trying to see whether there is
337 // a non-zero digit somewhere.
338 Advance(current, separator, radix, end);
339 DOUBLE_CONVERSION_ASSERT(*current != end);
340 post_decimal = true;
341 }
342 if (!isDigit(**current, radix)) break;
343 zero_tail = zero_tail && **current == '0';
344 if (!post_decimal) exponent += radix_log_2;
345 }
346
347 if (!parse_as_hex_float &&
348 !allow_trailing_junk &&
349 AdvanceToNonspace(current, end)) {
350 return junk_string_value;
351 }
352
353 int middle_value = (1 << (overflow_bits_count - 1));
354 if (dropped_bits > middle_value) {
355 number++; // Rounding up.
356 } else if (dropped_bits == middle_value) {
357 // Rounding to even to consistency with decimals: half-way case rounds
358 // up if significant part is odd and down otherwise.
359 if ((number & 1) != 0 || !zero_tail) {
360 number++; // Rounding up.
361 }
362 }
363
364 // Rounding up may cause overflow.
365 if ((number & ((int64_t)1 << kSignificandSize)) != 0) {
366 exponent++;
367 number >>= 1;
368 }
369 break;
370 }
371 if (Advance(current, separator, radix, end)) break;
372 }
373
374 DOUBLE_CONVERSION_ASSERT(number < ((int64_t)1 << kSignificandSize));
375 DOUBLE_CONVERSION_ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number);
376
377 *result_is_junk = false;
378
379 if (parse_as_hex_float) {
380 DOUBLE_CONVERSION_ASSERT(**current == 'p' || **current == 'P');
381 Advance(current, separator, radix, end);
382 DOUBLE_CONVERSION_ASSERT(*current != end);
383 bool is_negative = false;
384 if (**current == '+') {
385 Advance(current, separator, radix, end);
386 DOUBLE_CONVERSION_ASSERT(*current != end);
387 } else if (**current == '-') {
388 is_negative = true;
389 Advance(current, separator, radix, end);
390 DOUBLE_CONVERSION_ASSERT(*current != end);
391 }
392 int written_exponent = 0;
393 while (IsDecimalDigitForRadix(**current, 10)) {
394 // No need to read exponents if they are too big. That could potentially overflow
395 // the `written_exponent` variable.
396 if (abs(written_exponent) <= 100 * Double::kMaxExponent) {
397 written_exponent = 10 * written_exponent + **current - '0';
398 }
399 if (Advance(current, separator, radix, end)) break;
400 }
401 if (is_negative) written_exponent = -written_exponent;
402 exponent += written_exponent;
403 }
404
405 if (exponent == 0 || number == 0) {
406 if (sign) {
407 if (number == 0) return -0.0;
408 number = -number;
409 }
410 return static_cast<double>(number);
411 }
412
413 DOUBLE_CONVERSION_ASSERT(number != 0);
414 double result = Double(DiyFp(number, exponent)).value();
415 return sign ? -result : result;
416}
417
418template <class Iterator>
419double StringToDoubleConverter::StringToIeee(
420 Iterator input,
421 int length,
422 bool read_as_double,
423 int* processed_characters_count) const {
424 Iterator current = input;
425 Iterator end = input + length;
426
427 *processed_characters_count = 0;
428
429 const bool allow_trailing_junk = (flags_ & ALLOW_TRAILING_JUNK) != 0;
430 const bool allow_leading_spaces = (flags_ & ALLOW_LEADING_SPACES) != 0;
431 const bool allow_trailing_spaces = (flags_ & ALLOW_TRAILING_SPACES) != 0;
432 const bool allow_spaces_after_sign = (flags_ & ALLOW_SPACES_AFTER_SIGN) != 0;
433 const bool allow_case_insensitivity = (flags_ & ALLOW_CASE_INSENSITIVITY) != 0;
434
435 // To make sure that iterator dereferencing is valid the following
436 // convention is used:
437 // 1. Each '++current' statement is followed by check for equality to 'end'.
438 // 2. If AdvanceToNonspace returned false then current == end.
439 // 3. If 'current' becomes equal to 'end' the function returns or goes to
440 // 'parsing_done'.
441 // 4. 'current' is not dereferenced after the 'parsing_done' label.
442 // 5. Code before 'parsing_done' may rely on 'current != end'.
443 if (current == end) return empty_string_value_;
444
445 if (allow_leading_spaces || allow_trailing_spaces) {
446 if (!AdvanceToNonspace(&current, end)) {
447 *processed_characters_count = static_cast<int>(current - input);
448 return empty_string_value_;
449 }
450 if (!allow_leading_spaces && (input != current)) {
451 // No leading spaces allowed, but AdvanceToNonspace moved forward.
452 return junk_string_value_;
453 }
454 }
455
456 // Exponent will be adjusted if insignificant digits of the integer part
457 // or insignificant leading zeros of the fractional part are dropped.
458 int exponent = 0;
459 int significant_digits = 0;
460 int insignificant_digits = 0;
461 bool nonzero_digit_dropped = false;
462
463 bool sign = false;
464
465 if (*current == '+' || *current == '-') {
466 sign = (*current == '-');
467 ++current;
468 Iterator next_non_space = current;
469 // Skip following spaces (if allowed).
470 if (!AdvanceToNonspace(&next_non_space, end)) return junk_string_value_;
471 if (!allow_spaces_after_sign && (current != next_non_space)) {
472 return junk_string_value_;
473 }
474 current = next_non_space;
475 }
476
477 if (infinity_symbol_ != DOUBLE_CONVERSION_NULLPTR) {
478 if (ConsumeFirstCharacter(*current, infinity_symbol_, allow_case_insensitivity)) {
479 if (!ConsumeSubString(&current, end, infinity_symbol_, allow_case_insensitivity)) {
480 return junk_string_value_;
481 }
482
483 if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
484 return junk_string_value_;
485 }
486 if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
487 return junk_string_value_;
488 }
489
490 *processed_characters_count = static_cast<int>(current - input);
491 return sign ? -Double::Infinity() : Double::Infinity();
492 }
493 }
494
495 if (nan_symbol_ != DOUBLE_CONVERSION_NULLPTR) {
496 if (ConsumeFirstCharacter(*current, nan_symbol_, allow_case_insensitivity)) {
497 if (!ConsumeSubString(&current, end, nan_symbol_, allow_case_insensitivity)) {
498 return junk_string_value_;
499 }
500
501 if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
502 return junk_string_value_;
503 }
504 if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
505 return junk_string_value_;
506 }
507
508 *processed_characters_count = static_cast<int>(current - input);
509 return sign ? -Double::NaN() : Double::NaN();
510 }
511 }
512
513 bool leading_zero = false;
514 if (*current == '0') {
515 if (Advance(&current, separator_, 10, end)) {
516 *processed_characters_count = static_cast<int>(current - input);
517 return SignedZero(sign);
518 }
519
520 leading_zero = true;
521
522 // It could be hexadecimal value.
523 if (((flags_ & ALLOW_HEX) || (flags_ & ALLOW_HEX_FLOATS)) &&
524 (*current == 'x' || *current == 'X')) {
525 ++current;
526
527 if (current == end) return junk_string_value_; // "0x"
528
529 bool parse_as_hex_float = (flags_ & ALLOW_HEX_FLOATS) &&
530 IsHexFloatString(current, end, separator_, allow_trailing_junk);
531
532 if (!parse_as_hex_float && !isDigit(*current, 16)) {
533 return junk_string_value_;
534 }
535
536 bool result_is_junk;
537 double result = RadixStringToIeee<4>(&current,
538 end,
539 sign,
540 separator_,
541 parse_as_hex_float,
542 allow_trailing_junk,
543 junk_string_value_,
544 read_as_double,
545 &result_is_junk);
546 if (!result_is_junk) {
547 if (allow_trailing_spaces) AdvanceToNonspace(&current, end);
548 *processed_characters_count = static_cast<int>(current - input);
549 }
550 return result;
551 }
552
553 // Ignore leading zeros in the integer part.
554 while (*current == '0') {
555 if (Advance(&current, separator_, 10, end)) {
556 *processed_characters_count = static_cast<int>(current - input);
557 return SignedZero(sign);
558 }
559 }
560 }
561
562 bool octal = leading_zero && (flags_ & ALLOW_OCTALS) != 0;
563
564 // The longest form of simplified number is: "-<significant digits>.1eXXX\0".
565 const int kBufferSize = kMaxSignificantDigits + 10;
567 buffer[kBufferSize]; // NOLINT: size is known at compile time.
568 int buffer_pos = 0;
569
570 // Copy significant digits of the integer part (if any) to the buffer.
571 while (*current >= '0' && *current <= '9') {
572 if (significant_digits < kMaxSignificantDigits) {
574 buffer[buffer_pos++] = static_cast<char>(*current);
575 significant_digits++;
576 // Will later check if it's an octal in the buffer.
577 } else {
578 insignificant_digits++; // Move the digit into the exponential part.
579 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
580 }
581 octal = octal && *current < '8';
582 if (Advance(&current, separator_, 10, end)) goto parsing_done;
583 }
584
585 if (significant_digits == 0) {
586 octal = false;
587 }
588
589 if (*current == '.') {
590 if (octal && !allow_trailing_junk) return junk_string_value_;
591 if (octal) goto parsing_done;
592
593 if (Advance(&current, separator_, 10, end)) {
594 if (significant_digits == 0 && !leading_zero) {
595 return junk_string_value_;
596 } else {
597 goto parsing_done;
598 }
599 }
600
601 if (significant_digits == 0) {
602 // octal = false;
603 // Integer part consists of 0 or is absent. Significant digits start after
604 // leading zeros (if any).
605 while (*current == '0') {
606 if (Advance(&current, separator_, 10, end)) {
607 *processed_characters_count = static_cast<int>(current - input);
608 return SignedZero(sign);
609 }
610 exponent--; // Move this 0 into the exponent.
611 }
612 }
613
614 // There is a fractional part.
615 // We don't emit a '.', but adjust the exponent instead.
616 while (*current >= '0' && *current <= '9') {
617 if (significant_digits < kMaxSignificantDigits) {
619 buffer[buffer_pos++] = static_cast<char>(*current);
620 significant_digits++;
621 exponent--;
622 } else {
623 // Ignore insignificant digits in the fractional part.
624 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
625 }
626 if (Advance(&current, separator_, 10, end)) goto parsing_done;
627 }
628 }
629
630 if (!leading_zero && exponent == 0 && significant_digits == 0) {
631 // If leading_zeros is true then the string contains zeros.
632 // If exponent < 0 then string was [+-]\.0*...
633 // If significant_digits != 0 the string is not equal to 0.
634 // Otherwise there are no digits in the string.
635 return junk_string_value_;
636 }
637
638 // Parse exponential part.
639 if (*current == 'e' || *current == 'E') {
640 if (octal && !allow_trailing_junk) return junk_string_value_;
641 if (octal) goto parsing_done;
642 Iterator junk_begin = current;
643 ++current;
644 if (current == end) {
645 if (allow_trailing_junk) {
646 current = junk_begin;
647 goto parsing_done;
648 } else {
649 return junk_string_value_;
650 }
651 }
652 char exponen_sign = '+';
653 if (*current == '+' || *current == '-') {
654 exponen_sign = static_cast<char>(*current);
655 ++current;
656 if (current == end) {
657 if (allow_trailing_junk) {
658 current = junk_begin;
659 goto parsing_done;
660 } else {
661 return junk_string_value_;
662 }
663 }
664 }
665
666 if (current == end || *current < '0' || *current > '9') {
667 if (allow_trailing_junk) {
668 current = junk_begin;
669 goto parsing_done;
670 } else {
671 return junk_string_value_;
672 }
673 }
674
675 const int max_exponent = INT_MAX / 2;
676 DOUBLE_CONVERSION_ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
677 int num = 0;
678 do {
679 // Check overflow.
680 int digit = *current - '0';
681 if (num >= max_exponent / 10
682 && !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
683 num = max_exponent;
684 } else {
685 num = num * 10 + digit;
686 }
687 ++current;
688 } while (current != end && *current >= '0' && *current <= '9');
689
690 exponent += (exponen_sign == '-' ? -num : num);
691 }
692
693 if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
694 return junk_string_value_;
695 }
696 if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
697 return junk_string_value_;
698 }
699 if (allow_trailing_spaces) {
700 AdvanceToNonspace(&current, end);
701 }
702
703 parsing_done:
704 exponent += insignificant_digits;
705
706 if (octal) {
707 double result;
708 bool result_is_junk;
709 char* start = buffer;
710 result = RadixStringToIeee<3>(&start,
711 buffer + buffer_pos,
712 sign,
713 separator_,
714 false, // Don't parse as hex_float.
715 allow_trailing_junk,
716 junk_string_value_,
717 read_as_double,
718 &result_is_junk);
719 DOUBLE_CONVERSION_ASSERT(!result_is_junk);
720 *processed_characters_count = static_cast<int>(current - input);
721 return result;
722 }
723
724 if (nonzero_digit_dropped) {
725 buffer[buffer_pos++] = '1';
726 exponent--;
727 }
728
730 buffer[buffer_pos] = '\0';
731
732 // Code above ensures there are no leading zeros and the buffer has fewer than
733 // kMaxSignificantDecimalDigits characters. Trim trailing zeros.
734 Vector<const char> chars(buffer, buffer_pos);
735 chars = TrimTrailingZeros(chars);
736 exponent += buffer_pos - chars.length();
737
738 double converted;
739 if (read_as_double) {
740 converted = StrtodTrimmed(chars, exponent);
741 } else {
742 converted = StrtofTrimmed(chars, exponent);
743 }
744 *processed_characters_count = static_cast<int>(current - input);
745 return sign? -converted: converted;
746}
747
748
750 const char* buffer,
751 int length,
752 int* processed_characters_count) const {
753 return StringToIeee(buffer, length, true, processed_characters_count);
754}
755
756
758 const uc16* buffer,
759 int length,
760 int* processed_characters_count) const {
761 return StringToIeee(buffer, length, true, processed_characters_count);
762}
763
764
766 const char* buffer,
767 int length,
768 int* processed_characters_count) const {
769 return static_cast<float>(StringToIeee(buffer, length, false,
770 processed_characters_count));
771}
772
773
775 const uc16* buffer,
776 int length,
777 int* processed_characters_count) const {
778 return static_cast<float>(StringToIeee(buffer, length, false,
779 processed_characters_count));
780}
781
782
783template<>
784double StringToDoubleConverter::StringTo<double>(
785 const char* buffer,
786 int length,
787 int* processed_characters_count) const {
788 return StringToDouble(buffer, length, processed_characters_count);
789}
790
791
792template<>
793float StringToDoubleConverter::StringTo<float>(
794 const char* buffer,
795 int length,
796 int* processed_characters_count) const {
797 return StringToFloat(buffer, length, processed_characters_count);
798}
799
800
801template<>
802double StringToDoubleConverter::StringTo<double>(
803 const uc16* buffer,
804 int length,
805 int* processed_characters_count) const {
806 return StringToDouble(buffer, length, processed_characters_count);
807}
808
809
810template<>
811float StringToDoubleConverter::StringTo<float>(
812 const uc16* buffer,
813 int length,
814 int* processed_characters_count) const {
815 return StringToFloat(buffer, length, processed_characters_count);
816}
817
818} // namespace double_conversion
static int sign(SkScalar x)
Definition: SkPath.cpp:2205
static const size_t kBufferSize
Definition: SkString.cpp:27
static double Infinity()
Definition: ieee.h:236
static const int kMaxExponent
Definition: ieee.h:52
static double NaN()
Definition: ieee.h:240
static const int kSignificandSize
Definition: ieee.h:50
double value() const
Definition: ieee.h:220
static const int kSignificandSize
Definition: ieee.h:294
float StringToFloat(const char *buffer, int length, int *processed_characters_count) const
double StringToDouble(const char *buffer, int length, int *processed_characters_count) const
glong glong end
GAsyncResult * result
size_t length
double x
string converter
Definition: cacheimages.py:19
constexpr intptr_t kDoubleSize
Definition: globals.h:456
static bool IsHexFloatString(Iterator start, Iterator end, uc16 separator, bool allow_trailing_junk)
static bool IsDecimalDigitForRadix(int c, int radix)
const int kMaxSignificantDigits
static bool Advance(Iterator *it, uc16 separator, int base, Iterator &end)
static bool IsCharacterDigitForRadix(int c, int radix, char a_character)
static const int kWhitespaceTable7Length
static double RadixStringToIeee(Iterator *current, Iterator end, bool sign, uc16 separator, bool parse_as_hex_float, bool allow_trailing_junk, double junk_string_value, bool read_as_double, bool *result_is_junk)
float StrtofTrimmed(Vector< const char > trimmed, int exponent)
Definition: strtod.cc:531
static bool isWhitespace(int x)
static const int kWhitespaceTable16Length
double StrtodTrimmed(Vector< const char > trimmed, int exponent)
Definition: strtod.cc:466
static bool isDigit(int x, int radix)
static const uc16 kWhitespaceTable16[]
static double SignedZero(bool sign)
Vector< const char > TrimTrailingZeros(Vector< const char > buffer)
Definition: strtod.h:53
static const char kWhitespaceTable7[]
static bool AdvanceToNonspace(Iterator *current, Iterator end)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
SIN Vec< N, float > abs(const Vec< N, float > &x)
Definition: SkVx.h:707
#define DOUBLE_CONVERSION_NULLPTR
Definition: utils.h:41
#define DOUBLE_CONVERSION_ASSERT(condition)
Definition: utils.h:46
uint16_t uc16
Definition: utils.h:190
#define DOUBLE_CONVERSION_STACK_UNINITIALIZED
Definition: utils.h:106
#define DOUBLE_CONVERSION_ARRAY_SIZE(a)
Definition: utils.h:205