Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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 };
113static const int kWhitespaceTable7Length = DOUBLE_CONVERSION_ARRAY_SIZE(kWhitespaceTable7);
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};
120static const int kWhitespaceTable16Length = DOUBLE_CONVERSION_ARRAY_SIZE(kWhitespaceTable16);
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
269 const int kDoubleSize = Double::kSignificandSize;
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
749double StringToDoubleConverter::StringToDouble(
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
757double StringToDoubleConverter::StringToDouble(
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
765float StringToDoubleConverter::StringToFloat(
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
774float StringToDoubleConverter::StringToFloat(
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:2141
static const size_t kBufferSize
Definition SkString.cpp:27
double value() const
Definition ieee.h:220
if(end==-1)
glong glong end
static const uint8_t buffer[]
GAsyncResult * result
size_t length
double x
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)
#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