diff options
author | mcheshkov <mcheshkov@yandex-team.ru> | 2022-02-10 16:46:15 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:46:15 +0300 |
commit | e9d19cec64684c9c1e6b0c98297e5b895cf904fe (patch) | |
tree | 2768b1223e96a8a0610a93d18425d9647c1123c8 /contrib/libs/icu/i18n/double-conversion-string-to-double.cpp | |
parent | 60040c91ffe701a84689b2c6310ff845e65cff42 (diff) | |
download | ydb-e9d19cec64684c9c1e6b0c98297e5b895cf904fe.tar.gz |
Restoring authorship annotation for <mcheshkov@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/icu/i18n/double-conversion-string-to-double.cpp')
-rw-r--r-- | contrib/libs/icu/i18n/double-conversion-string-to-double.cpp | 1578 |
1 files changed, 789 insertions, 789 deletions
diff --git a/contrib/libs/icu/i18n/double-conversion-string-to-double.cpp b/contrib/libs/icu/i18n/double-conversion-string-to-double.cpp index 548cad1f302..232b61f4f82 100644 --- a/contrib/libs/icu/i18n/double-conversion-string-to-double.cpp +++ b/contrib/libs/icu/i18n/double-conversion-string-to-double.cpp @@ -1,789 +1,789 @@ -// © 2018 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -// -// From the double-conversion library. Original license: -// -// Copyright 2010 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// ICU PATCH: ifdef around UCONFIG_NO_FORMATTING -#include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING - -// ICU PATCH: Do not include std::locale. - -#include <climits> -// #include <locale> -#include <cmath> - -// ICU PATCH: Customize header file paths for ICU. - -#include "double-conversion-string-to-double.h" - -#include "double-conversion-ieee.h" -#include "double-conversion-strtod.h" -#include "double-conversion-utils.h" - -// ICU PATCH: Wrap in ICU namespace -U_NAMESPACE_BEGIN - -namespace double_conversion { - -namespace { - -inline char ToLower(char ch) { -#if 0 // do not include std::locale in ICU - static const std::ctype<char>& cType = - std::use_facet<std::ctype<char> >(std::locale::classic()); - return cType.tolower(ch); -#else - (void)ch; - DOUBLE_CONVERSION_UNREACHABLE(); -#endif -} - -inline char Pass(char ch) { - return ch; -} - -template <class Iterator, class Converter> -static inline bool ConsumeSubStringImpl(Iterator* current, - Iterator end, - const char* substring, - Converter converter) { - DOUBLE_CONVERSION_ASSERT(converter(**current) == *substring); - for (substring++; *substring != '\0'; substring++) { - ++*current; - if (*current == end || converter(**current) != *substring) { - return false; - } - } - ++*current; - return true; -} - -// Consumes the given substring from the iterator. -// Returns false, if the substring does not match. -template <class Iterator> -static bool ConsumeSubString(Iterator* current, - Iterator end, - const char* substring, - bool allow_case_insensitivity) { - if (allow_case_insensitivity) { - return ConsumeSubStringImpl(current, end, substring, ToLower); - } else { - return ConsumeSubStringImpl(current, end, substring, Pass); - } -} - -// Consumes first character of the str is equal to ch -inline bool ConsumeFirstCharacter(char ch, - const char* str, - bool case_insensitivity) { - return case_insensitivity ? ToLower(ch) == str[0] : ch == str[0]; -} -} // namespace - -// Maximum number of significant digits in decimal representation. -// The longest possible double in decimal representation is -// (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074 -// (768 digits). If we parse a number whose first digits are equal to a -// mean of 2 adjacent doubles (that could have up to 769 digits) the result -// must be rounded to the bigger one unless the tail consists of zeros, so -// we don't need to preserve all the digits. -const int kMaxSignificantDigits = 772; - - -static const char kWhitespaceTable7[] = { 32, 13, 10, 9, 11, 12 }; -static const int kWhitespaceTable7Length = DOUBLE_CONVERSION_ARRAY_SIZE(kWhitespaceTable7); - - -static const uc16 kWhitespaceTable16[] = { - 160, 8232, 8233, 5760, 6158, 8192, 8193, 8194, 8195, - 8196, 8197, 8198, 8199, 8200, 8201, 8202, 8239, 8287, 12288, 65279 -}; -static const int kWhitespaceTable16Length = DOUBLE_CONVERSION_ARRAY_SIZE(kWhitespaceTable16); - - -static bool isWhitespace(int x) { - if (x < 128) { - for (int i = 0; i < kWhitespaceTable7Length; i++) { - if (kWhitespaceTable7[i] == x) return true; - } - } else { - for (int i = 0; i < kWhitespaceTable16Length; i++) { - if (kWhitespaceTable16[i] == x) return true; - } - } - return false; -} - - -// Returns true if a nonspace found and false if the end has reached. -template <class Iterator> -static inline bool AdvanceToNonspace(Iterator* current, Iterator end) { - while (*current != end) { - if (!isWhitespace(**current)) return true; - ++*current; - } - return false; -} - - -static bool isDigit(int x, int radix) { - return (x >= '0' && x <= '9' && x < '0' + radix) - || (radix > 10 && x >= 'a' && x < 'a' + radix - 10) - || (radix > 10 && x >= 'A' && x < 'A' + radix - 10); -} - - -static double SignedZero(bool sign) { - return sign ? -0.0 : 0.0; -} - - -// Returns true if 'c' is a decimal digit that is valid for the given radix. -// -// The function is small and could be inlined, but VS2012 emitted a warning -// because it constant-propagated the radix and concluded that the last -// condition was always true. By moving it into a separate function the -// compiler wouldn't warn anymore. -#ifdef _MSC_VER -#pragma optimize("",off) -static bool IsDecimalDigitForRadix(int c, int radix) { - return '0' <= c && c <= '9' && (c - '0') < radix; -} -#pragma optimize("",on) -#else -static bool inline IsDecimalDigitForRadix(int c, int radix) { - return '0' <= c && c <= '9' && (c - '0') < radix; -} -#endif -// Returns true if 'c' is a character digit that is valid for the given radix. -// The 'a_character' should be 'a' or 'A'. -// -// The function is small and could be inlined, but VS2012 emitted a warning -// because it constant-propagated the radix and concluded that the first -// condition was always false. By moving it into a separate function the -// compiler wouldn't warn anymore. -static bool IsCharacterDigitForRadix(int c, int radix, char a_character) { - return radix > 10 && c >= a_character && c < a_character + radix - 10; -} - -// Returns true, when the iterator is equal to end. -template<class Iterator> -static bool Advance (Iterator* it, uc16 separator, int base, Iterator& end) { - if (separator == StringToDoubleConverter::kNoSeparator) { - ++(*it); - return *it == end; - } - if (!isDigit(**it, base)) { - ++(*it); - return *it == end; - } - ++(*it); - if (*it == end) return true; - if (*it + 1 == end) return false; - if (**it == separator && isDigit(*(*it + 1), base)) { - ++(*it); - } - return *it == end; -} - -// Checks whether the string in the range start-end is a hex-float string. -// This function assumes that the leading '0x'/'0X' is already consumed. -// -// Hex float strings are of one of the following forms: -// - hex_digits+ 'p' ('+'|'-')? exponent_digits+ -// - hex_digits* '.' hex_digits+ 'p' ('+'|'-')? exponent_digits+ -// - hex_digits+ '.' 'p' ('+'|'-')? exponent_digits+ -template<class Iterator> -static bool IsHexFloatString(Iterator start, - Iterator end, - uc16 separator, - bool allow_trailing_junk) { - DOUBLE_CONVERSION_ASSERT(start != end); - - Iterator current = start; - - bool saw_digit = false; - while (isDigit(*current, 16)) { - saw_digit = true; - if (Advance(¤t, separator, 16, end)) return false; - } - if (*current == '.') { - if (Advance(¤t, separator, 16, end)) return false; - while (isDigit(*current, 16)) { - saw_digit = true; - if (Advance(¤t, separator, 16, end)) return false; - } - } - if (!saw_digit) return false; - if (*current != 'p' && *current != 'P') return false; - if (Advance(¤t, separator, 16, end)) return false; - if (*current == '+' || *current == '-') { - if (Advance(¤t, separator, 16, end)) return false; - } - if (!isDigit(*current, 10)) return false; - if (Advance(¤t, separator, 16, end)) return true; - while (isDigit(*current, 10)) { - if (Advance(¤t, separator, 16, end)) return true; - } - return allow_trailing_junk || !AdvanceToNonspace(¤t, end); -} - - -// Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end. -// -// If parse_as_hex_float is true, then the string must be a valid -// hex-float. -template <int radix_log_2, class Iterator> -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) { - DOUBLE_CONVERSION_ASSERT(*current != end); - DOUBLE_CONVERSION_ASSERT(!parse_as_hex_float || - IsHexFloatString(*current, end, separator, allow_trailing_junk)); - - const int kDoubleSize = Double::kSignificandSize; - const int kSingleSize = Single::kSignificandSize; - const int kSignificandSize = read_as_double? kDoubleSize: kSingleSize; - - *result_is_junk = true; - - int64_t number = 0; - int exponent = 0; - const int radix = (1 << radix_log_2); - // Whether we have encountered a '.' and are parsing the decimal digits. - // Only relevant if parse_as_hex_float is true. - bool post_decimal = false; - - // Skip leading 0s. - while (**current == '0') { - if (Advance(current, separator, radix, end)) { - *result_is_junk = false; - return SignedZero(sign); - } - } - - while (true) { - int digit; - if (IsDecimalDigitForRadix(**current, radix)) { - digit = static_cast<char>(**current) - '0'; - if (post_decimal) exponent -= radix_log_2; - } else if (IsCharacterDigitForRadix(**current, radix, 'a')) { - digit = static_cast<char>(**current) - 'a' + 10; - if (post_decimal) exponent -= radix_log_2; - } else if (IsCharacterDigitForRadix(**current, radix, 'A')) { - digit = static_cast<char>(**current) - 'A' + 10; - if (post_decimal) exponent -= radix_log_2; - } else if (parse_as_hex_float && **current == '.') { - post_decimal = true; - Advance(current, separator, radix, end); - DOUBLE_CONVERSION_ASSERT(*current != end); - continue; - } else if (parse_as_hex_float && (**current == 'p' || **current == 'P')) { - break; - } else { - if (allow_trailing_junk || !AdvanceToNonspace(current, end)) { - break; - } else { - return junk_string_value; - } - } - - number = number * radix + digit; - int overflow = static_cast<int>(number >> kSignificandSize); - if (overflow != 0) { - // Overflow occurred. Need to determine which direction to round the - // result. - int overflow_bits_count = 1; - while (overflow > 1) { - overflow_bits_count++; - overflow >>= 1; - } - - int dropped_bits_mask = ((1 << overflow_bits_count) - 1); - int dropped_bits = static_cast<int>(number) & dropped_bits_mask; - number >>= overflow_bits_count; - exponent += overflow_bits_count; - - bool zero_tail = true; - for (;;) { - if (Advance(current, separator, radix, end)) break; - if (parse_as_hex_float && **current == '.') { - // Just run over the '.'. We are just trying to see whether there is - // a non-zero digit somewhere. - Advance(current, separator, radix, end); - DOUBLE_CONVERSION_ASSERT(*current != end); - post_decimal = true; - } - if (!isDigit(**current, radix)) break; - zero_tail = zero_tail && **current == '0'; - if (!post_decimal) exponent += radix_log_2; - } - - if (!parse_as_hex_float && - !allow_trailing_junk && - AdvanceToNonspace(current, end)) { - return junk_string_value; - } - - int middle_value = (1 << (overflow_bits_count - 1)); - if (dropped_bits > middle_value) { - number++; // Rounding up. - } else if (dropped_bits == middle_value) { - // Rounding to even to consistency with decimals: half-way case rounds - // up if significant part is odd and down otherwise. - if ((number & 1) != 0 || !zero_tail) { - number++; // Rounding up. - } - } - - // Rounding up may cause overflow. - if ((number & ((int64_t)1 << kSignificandSize)) != 0) { - exponent++; - number >>= 1; - } - break; - } - if (Advance(current, separator, radix, end)) break; - } - - DOUBLE_CONVERSION_ASSERT(number < ((int64_t)1 << kSignificandSize)); - DOUBLE_CONVERSION_ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number); - - *result_is_junk = false; - - if (parse_as_hex_float) { - DOUBLE_CONVERSION_ASSERT(**current == 'p' || **current == 'P'); - Advance(current, separator, radix, end); - DOUBLE_CONVERSION_ASSERT(*current != end); - bool is_negative = false; - if (**current == '+') { - Advance(current, separator, radix, end); - DOUBLE_CONVERSION_ASSERT(*current != end); - } else if (**current == '-') { - is_negative = true; - Advance(current, separator, radix, end); - DOUBLE_CONVERSION_ASSERT(*current != end); - } - int written_exponent = 0; - while (IsDecimalDigitForRadix(**current, 10)) { - // No need to read exponents if they are too big. That could potentially overflow - // the `written_exponent` variable. - if (abs(written_exponent) <= 100 * Double::kMaxExponent) { - written_exponent = 10 * written_exponent + **current - '0'; - } - if (Advance(current, separator, radix, end)) break; - } - if (is_negative) written_exponent = -written_exponent; - exponent += written_exponent; - } - - if (exponent == 0 || number == 0) { - if (sign) { - if (number == 0) return -0.0; - number = -number; - } - return static_cast<double>(number); - } - - DOUBLE_CONVERSION_ASSERT(number != 0); - double result = Double(DiyFp(number, exponent)).value(); - return sign ? -result : result; -} - -template <class Iterator> -double StringToDoubleConverter::StringToIeee( - Iterator input, - int length, - bool read_as_double, - int* processed_characters_count) const { - Iterator current = input; - Iterator end = input + length; - - *processed_characters_count = 0; - - const bool allow_trailing_junk = (flags_ & ALLOW_TRAILING_JUNK) != 0; - const bool allow_leading_spaces = (flags_ & ALLOW_LEADING_SPACES) != 0; - const bool allow_trailing_spaces = (flags_ & ALLOW_TRAILING_SPACES) != 0; - const bool allow_spaces_after_sign = (flags_ & ALLOW_SPACES_AFTER_SIGN) != 0; - const bool allow_case_insensitivity = (flags_ & ALLOW_CASE_INSENSITIVITY) != 0; - - // To make sure that iterator dereferencing is valid the following - // convention is used: - // 1. Each '++current' statement is followed by check for equality to 'end'. - // 2. If AdvanceToNonspace returned false then current == end. - // 3. If 'current' becomes equal to 'end' the function returns or goes to - // 'parsing_done'. - // 4. 'current' is not dereferenced after the 'parsing_done' label. - // 5. Code before 'parsing_done' may rely on 'current != end'. - if (current == end) return empty_string_value_; - - if (allow_leading_spaces || allow_trailing_spaces) { - if (!AdvanceToNonspace(¤t, end)) { - *processed_characters_count = static_cast<int>(current - input); - return empty_string_value_; - } - if (!allow_leading_spaces && (input != current)) { - // No leading spaces allowed, but AdvanceToNonspace moved forward. - return junk_string_value_; - } - } - - // Exponent will be adjusted if insignificant digits of the integer part - // or insignificant leading zeros of the fractional part are dropped. - int exponent = 0; - int significant_digits = 0; - int insignificant_digits = 0; - bool nonzero_digit_dropped = false; - - bool sign = false; - - if (*current == '+' || *current == '-') { - sign = (*current == '-'); - ++current; - Iterator next_non_space = current; - // Skip following spaces (if allowed). - if (!AdvanceToNonspace(&next_non_space, end)) return junk_string_value_; - if (!allow_spaces_after_sign && (current != next_non_space)) { - return junk_string_value_; - } - current = next_non_space; - } - - if (infinity_symbol_ != NULL) { - if (ConsumeFirstCharacter(*current, infinity_symbol_, allow_case_insensitivity)) { - if (!ConsumeSubString(¤t, end, infinity_symbol_, allow_case_insensitivity)) { - return junk_string_value_; - } - - if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) { - return junk_string_value_; - } - if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { - return junk_string_value_; - } - - *processed_characters_count = static_cast<int>(current - input); - return sign ? -Double::Infinity() : Double::Infinity(); - } - } - - if (nan_symbol_ != NULL) { - if (ConsumeFirstCharacter(*current, nan_symbol_, allow_case_insensitivity)) { - if (!ConsumeSubString(¤t, end, nan_symbol_, allow_case_insensitivity)) { - return junk_string_value_; - } - - if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) { - return junk_string_value_; - } - if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { - return junk_string_value_; - } - - *processed_characters_count = static_cast<int>(current - input); - return sign ? -Double::NaN() : Double::NaN(); - } - } - - bool leading_zero = false; - if (*current == '0') { - if (Advance(¤t, separator_, 10, end)) { - *processed_characters_count = static_cast<int>(current - input); - return SignedZero(sign); - } - - leading_zero = true; - - // It could be hexadecimal value. - if (((flags_ & ALLOW_HEX) || (flags_ & ALLOW_HEX_FLOATS)) && - (*current == 'x' || *current == 'X')) { - ++current; - - if (current == end) return junk_string_value_; // "0x" - - bool parse_as_hex_float = (flags_ & ALLOW_HEX_FLOATS) && - IsHexFloatString(current, end, separator_, allow_trailing_junk); - - if (!parse_as_hex_float && !isDigit(*current, 16)) { - return junk_string_value_; - } - - bool result_is_junk; - double result = RadixStringToIeee<4>(¤t, - end, - sign, - separator_, - parse_as_hex_float, - allow_trailing_junk, - junk_string_value_, - read_as_double, - &result_is_junk); - if (!result_is_junk) { - if (allow_trailing_spaces) AdvanceToNonspace(¤t, end); - *processed_characters_count = static_cast<int>(current - input); - } - return result; - } - - // Ignore leading zeros in the integer part. - while (*current == '0') { - if (Advance(¤t, separator_, 10, end)) { - *processed_characters_count = static_cast<int>(current - input); - return SignedZero(sign); - } - } - } - - bool octal = leading_zero && (flags_ & ALLOW_OCTALS) != 0; - - // The longest form of simplified number is: "-<significant digits>.1eXXX\0". - const int kBufferSize = kMaxSignificantDigits + 10; - DOUBLE_CONVERSION_STACK_UNINITIALIZED char - buffer[kBufferSize]; // NOLINT: size is known at compile time. - int buffer_pos = 0; - - // Copy significant digits of the integer part (if any) to the buffer. - while (*current >= '0' && *current <= '9') { - if (significant_digits < kMaxSignificantDigits) { - DOUBLE_CONVERSION_ASSERT(buffer_pos < kBufferSize); - buffer[buffer_pos++] = static_cast<char>(*current); - significant_digits++; - // Will later check if it's an octal in the buffer. - } else { - insignificant_digits++; // Move the digit into the exponential part. - nonzero_digit_dropped = nonzero_digit_dropped || *current != '0'; - } - octal = octal && *current < '8'; - if (Advance(¤t, separator_, 10, end)) goto parsing_done; - } - - if (significant_digits == 0) { - octal = false; - } - - if (*current == '.') { - if (octal && !allow_trailing_junk) return junk_string_value_; - if (octal) goto parsing_done; - - if (Advance(¤t, separator_, 10, end)) { - if (significant_digits == 0 && !leading_zero) { - return junk_string_value_; - } else { - goto parsing_done; - } - } - - if (significant_digits == 0) { - // octal = false; - // Integer part consists of 0 or is absent. Significant digits start after - // leading zeros (if any). - while (*current == '0') { - if (Advance(¤t, separator_, 10, end)) { - *processed_characters_count = static_cast<int>(current - input); - return SignedZero(sign); - } - exponent--; // Move this 0 into the exponent. - } - } - - // There is a fractional part. - // We don't emit a '.', but adjust the exponent instead. - while (*current >= '0' && *current <= '9') { - if (significant_digits < kMaxSignificantDigits) { - DOUBLE_CONVERSION_ASSERT(buffer_pos < kBufferSize); - buffer[buffer_pos++] = static_cast<char>(*current); - significant_digits++; - exponent--; - } else { - // Ignore insignificant digits in the fractional part. - nonzero_digit_dropped = nonzero_digit_dropped || *current != '0'; - } - if (Advance(¤t, separator_, 10, end)) goto parsing_done; - } - } - - if (!leading_zero && exponent == 0 && significant_digits == 0) { - // If leading_zeros is true then the string contains zeros. - // If exponent < 0 then string was [+-]\.0*... - // If significant_digits != 0 the string is not equal to 0. - // Otherwise there are no digits in the string. - return junk_string_value_; - } - - // Parse exponential part. - if (*current == 'e' || *current == 'E') { - if (octal && !allow_trailing_junk) return junk_string_value_; - if (octal) goto parsing_done; - Iterator junk_begin = current; - ++current; - if (current == end) { - if (allow_trailing_junk) { - current = junk_begin; - goto parsing_done; - } else { - return junk_string_value_; - } - } - char exponen_sign = '+'; - if (*current == '+' || *current == '-') { - exponen_sign = static_cast<char>(*current); - ++current; - if (current == end) { - if (allow_trailing_junk) { - current = junk_begin; - goto parsing_done; - } else { - return junk_string_value_; - } - } - } - - if (current == end || *current < '0' || *current > '9') { - if (allow_trailing_junk) { - current = junk_begin; - goto parsing_done; - } else { - return junk_string_value_; - } - } - - const int max_exponent = INT_MAX / 2; - DOUBLE_CONVERSION_ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2); - int num = 0; - do { - // Check overflow. - int digit = *current - '0'; - if (num >= max_exponent / 10 - && !(num == max_exponent / 10 && digit <= max_exponent % 10)) { - num = max_exponent; - } else { - num = num * 10 + digit; - } - ++current; - } while (current != end && *current >= '0' && *current <= '9'); - - exponent += (exponen_sign == '-' ? -num : num); - } - - if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) { - return junk_string_value_; - } - if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { - return junk_string_value_; - } - if (allow_trailing_spaces) { - AdvanceToNonspace(¤t, end); - } - - parsing_done: - exponent += insignificant_digits; - - if (octal) { - double result; - bool result_is_junk; - char* start = buffer; - result = RadixStringToIeee<3>(&start, - buffer + buffer_pos, - sign, - separator_, - false, // Don't parse as hex_float. - allow_trailing_junk, - junk_string_value_, - read_as_double, - &result_is_junk); - DOUBLE_CONVERSION_ASSERT(!result_is_junk); - *processed_characters_count = static_cast<int>(current - input); - return result; - } - - if (nonzero_digit_dropped) { - buffer[buffer_pos++] = '1'; - exponent--; - } - - DOUBLE_CONVERSION_ASSERT(buffer_pos < kBufferSize); - buffer[buffer_pos] = '\0'; - - double converted; - if (read_as_double) { - converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent); - } else { - converted = Strtof(Vector<const char>(buffer, buffer_pos), exponent); - } - *processed_characters_count = static_cast<int>(current - input); - return sign? -converted: converted; -} - - -double StringToDoubleConverter::StringToDouble( - const char* buffer, - int length, - int* processed_characters_count) const { - return StringToIeee(buffer, length, true, processed_characters_count); -} - - -double StringToDoubleConverter::StringToDouble( - const uc16* buffer, - int length, - int* processed_characters_count) const { - return StringToIeee(buffer, length, true, processed_characters_count); -} - - -float StringToDoubleConverter::StringToFloat( - const char* buffer, - int length, - int* processed_characters_count) const { - return static_cast<float>(StringToIeee(buffer, length, false, - processed_characters_count)); -} - - -float StringToDoubleConverter::StringToFloat( - const uc16* buffer, - int length, - int* processed_characters_count) const { - return static_cast<float>(StringToIeee(buffer, length, false, - processed_characters_count)); -} - -} // namespace double_conversion - -// ICU PATCH: Close ICU namespace -U_NAMESPACE_END -#endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING +// © 2018 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +// +// From the double-conversion library. Original license: +// +// Copyright 2010 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// ICU PATCH: ifdef around UCONFIG_NO_FORMATTING +#include "unicode/utypes.h" +#if !UCONFIG_NO_FORMATTING + +// ICU PATCH: Do not include std::locale. + +#include <climits> +// #include <locale> +#include <cmath> + +// ICU PATCH: Customize header file paths for ICU. + +#include "double-conversion-string-to-double.h" + +#include "double-conversion-ieee.h" +#include "double-conversion-strtod.h" +#include "double-conversion-utils.h" + +// ICU PATCH: Wrap in ICU namespace +U_NAMESPACE_BEGIN + +namespace double_conversion { + +namespace { + +inline char ToLower(char ch) { +#if 0 // do not include std::locale in ICU + static const std::ctype<char>& cType = + std::use_facet<std::ctype<char> >(std::locale::classic()); + return cType.tolower(ch); +#else + (void)ch; + DOUBLE_CONVERSION_UNREACHABLE(); +#endif +} + +inline char Pass(char ch) { + return ch; +} + +template <class Iterator, class Converter> +static inline bool ConsumeSubStringImpl(Iterator* current, + Iterator end, + const char* substring, + Converter converter) { + DOUBLE_CONVERSION_ASSERT(converter(**current) == *substring); + for (substring++; *substring != '\0'; substring++) { + ++*current; + if (*current == end || converter(**current) != *substring) { + return false; + } + } + ++*current; + return true; +} + +// Consumes the given substring from the iterator. +// Returns false, if the substring does not match. +template <class Iterator> +static bool ConsumeSubString(Iterator* current, + Iterator end, + const char* substring, + bool allow_case_insensitivity) { + if (allow_case_insensitivity) { + return ConsumeSubStringImpl(current, end, substring, ToLower); + } else { + return ConsumeSubStringImpl(current, end, substring, Pass); + } +} + +// Consumes first character of the str is equal to ch +inline bool ConsumeFirstCharacter(char ch, + const char* str, + bool case_insensitivity) { + return case_insensitivity ? ToLower(ch) == str[0] : ch == str[0]; +} +} // namespace + +// Maximum number of significant digits in decimal representation. +// The longest possible double in decimal representation is +// (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074 +// (768 digits). If we parse a number whose first digits are equal to a +// mean of 2 adjacent doubles (that could have up to 769 digits) the result +// must be rounded to the bigger one unless the tail consists of zeros, so +// we don't need to preserve all the digits. +const int kMaxSignificantDigits = 772; + + +static const char kWhitespaceTable7[] = { 32, 13, 10, 9, 11, 12 }; +static const int kWhitespaceTable7Length = DOUBLE_CONVERSION_ARRAY_SIZE(kWhitespaceTable7); + + +static const uc16 kWhitespaceTable16[] = { + 160, 8232, 8233, 5760, 6158, 8192, 8193, 8194, 8195, + 8196, 8197, 8198, 8199, 8200, 8201, 8202, 8239, 8287, 12288, 65279 +}; +static const int kWhitespaceTable16Length = DOUBLE_CONVERSION_ARRAY_SIZE(kWhitespaceTable16); + + +static bool isWhitespace(int x) { + if (x < 128) { + for (int i = 0; i < kWhitespaceTable7Length; i++) { + if (kWhitespaceTable7[i] == x) return true; + } + } else { + for (int i = 0; i < kWhitespaceTable16Length; i++) { + if (kWhitespaceTable16[i] == x) return true; + } + } + return false; +} + + +// Returns true if a nonspace found and false if the end has reached. +template <class Iterator> +static inline bool AdvanceToNonspace(Iterator* current, Iterator end) { + while (*current != end) { + if (!isWhitespace(**current)) return true; + ++*current; + } + return false; +} + + +static bool isDigit(int x, int radix) { + return (x >= '0' && x <= '9' && x < '0' + radix) + || (radix > 10 && x >= 'a' && x < 'a' + radix - 10) + || (radix > 10 && x >= 'A' && x < 'A' + radix - 10); +} + + +static double SignedZero(bool sign) { + return sign ? -0.0 : 0.0; +} + + +// Returns true if 'c' is a decimal digit that is valid for the given radix. +// +// The function is small and could be inlined, but VS2012 emitted a warning +// because it constant-propagated the radix and concluded that the last +// condition was always true. By moving it into a separate function the +// compiler wouldn't warn anymore. +#ifdef _MSC_VER +#pragma optimize("",off) +static bool IsDecimalDigitForRadix(int c, int radix) { + return '0' <= c && c <= '9' && (c - '0') < radix; +} +#pragma optimize("",on) +#else +static bool inline IsDecimalDigitForRadix(int c, int radix) { + return '0' <= c && c <= '9' && (c - '0') < radix; +} +#endif +// Returns true if 'c' is a character digit that is valid for the given radix. +// The 'a_character' should be 'a' or 'A'. +// +// The function is small and could be inlined, but VS2012 emitted a warning +// because it constant-propagated the radix and concluded that the first +// condition was always false. By moving it into a separate function the +// compiler wouldn't warn anymore. +static bool IsCharacterDigitForRadix(int c, int radix, char a_character) { + return radix > 10 && c >= a_character && c < a_character + radix - 10; +} + +// Returns true, when the iterator is equal to end. +template<class Iterator> +static bool Advance (Iterator* it, uc16 separator, int base, Iterator& end) { + if (separator == StringToDoubleConverter::kNoSeparator) { + ++(*it); + return *it == end; + } + if (!isDigit(**it, base)) { + ++(*it); + return *it == end; + } + ++(*it); + if (*it == end) return true; + if (*it + 1 == end) return false; + if (**it == separator && isDigit(*(*it + 1), base)) { + ++(*it); + } + return *it == end; +} + +// Checks whether the string in the range start-end is a hex-float string. +// This function assumes that the leading '0x'/'0X' is already consumed. +// +// Hex float strings are of one of the following forms: +// - hex_digits+ 'p' ('+'|'-')? exponent_digits+ +// - hex_digits* '.' hex_digits+ 'p' ('+'|'-')? exponent_digits+ +// - hex_digits+ '.' 'p' ('+'|'-')? exponent_digits+ +template<class Iterator> +static bool IsHexFloatString(Iterator start, + Iterator end, + uc16 separator, + bool allow_trailing_junk) { + DOUBLE_CONVERSION_ASSERT(start != end); + + Iterator current = start; + + bool saw_digit = false; + while (isDigit(*current, 16)) { + saw_digit = true; + if (Advance(¤t, separator, 16, end)) return false; + } + if (*current == '.') { + if (Advance(¤t, separator, 16, end)) return false; + while (isDigit(*current, 16)) { + saw_digit = true; + if (Advance(¤t, separator, 16, end)) return false; + } + } + if (!saw_digit) return false; + if (*current != 'p' && *current != 'P') return false; + if (Advance(¤t, separator, 16, end)) return false; + if (*current == '+' || *current == '-') { + if (Advance(¤t, separator, 16, end)) return false; + } + if (!isDigit(*current, 10)) return false; + if (Advance(¤t, separator, 16, end)) return true; + while (isDigit(*current, 10)) { + if (Advance(¤t, separator, 16, end)) return true; + } + return allow_trailing_junk || !AdvanceToNonspace(¤t, end); +} + + +// Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end. +// +// If parse_as_hex_float is true, then the string must be a valid +// hex-float. +template <int radix_log_2, class Iterator> +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) { + DOUBLE_CONVERSION_ASSERT(*current != end); + DOUBLE_CONVERSION_ASSERT(!parse_as_hex_float || + IsHexFloatString(*current, end, separator, allow_trailing_junk)); + + const int kDoubleSize = Double::kSignificandSize; + const int kSingleSize = Single::kSignificandSize; + const int kSignificandSize = read_as_double? kDoubleSize: kSingleSize; + + *result_is_junk = true; + + int64_t number = 0; + int exponent = 0; + const int radix = (1 << radix_log_2); + // Whether we have encountered a '.' and are parsing the decimal digits. + // Only relevant if parse_as_hex_float is true. + bool post_decimal = false; + + // Skip leading 0s. + while (**current == '0') { + if (Advance(current, separator, radix, end)) { + *result_is_junk = false; + return SignedZero(sign); + } + } + + while (true) { + int digit; + if (IsDecimalDigitForRadix(**current, radix)) { + digit = static_cast<char>(**current) - '0'; + if (post_decimal) exponent -= radix_log_2; + } else if (IsCharacterDigitForRadix(**current, radix, 'a')) { + digit = static_cast<char>(**current) - 'a' + 10; + if (post_decimal) exponent -= radix_log_2; + } else if (IsCharacterDigitForRadix(**current, radix, 'A')) { + digit = static_cast<char>(**current) - 'A' + 10; + if (post_decimal) exponent -= radix_log_2; + } else if (parse_as_hex_float && **current == '.') { + post_decimal = true; + Advance(current, separator, radix, end); + DOUBLE_CONVERSION_ASSERT(*current != end); + continue; + } else if (parse_as_hex_float && (**current == 'p' || **current == 'P')) { + break; + } else { + if (allow_trailing_junk || !AdvanceToNonspace(current, end)) { + break; + } else { + return junk_string_value; + } + } + + number = number * radix + digit; + int overflow = static_cast<int>(number >> kSignificandSize); + if (overflow != 0) { + // Overflow occurred. Need to determine which direction to round the + // result. + int overflow_bits_count = 1; + while (overflow > 1) { + overflow_bits_count++; + overflow >>= 1; + } + + int dropped_bits_mask = ((1 << overflow_bits_count) - 1); + int dropped_bits = static_cast<int>(number) & dropped_bits_mask; + number >>= overflow_bits_count; + exponent += overflow_bits_count; + + bool zero_tail = true; + for (;;) { + if (Advance(current, separator, radix, end)) break; + if (parse_as_hex_float && **current == '.') { + // Just run over the '.'. We are just trying to see whether there is + // a non-zero digit somewhere. + Advance(current, separator, radix, end); + DOUBLE_CONVERSION_ASSERT(*current != end); + post_decimal = true; + } + if (!isDigit(**current, radix)) break; + zero_tail = zero_tail && **current == '0'; + if (!post_decimal) exponent += radix_log_2; + } + + if (!parse_as_hex_float && + !allow_trailing_junk && + AdvanceToNonspace(current, end)) { + return junk_string_value; + } + + int middle_value = (1 << (overflow_bits_count - 1)); + if (dropped_bits > middle_value) { + number++; // Rounding up. + } else if (dropped_bits == middle_value) { + // Rounding to even to consistency with decimals: half-way case rounds + // up if significant part is odd and down otherwise. + if ((number & 1) != 0 || !zero_tail) { + number++; // Rounding up. + } + } + + // Rounding up may cause overflow. + if ((number & ((int64_t)1 << kSignificandSize)) != 0) { + exponent++; + number >>= 1; + } + break; + } + if (Advance(current, separator, radix, end)) break; + } + + DOUBLE_CONVERSION_ASSERT(number < ((int64_t)1 << kSignificandSize)); + DOUBLE_CONVERSION_ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number); + + *result_is_junk = false; + + if (parse_as_hex_float) { + DOUBLE_CONVERSION_ASSERT(**current == 'p' || **current == 'P'); + Advance(current, separator, radix, end); + DOUBLE_CONVERSION_ASSERT(*current != end); + bool is_negative = false; + if (**current == '+') { + Advance(current, separator, radix, end); + DOUBLE_CONVERSION_ASSERT(*current != end); + } else if (**current == '-') { + is_negative = true; + Advance(current, separator, radix, end); + DOUBLE_CONVERSION_ASSERT(*current != end); + } + int written_exponent = 0; + while (IsDecimalDigitForRadix(**current, 10)) { + // No need to read exponents if they are too big. That could potentially overflow + // the `written_exponent` variable. + if (abs(written_exponent) <= 100 * Double::kMaxExponent) { + written_exponent = 10 * written_exponent + **current - '0'; + } + if (Advance(current, separator, radix, end)) break; + } + if (is_negative) written_exponent = -written_exponent; + exponent += written_exponent; + } + + if (exponent == 0 || number == 0) { + if (sign) { + if (number == 0) return -0.0; + number = -number; + } + return static_cast<double>(number); + } + + DOUBLE_CONVERSION_ASSERT(number != 0); + double result = Double(DiyFp(number, exponent)).value(); + return sign ? -result : result; +} + +template <class Iterator> +double StringToDoubleConverter::StringToIeee( + Iterator input, + int length, + bool read_as_double, + int* processed_characters_count) const { + Iterator current = input; + Iterator end = input + length; + + *processed_characters_count = 0; + + const bool allow_trailing_junk = (flags_ & ALLOW_TRAILING_JUNK) != 0; + const bool allow_leading_spaces = (flags_ & ALLOW_LEADING_SPACES) != 0; + const bool allow_trailing_spaces = (flags_ & ALLOW_TRAILING_SPACES) != 0; + const bool allow_spaces_after_sign = (flags_ & ALLOW_SPACES_AFTER_SIGN) != 0; + const bool allow_case_insensitivity = (flags_ & ALLOW_CASE_INSENSITIVITY) != 0; + + // To make sure that iterator dereferencing is valid the following + // convention is used: + // 1. Each '++current' statement is followed by check for equality to 'end'. + // 2. If AdvanceToNonspace returned false then current == end. + // 3. If 'current' becomes equal to 'end' the function returns or goes to + // 'parsing_done'. + // 4. 'current' is not dereferenced after the 'parsing_done' label. + // 5. Code before 'parsing_done' may rely on 'current != end'. + if (current == end) return empty_string_value_; + + if (allow_leading_spaces || allow_trailing_spaces) { + if (!AdvanceToNonspace(¤t, end)) { + *processed_characters_count = static_cast<int>(current - input); + return empty_string_value_; + } + if (!allow_leading_spaces && (input != current)) { + // No leading spaces allowed, but AdvanceToNonspace moved forward. + return junk_string_value_; + } + } + + // Exponent will be adjusted if insignificant digits of the integer part + // or insignificant leading zeros of the fractional part are dropped. + int exponent = 0; + int significant_digits = 0; + int insignificant_digits = 0; + bool nonzero_digit_dropped = false; + + bool sign = false; + + if (*current == '+' || *current == '-') { + sign = (*current == '-'); + ++current; + Iterator next_non_space = current; + // Skip following spaces (if allowed). + if (!AdvanceToNonspace(&next_non_space, end)) return junk_string_value_; + if (!allow_spaces_after_sign && (current != next_non_space)) { + return junk_string_value_; + } + current = next_non_space; + } + + if (infinity_symbol_ != NULL) { + if (ConsumeFirstCharacter(*current, infinity_symbol_, allow_case_insensitivity)) { + if (!ConsumeSubString(¤t, end, infinity_symbol_, allow_case_insensitivity)) { + return junk_string_value_; + } + + if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) { + return junk_string_value_; + } + if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { + return junk_string_value_; + } + + *processed_characters_count = static_cast<int>(current - input); + return sign ? -Double::Infinity() : Double::Infinity(); + } + } + + if (nan_symbol_ != NULL) { + if (ConsumeFirstCharacter(*current, nan_symbol_, allow_case_insensitivity)) { + if (!ConsumeSubString(¤t, end, nan_symbol_, allow_case_insensitivity)) { + return junk_string_value_; + } + + if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) { + return junk_string_value_; + } + if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { + return junk_string_value_; + } + + *processed_characters_count = static_cast<int>(current - input); + return sign ? -Double::NaN() : Double::NaN(); + } + } + + bool leading_zero = false; + if (*current == '0') { + if (Advance(¤t, separator_, 10, end)) { + *processed_characters_count = static_cast<int>(current - input); + return SignedZero(sign); + } + + leading_zero = true; + + // It could be hexadecimal value. + if (((flags_ & ALLOW_HEX) || (flags_ & ALLOW_HEX_FLOATS)) && + (*current == 'x' || *current == 'X')) { + ++current; + + if (current == end) return junk_string_value_; // "0x" + + bool parse_as_hex_float = (flags_ & ALLOW_HEX_FLOATS) && + IsHexFloatString(current, end, separator_, allow_trailing_junk); + + if (!parse_as_hex_float && !isDigit(*current, 16)) { + return junk_string_value_; + } + + bool result_is_junk; + double result = RadixStringToIeee<4>(¤t, + end, + sign, + separator_, + parse_as_hex_float, + allow_trailing_junk, + junk_string_value_, + read_as_double, + &result_is_junk); + if (!result_is_junk) { + if (allow_trailing_spaces) AdvanceToNonspace(¤t, end); + *processed_characters_count = static_cast<int>(current - input); + } + return result; + } + + // Ignore leading zeros in the integer part. + while (*current == '0') { + if (Advance(¤t, separator_, 10, end)) { + *processed_characters_count = static_cast<int>(current - input); + return SignedZero(sign); + } + } + } + + bool octal = leading_zero && (flags_ & ALLOW_OCTALS) != 0; + + // The longest form of simplified number is: "-<significant digits>.1eXXX\0". + const int kBufferSize = kMaxSignificantDigits + 10; + DOUBLE_CONVERSION_STACK_UNINITIALIZED char + buffer[kBufferSize]; // NOLINT: size is known at compile time. + int buffer_pos = 0; + + // Copy significant digits of the integer part (if any) to the buffer. + while (*current >= '0' && *current <= '9') { + if (significant_digits < kMaxSignificantDigits) { + DOUBLE_CONVERSION_ASSERT(buffer_pos < kBufferSize); + buffer[buffer_pos++] = static_cast<char>(*current); + significant_digits++; + // Will later check if it's an octal in the buffer. + } else { + insignificant_digits++; // Move the digit into the exponential part. + nonzero_digit_dropped = nonzero_digit_dropped || *current != '0'; + } + octal = octal && *current < '8'; + if (Advance(¤t, separator_, 10, end)) goto parsing_done; + } + + if (significant_digits == 0) { + octal = false; + } + + if (*current == '.') { + if (octal && !allow_trailing_junk) return junk_string_value_; + if (octal) goto parsing_done; + + if (Advance(¤t, separator_, 10, end)) { + if (significant_digits == 0 && !leading_zero) { + return junk_string_value_; + } else { + goto parsing_done; + } + } + + if (significant_digits == 0) { + // octal = false; + // Integer part consists of 0 or is absent. Significant digits start after + // leading zeros (if any). + while (*current == '0') { + if (Advance(¤t, separator_, 10, end)) { + *processed_characters_count = static_cast<int>(current - input); + return SignedZero(sign); + } + exponent--; // Move this 0 into the exponent. + } + } + + // There is a fractional part. + // We don't emit a '.', but adjust the exponent instead. + while (*current >= '0' && *current <= '9') { + if (significant_digits < kMaxSignificantDigits) { + DOUBLE_CONVERSION_ASSERT(buffer_pos < kBufferSize); + buffer[buffer_pos++] = static_cast<char>(*current); + significant_digits++; + exponent--; + } else { + // Ignore insignificant digits in the fractional part. + nonzero_digit_dropped = nonzero_digit_dropped || *current != '0'; + } + if (Advance(¤t, separator_, 10, end)) goto parsing_done; + } + } + + if (!leading_zero && exponent == 0 && significant_digits == 0) { + // If leading_zeros is true then the string contains zeros. + // If exponent < 0 then string was [+-]\.0*... + // If significant_digits != 0 the string is not equal to 0. + // Otherwise there are no digits in the string. + return junk_string_value_; + } + + // Parse exponential part. + if (*current == 'e' || *current == 'E') { + if (octal && !allow_trailing_junk) return junk_string_value_; + if (octal) goto parsing_done; + Iterator junk_begin = current; + ++current; + if (current == end) { + if (allow_trailing_junk) { + current = junk_begin; + goto parsing_done; + } else { + return junk_string_value_; + } + } + char exponen_sign = '+'; + if (*current == '+' || *current == '-') { + exponen_sign = static_cast<char>(*current); + ++current; + if (current == end) { + if (allow_trailing_junk) { + current = junk_begin; + goto parsing_done; + } else { + return junk_string_value_; + } + } + } + + if (current == end || *current < '0' || *current > '9') { + if (allow_trailing_junk) { + current = junk_begin; + goto parsing_done; + } else { + return junk_string_value_; + } + } + + const int max_exponent = INT_MAX / 2; + DOUBLE_CONVERSION_ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2); + int num = 0; + do { + // Check overflow. + int digit = *current - '0'; + if (num >= max_exponent / 10 + && !(num == max_exponent / 10 && digit <= max_exponent % 10)) { + num = max_exponent; + } else { + num = num * 10 + digit; + } + ++current; + } while (current != end && *current >= '0' && *current <= '9'); + + exponent += (exponen_sign == '-' ? -num : num); + } + + if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) { + return junk_string_value_; + } + if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { + return junk_string_value_; + } + if (allow_trailing_spaces) { + AdvanceToNonspace(¤t, end); + } + + parsing_done: + exponent += insignificant_digits; + + if (octal) { + double result; + bool result_is_junk; + char* start = buffer; + result = RadixStringToIeee<3>(&start, + buffer + buffer_pos, + sign, + separator_, + false, // Don't parse as hex_float. + allow_trailing_junk, + junk_string_value_, + read_as_double, + &result_is_junk); + DOUBLE_CONVERSION_ASSERT(!result_is_junk); + *processed_characters_count = static_cast<int>(current - input); + return result; + } + + if (nonzero_digit_dropped) { + buffer[buffer_pos++] = '1'; + exponent--; + } + + DOUBLE_CONVERSION_ASSERT(buffer_pos < kBufferSize); + buffer[buffer_pos] = '\0'; + + double converted; + if (read_as_double) { + converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent); + } else { + converted = Strtof(Vector<const char>(buffer, buffer_pos), exponent); + } + *processed_characters_count = static_cast<int>(current - input); + return sign? -converted: converted; +} + + +double StringToDoubleConverter::StringToDouble( + const char* buffer, + int length, + int* processed_characters_count) const { + return StringToIeee(buffer, length, true, processed_characters_count); +} + + +double StringToDoubleConverter::StringToDouble( + const uc16* buffer, + int length, + int* processed_characters_count) const { + return StringToIeee(buffer, length, true, processed_characters_count); +} + + +float StringToDoubleConverter::StringToFloat( + const char* buffer, + int length, + int* processed_characters_count) const { + return static_cast<float>(StringToIeee(buffer, length, false, + processed_characters_count)); +} + + +float StringToDoubleConverter::StringToFloat( + const uc16* buffer, + int length, + int* processed_characters_count) const { + return static_cast<float>(StringToIeee(buffer, length, false, + processed_characters_count)); +} + +} // namespace double_conversion + +// ICU PATCH: Close ICU namespace +U_NAMESPACE_END +#endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING |