|
|
@ -25,17 +25,18 @@ |
|
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
|
|
|
#include <limits.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <climits>
|
|
|
|
#include <locale>
|
|
|
|
#include <cmath>
|
|
|
|
|
|
|
|
#include "double-conversion/double-conversion.h"
|
|
|
|
#include "double-conversion.h"
|
|
|
|
|
|
|
|
#include "double-conversion/bignum-dtoa.h"
|
|
|
|
#include "double-conversion/fast-dtoa.h"
|
|
|
|
#include "double-conversion/fixed-dtoa.h"
|
|
|
|
#include "double-conversion/ieee.h"
|
|
|
|
#include "double-conversion/strtod.h"
|
|
|
|
#include "double-conversion/utils.h"
|
|
|
|
#include "bignum-dtoa.h"
|
|
|
|
#include "fast-dtoa.h"
|
|
|
|
#include "fixed-dtoa.h"
|
|
|
|
#include "ieee.h"
|
|
|
|
#include "strtod.h"
|
|
|
|
#include "utils.h"
|
|
|
|
|
|
|
|
namespace double_conversion { |
|
|
|
|
|
|
@ -118,7 +119,7 @@ void DoubleToStringConverter::CreateDecimalRepresentation( |
|
|
|
StringBuilder* result_builder) const { |
|
|
|
// Create a representation that is padded with zeros if needed.
|
|
|
|
if (decimal_point <= 0) { |
|
|
|
// "0.00000decimal_rep".
|
|
|
|
// "0.00000decimal_rep" or "0.000decimal_rep00".
|
|
|
|
result_builder->AddCharacter('0'); |
|
|
|
if (digits_after_point > 0) { |
|
|
|
result_builder->AddCharacter('.'); |
|
|
@ -129,7 +130,7 @@ void DoubleToStringConverter::CreateDecimalRepresentation( |
|
|
|
result_builder->AddPadding('0', remaining_digits); |
|
|
|
} |
|
|
|
} else if (decimal_point >= length) { |
|
|
|
// "decimal_rep0000.00000" or "decimal_rep.0000"
|
|
|
|
// "decimal_rep0000.00000" or "decimal_rep.0000".
|
|
|
|
result_builder->AddSubstring(decimal_digits, length); |
|
|
|
result_builder->AddPadding('0', decimal_point - length); |
|
|
|
if (digits_after_point > 0) { |
|
|
@ -137,7 +138,7 @@ void DoubleToStringConverter::CreateDecimalRepresentation( |
|
|
|
result_builder->AddPadding('0', digits_after_point); |
|
|
|
} |
|
|
|
} else { |
|
|
|
// "decima.l_rep000"
|
|
|
|
// "decima.l_rep000".
|
|
|
|
ASSERT(digits_after_point > 0); |
|
|
|
result_builder->AddSubstring(decimal_digits, decimal_point); |
|
|
|
result_builder->AddCharacter('.'); |
|
|
@ -249,6 +250,12 @@ bool DoubleToStringConverter::ToExponential( |
|
|
|
const int kDecimalRepCapacity = kMaxExponentialDigits + 2; |
|
|
|
ASSERT(kDecimalRepCapacity > kBase10MaximalLength); |
|
|
|
char decimal_rep[kDecimalRepCapacity]; |
|
|
|
#ifndef NDEBUG
|
|
|
|
// Problem: there is an assert in StringBuilder::AddSubstring() that
|
|
|
|
// will pass this buffer to strlen(), and this buffer is not generally
|
|
|
|
// null-terminated.
|
|
|
|
memset(decimal_rep, 0, sizeof(decimal_rep)); |
|
|
|
#endif
|
|
|
|
int decimal_rep_length; |
|
|
|
|
|
|
|
if (requested_digits == -1) { |
|
|
@ -414,21 +421,55 @@ void DoubleToStringConverter::DoubleToAscii(double v, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
namespace { |
|
|
|
|
|
|
|
inline char ToLower(char ch) { |
|
|
|
static const std::ctype<char>& cType = |
|
|
|
std::use_facet<std::ctype<char> >(std::locale::classic()); |
|
|
|
return cType.tolower(ch); |
|
|
|
} |
|
|
|
|
|
|
|
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) { |
|
|
|
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) { |
|
|
|
ASSERT(**current == *substring); |
|
|
|
for (substring++; *substring != '\0'; substring++) { |
|
|
|
++*current; |
|
|
|
if (*current == end || **current != *substring) return false; |
|
|
|
const char* substring, |
|
|
|
bool allow_case_insensibility) { |
|
|
|
if (allow_case_insensibility) { |
|
|
|
return ConsumeSubStringImpl(current, end, substring, ToLower); |
|
|
|
} else { |
|
|
|
return ConsumeSubStringImpl(current, end, substring, Pass); |
|
|
|
} |
|
|
|
++*current; |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
// Consumes first character of the str is equal to ch
|
|
|
|
inline bool ConsumeFirstCharacter(char ch, |
|
|
|
const char* str, |
|
|
|
bool case_insensibility) { |
|
|
|
return case_insensibility ? ToLower(ch) == str[0] : ch == str[0]; |
|
|
|
} |
|
|
|
} // namespace
|
|
|
|
|
|
|
|
// Maximum number of significant digits in decimal representation.
|
|
|
|
// The longest possible double in decimal representation is
|
|
|
@ -494,7 +535,7 @@ static double SignedZero(bool sign) { |
|
|
|
// 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.
|
|
|
|
#if _MSC_VER
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
#pragma optimize("",off)
|
|
|
|
static bool IsDecimalDigitForRadix(int c, int radix) { |
|
|
|
return '0' <= c && c <= '9' && (c - '0') < radix; |
|
|
@ -502,7 +543,7 @@ static bool IsDecimalDigitForRadix(int c, int radix) { |
|
|
|
#pragma optimize("",on)
|
|
|
|
#else
|
|
|
|
static bool inline IsDecimalDigitForRadix(int c, int radix) { |
|
|
|
return '0' <= c && c <= '9' && (c - '0') < 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.
|
|
|
@ -516,17 +557,86 @@ 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) { |
|
|
|
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; // Only the '.', but no digits.
|
|
|
|
} |
|
|
|
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) { |
|
|
|
ASSERT(*current != end); |
|
|
|
ASSERT(!parse_as_hex_float || |
|
|
|
IsHexFloatString(*current, end, separator, allow_trailing_junk)); |
|
|
|
|
|
|
|
const int kDoubleSize = Double::kSignificandSize; |
|
|
|
const int kSingleSize = Single::kSignificandSize; |
|
|
@ -534,27 +644,39 @@ static double RadixStringToIeee(Iterator* current, |
|
|
|
|
|
|
|
*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') { |
|
|
|
++(*current); |
|
|
|
if (*current == end) { |
|
|
|
if (Advance(current, separator, radix, end)) { |
|
|
|
*result_is_junk = false; |
|
|
|
return SignedZero(sign); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
int64_t number = 0; |
|
|
|
int exponent = 0; |
|
|
|
const int radix = (1 << radix_log_2); |
|
|
|
|
|
|
|
do { |
|
|
|
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); |
|
|
|
ASSERT(*current != end); |
|
|
|
continue; |
|
|
|
} else if (parse_as_hex_float && (**current == 'p' || **current == 'P')) { |
|
|
|
break; |
|
|
|
} else { |
|
|
|
if (allow_trailing_junk || !AdvanceToNonspace(current, end)) { |
|
|
|
break; |
|
|
@ -577,17 +699,26 @@ static double RadixStringToIeee(Iterator* current, |
|
|
|
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; |
|
|
|
exponent += overflow_bits_count; |
|
|
|
|
|
|
|
bool zero_tail = true; |
|
|
|
for (;;) { |
|
|
|
++(*current); |
|
|
|
if (*current == end || !isDigit(**current, radix)) break; |
|
|
|
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); |
|
|
|
ASSERT(*current != end); |
|
|
|
post_decimal = true; |
|
|
|
} |
|
|
|
if (!isDigit(**current, radix)) break; |
|
|
|
zero_tail = zero_tail && **current == '0'; |
|
|
|
exponent += radix_log_2; |
|
|
|
if (!post_decimal) exponent += radix_log_2; |
|
|
|
} |
|
|
|
|
|
|
|
if (!allow_trailing_junk && AdvanceToNonspace(current, end)) { |
|
|
|
if (!parse_as_hex_float && |
|
|
|
!allow_trailing_junk && |
|
|
|
AdvanceToNonspace(current, end)) { |
|
|
|
return junk_string_value; |
|
|
|
} |
|
|
|
|
|
|
@ -609,15 +740,37 @@ static double RadixStringToIeee(Iterator* current, |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
++(*current); |
|
|
|
} while (*current != end); |
|
|
|
if (Advance(current, separator, radix, end)) break; |
|
|
|
} |
|
|
|
|
|
|
|
ASSERT(number < ((int64_t)1 << kSignificandSize)); |
|
|
|
ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number); |
|
|
|
|
|
|
|
*result_is_junk = false; |
|
|
|
|
|
|
|
if (exponent == 0) { |
|
|
|
if (parse_as_hex_float) { |
|
|
|
ASSERT(**current == 'p' || **current == 'P'); |
|
|
|
Advance(current, separator, radix, end); |
|
|
|
ASSERT(*current != end); |
|
|
|
bool is_negative = false; |
|
|
|
if (**current == '+') { |
|
|
|
Advance(current, separator, radix, end); |
|
|
|
ASSERT(*current != end); |
|
|
|
} else if (**current == '-') { |
|
|
|
is_negative = true; |
|
|
|
Advance(current, separator, radix, end); |
|
|
|
ASSERT(*current != end); |
|
|
|
} |
|
|
|
int written_exponent = 0; |
|
|
|
while (IsDecimalDigitForRadix(**current, 10)) { |
|
|
|
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; |
|
|
@ -626,10 +779,10 @@ static double RadixStringToIeee(Iterator* current, |
|
|
|
} |
|
|
|
|
|
|
|
ASSERT(number != 0); |
|
|
|
return Double(DiyFp(number, exponent)).value(); |
|
|
|
double result = Double(DiyFp(number, exponent)).value(); |
|
|
|
return sign ? -result : result; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template <class Iterator> |
|
|
|
double StringToDoubleConverter::StringToIeee( |
|
|
|
Iterator input, |
|
|
@ -645,6 +798,7 @@ double StringToDoubleConverter::StringToIeee( |
|
|
|
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_insensibility = (flags_ & ALLOW_CASE_INSENSIBILITY) != 0; |
|
|
|
|
|
|
|
// To make sure that iterator dereferencing is valid the following
|
|
|
|
// convention is used:
|
|
|
@ -694,8 +848,8 @@ double StringToDoubleConverter::StringToIeee( |
|
|
|
} |
|
|
|
|
|
|
|
if (infinity_symbol_ != NULL) { |
|
|
|
if (*current == infinity_symbol_[0]) { |
|
|
|
if (!ConsumeSubString(¤t, end, infinity_symbol_)) { |
|
|
|
if (ConsumeFirstCharacter(*current, infinity_symbol_, allow_case_insensibility)) { |
|
|
|
if (!ConsumeSubString(¤t, end, infinity_symbol_, allow_case_insensibility)) { |
|
|
|
return junk_string_value_; |
|
|
|
} |
|
|
|
|
|
|
@ -713,8 +867,8 @@ double StringToDoubleConverter::StringToIeee( |
|
|
|
} |
|
|
|
|
|
|
|
if (nan_symbol_ != NULL) { |
|
|
|
if (*current == nan_symbol_[0]) { |
|
|
|
if (!ConsumeSubString(¤t, end, nan_symbol_)) { |
|
|
|
if (ConsumeFirstCharacter(*current, nan_symbol_, allow_case_insensibility)) { |
|
|
|
if (!ConsumeSubString(¤t, end, nan_symbol_, allow_case_insensibility)) { |
|
|
|
return junk_string_value_; |
|
|
|
} |
|
|
|
|
|
|
@ -733,8 +887,7 @@ double StringToDoubleConverter::StringToIeee( |
|
|
|
|
|
|
|
bool leading_zero = false; |
|
|
|
if (*current == '0') { |
|
|
|
++current; |
|
|
|
if (current == end) { |
|
|
|
if (Advance(¤t, separator_, 10, end)) { |
|
|
|
*processed_characters_count = static_cast<int>(current - input); |
|
|
|
return SignedZero(sign); |
|
|
|
} |
|
|
@ -742,16 +895,24 @@ double StringToDoubleConverter::StringToIeee( |
|
|
|
leading_zero = true; |
|
|
|
|
|
|
|
// It could be hexadecimal value.
|
|
|
|
if ((flags_ & ALLOW_HEX) && (*current == 'x' || *current == 'X')) { |
|
|
|
if (((flags_ & ALLOW_HEX) || (flags_ & ALLOW_HEX_FLOATS)) && |
|
|
|
(*current == 'x' || *current == 'X')) { |
|
|
|
++current; |
|
|
|
if (current == end || !isDigit(*current, 16)) { |
|
|
|
return junk_string_value_; // "0x".
|
|
|
|
|
|
|
|
bool parse_as_hex_float = (flags_ & ALLOW_HEX_FLOATS) && |
|
|
|
IsHexFloatString(current, end, separator_, allow_trailing_junk); |
|
|
|
|
|
|
|
if (current == end) return junk_string_value_; // "0x"
|
|
|
|
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, |
|
|
@ -765,8 +926,7 @@ double StringToDoubleConverter::StringToIeee( |
|
|
|
|
|
|
|
// Ignore leading zeros in the integer part.
|
|
|
|
while (*current == '0') { |
|
|
|
++current; |
|
|
|
if (current == end) { |
|
|
|
if (Advance(¤t, separator_, 10, end)) { |
|
|
|
*processed_characters_count = static_cast<int>(current - input); |
|
|
|
return SignedZero(sign); |
|
|
|
} |
|
|
@ -787,8 +947,7 @@ double StringToDoubleConverter::StringToIeee( |
|
|
|
nonzero_digit_dropped = nonzero_digit_dropped || *current != '0'; |
|
|
|
} |
|
|
|
octal = octal && *current < '8'; |
|
|
|
++current; |
|
|
|
if (current == end) goto parsing_done; |
|
|
|
if (Advance(¤t, separator_, 10, end)) goto parsing_done; |
|
|
|
} |
|
|
|
|
|
|
|
if (significant_digits == 0) { |
|
|
@ -799,8 +958,7 @@ double StringToDoubleConverter::StringToIeee( |
|
|
|
if (octal && !allow_trailing_junk) return junk_string_value_; |
|
|
|
if (octal) goto parsing_done; |
|
|
|
|
|
|
|
++current; |
|
|
|
if (current == end) { |
|
|
|
if (Advance(¤t, separator_, 10, end)) { |
|
|
|
if (significant_digits == 0 && !leading_zero) { |
|
|
|
return junk_string_value_; |
|
|
|
} else { |
|
|
@ -813,8 +971,7 @@ double StringToDoubleConverter::StringToIeee( |
|
|
|
// Integer part consists of 0 or is absent. Significant digits start after
|
|
|
|
// leading zeros (if any).
|
|
|
|
while (*current == '0') { |
|
|
|
++current; |
|
|
|
if (current == end) { |
|
|
|
if (Advance(¤t, separator_, 10, end)) { |
|
|
|
*processed_characters_count = static_cast<int>(current - input); |
|
|
|
return SignedZero(sign); |
|
|
|
} |
|
|
@ -834,8 +991,7 @@ double StringToDoubleConverter::StringToIeee( |
|
|
|
// Ignore insignificant digits in the fractional part.
|
|
|
|
nonzero_digit_dropped = nonzero_digit_dropped || *current != '0'; |
|
|
|
} |
|
|
|
++current; |
|
|
|
if (current == end) goto parsing_done; |
|
|
|
if (Advance(¤t, separator_, 10, end)) goto parsing_done; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -851,9 +1007,11 @@ double StringToDoubleConverter::StringToIeee( |
|
|
|
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_; |
|
|
@ -865,6 +1023,7 @@ double StringToDoubleConverter::StringToIeee( |
|
|
|
++current; |
|
|
|
if (current == end) { |
|
|
|
if (allow_trailing_junk) { |
|
|
|
current = junk_begin; |
|
|
|
goto parsing_done; |
|
|
|
} else { |
|
|
|
return junk_string_value_; |
|
|
@ -874,6 +1033,7 @@ double StringToDoubleConverter::StringToIeee( |
|
|
|
|
|
|
|
if (current == end || *current < '0' || *current > '9') { |
|
|
|
if (allow_trailing_junk) { |
|
|
|
current = junk_begin; |
|
|
|
goto parsing_done; |
|
|
|
} else { |
|
|
|
return junk_string_value_; |
|
|
@ -918,6 +1078,8 @@ double StringToDoubleConverter::StringToIeee( |
|
|
|
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, |
|
|
|