ICU-20438 Updating double-conversion from upstream master.
This commit is contained in:
parent
f3be3a9ae5
commit
93178a836c
@ -34,7 +34,7 @@
|
||||
#include "unicode/utypes.h"
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
|
||||
#include <math.h>
|
||||
#include <cmath>
|
||||
|
||||
// ICU PATCH: Customize header file paths for ICU.
|
||||
|
||||
|
@ -45,7 +45,7 @@ U_NAMESPACE_BEGIN
|
||||
namespace double_conversion {
|
||||
|
||||
Bignum::Bignum()
|
||||
: bigits_(bigits_buffer_, kBigitCapacity), used_digits_(0), exponent_(0) {
|
||||
: bigits_buffer_(), bigits_(bigits_buffer_, kBigitCapacity), used_digits_(0), exponent_(0) {
|
||||
for (int i = 0; i < kBigitCapacity; ++i) {
|
||||
bigits_[i] = 0;
|
||||
}
|
||||
@ -459,26 +459,27 @@ void Bignum::AssignPowerUInt16(uint16_t base, int power_exponent) {
|
||||
mask >>= 2;
|
||||
uint64_t this_value = base;
|
||||
|
||||
bool delayed_multipliciation = false;
|
||||
bool delayed_multiplication = false;
|
||||
const uint64_t max_32bits = 0xFFFFFFFF;
|
||||
while (mask != 0 && this_value <= max_32bits) {
|
||||
this_value = this_value * this_value;
|
||||
// Verify that there is enough space in this_value to perform the
|
||||
// multiplication. The first bit_size bits must be 0.
|
||||
if ((power_exponent & mask) != 0) {
|
||||
ASSERT(bit_size > 0);
|
||||
uint64_t base_bits_mask =
|
||||
~((static_cast<uint64_t>(1) << (64 - bit_size)) - 1);
|
||||
bool high_bits_zero = (this_value & base_bits_mask) == 0;
|
||||
if (high_bits_zero) {
|
||||
this_value *= base;
|
||||
} else {
|
||||
delayed_multipliciation = true;
|
||||
delayed_multiplication = true;
|
||||
}
|
||||
}
|
||||
mask >>= 1;
|
||||
}
|
||||
AssignUInt64(this_value);
|
||||
if (delayed_multipliciation) {
|
||||
if (delayed_multiplication) {
|
||||
MultiplyByUInt32(base);
|
||||
}
|
||||
|
||||
|
@ -150,7 +150,7 @@ class Bignum {
|
||||
// The Bignum's value equals value(bigits_) * 2^(exponent_ * kBigitSize).
|
||||
int exponent_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Bignum);
|
||||
DC_DISALLOW_COPY_AND_ASSIGN(Bignum);
|
||||
};
|
||||
|
||||
} // namespace double_conversion
|
||||
|
@ -34,9 +34,9 @@
|
||||
#include "unicode/utypes.h"
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <climits>
|
||||
#include <cmath>
|
||||
#include <cstdarg>
|
||||
|
||||
// ICU PATCH: Customize header file paths for ICU.
|
||||
|
||||
|
@ -271,7 +271,7 @@ class Double {
|
||||
(biased_exponent << kPhysicalSignificandSize);
|
||||
}
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Double);
|
||||
DC_DISALLOW_COPY_AND_ASSIGN(Double);
|
||||
};
|
||||
|
||||
class Single {
|
||||
@ -408,7 +408,7 @@ class Single {
|
||||
|
||||
const uint32_t d32_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Single);
|
||||
DC_DISALLOW_COPY_AND_ASSIGN(Single);
|
||||
};
|
||||
|
||||
} // namespace double_conversion
|
||||
|
@ -37,8 +37,8 @@
|
||||
#ifndef DOUBLE_CONVERSION_UTILS_H_
|
||||
#define DOUBLE_CONVERSION_UTILS_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
// ICU PATCH: Use U_ASSERT instead of <assert.h>
|
||||
#include "uassert.h"
|
||||
@ -75,7 +75,22 @@ inline void abort_noreturn() { abort(); }
|
||||
// the output of the division with the expected result. (Inlining must be
|
||||
// disabled.)
|
||||
// On Linux,x86 89255e-22 != Div_double(89255.0/1e22)
|
||||
// ICU PATCH: Enable ARM32 & ARM64 builds for Windows with 'defined(_M_ARM) || defined(_M_ARM64)'.
|
||||
//
|
||||
// For example:
|
||||
/*
|
||||
// -- in div.c
|
||||
double Div_double(double x, double y) { return x / y; }
|
||||
|
||||
// -- in main.c
|
||||
double Div_double(double x, double y); // Forward declaration.
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return Div_double(89255.0, 1e22) == 89255e-22;
|
||||
}
|
||||
*/
|
||||
// Run as follows ./main || echo "correct"
|
||||
//
|
||||
// If it prints "correct" then the architecture should be here, in the "correct" section.
|
||||
#if defined(_M_X64) || defined(__x86_64__) || \
|
||||
defined(__ARMEL__) || defined(__avr32__) || defined(_M_ARM) || defined(_M_ARM64) || \
|
||||
defined(__hppa__) || defined(__ia64__) || \
|
||||
@ -85,10 +100,13 @@ inline void abort_noreturn() { abort(); }
|
||||
defined(__sparc__) || defined(__sparc) || defined(__s390__) || \
|
||||
defined(__SH4__) || defined(__alpha__) || \
|
||||
defined(_MIPS_ARCH_MIPS32R2) || \
|
||||
defined(__AARCH64EL__) || defined(__aarch64__) || \
|
||||
defined(__riscv)
|
||||
defined(__AARCH64EL__) || defined(__aarch64__) || defined(__AARCH64EB__) || \
|
||||
defined(__riscv) || \
|
||||
defined(__or1k__) || defined(__arc__) || \
|
||||
defined(__EMSCRIPTEN__)
|
||||
#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
|
||||
#elif defined(__mc68000__)
|
||||
#elif defined(__mc68000__) || \
|
||||
defined(__pnacl__) || defined(__native_client__)
|
||||
#undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS
|
||||
#elif defined(_M_IX86) || defined(__i386__) || defined(__i386)
|
||||
#if defined(_WIN32)
|
||||
@ -101,12 +119,6 @@ inline void abort_noreturn() { abort(); }
|
||||
#error Target architecture was not detected as supported by Double-Conversion.
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define DOUBLE_CONVERSION_UNUSED __attribute__((unused))
|
||||
#else
|
||||
#define DOUBLE_CONVERSION_UNUSED
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !defined(__MINGW32__)
|
||||
|
||||
typedef signed char int8_t;
|
||||
@ -145,8 +157,8 @@ typedef uint16_t uc16;
|
||||
|
||||
// A macro to disallow the evil copy constructor and operator= functions
|
||||
// This should be used in the private: declarations for a class
|
||||
#ifndef DISALLOW_COPY_AND_ASSIGN
|
||||
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
||||
#ifndef DC_DISALLOW_COPY_AND_ASSIGN
|
||||
#define DC_DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
||||
TypeName(const TypeName&); \
|
||||
void operator=(const TypeName&)
|
||||
#endif
|
||||
@ -157,10 +169,10 @@ typedef uint16_t uc16;
|
||||
// This should be used in the private: declarations for a class
|
||||
// that wants to prevent anyone from instantiating it. This is
|
||||
// especially useful for classes containing only static methods.
|
||||
#ifndef DISALLOW_IMPLICIT_CONSTRUCTORS
|
||||
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
|
||||
#ifndef DC_DISALLOW_IMPLICIT_CONSTRUCTORS
|
||||
#define DC_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
|
||||
TypeName(); \
|
||||
DISALLOW_COPY_AND_ASSIGN(TypeName)
|
||||
DC_DISALLOW_COPY_AND_ASSIGN(TypeName)
|
||||
#endif
|
||||
|
||||
// ICU PATCH: Wrap in ICU namespace
|
||||
@ -305,7 +317,7 @@ class StringBuilder {
|
||||
|
||||
bool is_finalized() const { return position_ < 0; }
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
|
||||
DC_DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
|
||||
};
|
||||
|
||||
// The type-based aliasing rule allows the compiler to assume that pointers of
|
||||
@ -336,8 +348,12 @@ template <class Dest, class Source>
|
||||
inline Dest BitCast(const Source& source) {
|
||||
// Compile time assertion: sizeof(Dest) == sizeof(Source)
|
||||
// A compile error here means your Dest and Source have different sizes.
|
||||
DOUBLE_CONVERSION_UNUSED
|
||||
typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];
|
||||
#if __cplusplus >= 201103L
|
||||
static_assert(sizeof(Dest) == sizeof(Source),
|
||||
"source and destination size mismatch");
|
||||
#else
|
||||
typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];
|
||||
#endif
|
||||
|
||||
Dest dest;
|
||||
memmove(&dest, &source, sizeof(dest));
|
||||
|
@ -34,8 +34,9 @@
|
||||
#include "unicode/utypes.h"
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <climits>
|
||||
#include <locale>
|
||||
#include <cmath>
|
||||
|
||||
// ICU PATCH: Customize header file paths for ICU.
|
||||
// The file fixed-dtoa.h is not needed.
|
||||
@ -432,21 +433,55 @@ void DoubleToStringConverter::DoubleToAscii(double v,
|
||||
}
|
||||
|
||||
|
||||
// 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);
|
||||
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 || **current != *substring) return false;
|
||||
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_insensibility) {
|
||||
if (allow_case_insensibility) {
|
||||
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_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
|
||||
@ -513,7 +548,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;
|
||||
@ -521,7 +556,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.
|
||||
@ -535,17 +570,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, char 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,
|
||||
char 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,
|
||||
char 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;
|
||||
@ -553,27 +657,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;
|
||||
@ -596,17 +712,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;
|
||||
}
|
||||
|
||||
@ -628,15 +753,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;
|
||||
@ -645,7 +792,8 @@ 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>
|
||||
@ -663,6 +811,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:
|
||||
@ -712,8 +861,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_;
|
||||
}
|
||||
|
||||
@ -731,8 +880,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_;
|
||||
}
|
||||
|
||||
@ -751,8 +900,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);
|
||||
}
|
||||
@ -760,16 +908,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,
|
||||
@ -783,8 +939,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);
|
||||
}
|
||||
@ -805,8 +960,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) {
|
||||
@ -817,8 +971,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 {
|
||||
@ -831,8 +984,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);
|
||||
}
|
||||
@ -852,8 +1004,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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -869,9 +1020,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_;
|
||||
@ -883,6 +1036,7 @@ double StringToDoubleConverter::StringToIeee(
|
||||
++current;
|
||||
if (current == end) {
|
||||
if (allow_trailing_junk) {
|
||||
current = junk_begin;
|
||||
goto parsing_done;
|
||||
} else {
|
||||
return junk_string_value_;
|
||||
@ -892,6 +1046,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_;
|
||||
@ -936,6 +1091,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,
|
||||
|
@ -310,13 +310,18 @@ class DoubleToStringConverter {
|
||||
// should be at least kBase10MaximalLength + 1 characters long.
|
||||
static const int kBase10MaximalLength = 17;
|
||||
|
||||
// Converts the given double 'v' to ascii. 'v' must not be NaN, +Infinity, or
|
||||
// -Infinity. In SHORTEST_SINGLE-mode this restriction also applies to 'v'
|
||||
// after it has been casted to a single-precision float. That is, in this
|
||||
// mode static_cast<float>(v) must not be NaN, +Infinity or -Infinity.
|
||||
// Converts the given double 'v' to digit characters. 'v' must not be NaN,
|
||||
// +Infinity, or -Infinity. In SHORTEST_SINGLE-mode this restriction also
|
||||
// applies to 'v' after it has been casted to a single-precision float. That
|
||||
// is, in this mode static_cast<float>(v) must not be NaN, +Infinity or
|
||||
// -Infinity.
|
||||
//
|
||||
// The result should be interpreted as buffer * 10^(point-length).
|
||||
//
|
||||
// The digits are written to the buffer in the platform's charset, which is
|
||||
// often UTF-8 (with ASCII-range digits) but may be another charset, such
|
||||
// as EBCDIC.
|
||||
//
|
||||
// The output depends on the given mode:
|
||||
// - SHORTEST: produce the least amount of digits for which the internal
|
||||
// identity requirement is still satisfied. If the digits are printed
|
||||
@ -393,7 +398,7 @@ class DoubleToStringConverter {
|
||||
const int max_trailing_padding_zeroes_in_precision_mode_;
|
||||
#endif // not needed for ICU
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(DoubleToStringConverter);
|
||||
DC_DISALLOW_IMPLICIT_CONSTRUCTORS(DoubleToStringConverter);
|
||||
};
|
||||
|
||||
|
||||
@ -408,9 +413,13 @@ class StringToDoubleConverter {
|
||||
ALLOW_TRAILING_JUNK = 4,
|
||||
ALLOW_LEADING_SPACES = 8,
|
||||
ALLOW_TRAILING_SPACES = 16,
|
||||
ALLOW_SPACES_AFTER_SIGN = 32
|
||||
ALLOW_SPACES_AFTER_SIGN = 32,
|
||||
ALLOW_CASE_INSENSIBILITY = 64,
|
||||
ALLOW_HEX_FLOATS = 128,
|
||||
};
|
||||
|
||||
static const uc16 kNoSeparator = '\0';
|
||||
|
||||
// Flags should be a bit-or combination of the possible Flags-enum.
|
||||
// - NO_FLAGS: no special flags.
|
||||
// - ALLOW_HEX: recognizes the prefix "0x". Hex numbers may only be integers.
|
||||
@ -440,6 +449,13 @@ class StringToDoubleConverter {
|
||||
// - ALLOW_SPACES_AFTER_SIGN: ignore whitespace after the sign.
|
||||
// Ex: StringToDouble("- 123.2") -> -123.2.
|
||||
// StringToDouble("+ 123.2") -> 123.2
|
||||
// - ALLOW_CASE_INSENSIBILITY: ignore case of characters for special values:
|
||||
// infinity and nan.
|
||||
// - ALLOW_HEX_FLOATS: allows hexadecimal float literals.
|
||||
// This *must* start with "0x" and separate the exponent with "p".
|
||||
// Examples: 0x1.2p3 == 9.0
|
||||
// 0x10.1p0 == 16.0625
|
||||
// ALLOW_HEX and ALLOW_HEX_FLOATS are indendent.
|
||||
//
|
||||
// empty_string_value is returned when an empty string is given as input.
|
||||
// If ALLOW_LEADING_SPACES or ALLOW_TRAILING_SPACES are set, then a string
|
||||
@ -464,6 +480,12 @@ class StringToDoubleConverter {
|
||||
// - they must not have the same first character.
|
||||
// - they must not start with digits.
|
||||
//
|
||||
// If the separator character is not kNoSeparator, then that specific
|
||||
// character is ignored when in between two valid digits of the significant.
|
||||
// It is not allowed to appear in the exponent.
|
||||
// It is not allowed to lead or trail the number.
|
||||
// It is not allowed to appear twice next to each other.
|
||||
//
|
||||
// Examples:
|
||||
// flags = ALLOW_HEX | ALLOW_TRAILING_JUNK,
|
||||
// empty_string_value = 0.0,
|
||||
@ -503,16 +525,26 @@ class StringToDoubleConverter {
|
||||
// StringToDouble("01239E45") -> 1239e45.
|
||||
// StringToDouble("-infinity") -> NaN // junk_string_value.
|
||||
// StringToDouble("NaN") -> NaN // junk_string_value.
|
||||
//
|
||||
// flags = NO_FLAGS,
|
||||
// separator = ' ':
|
||||
// StringToDouble("1 2 3 4") -> 1234.0
|
||||
// StringToDouble("1 2") -> NaN // junk_string_value
|
||||
// StringToDouble("1 000 000.0") -> 1000000.0
|
||||
// StringToDouble("1.000 000") -> 1.0
|
||||
// StringToDouble("1.0e1 000") -> NaN // junk_string_value
|
||||
StringToDoubleConverter(int flags,
|
||||
double empty_string_value,
|
||||
double junk_string_value,
|
||||
const char* infinity_symbol,
|
||||
const char* nan_symbol)
|
||||
const char* nan_symbol,
|
||||
uc16 separator = kNoSeparator)
|
||||
: flags_(flags),
|
||||
empty_string_value_(empty_string_value),
|
||||
junk_string_value_(junk_string_value),
|
||||
infinity_symbol_(infinity_symbol),
|
||||
nan_symbol_(nan_symbol) {
|
||||
nan_symbol_(nan_symbol),
|
||||
separator_(separator) {
|
||||
}
|
||||
|
||||
// Performs the conversion.
|
||||
@ -547,6 +579,7 @@ class StringToDoubleConverter {
|
||||
const double junk_string_value_;
|
||||
const char* const infinity_symbol_;
|
||||
const char* const nan_symbol_;
|
||||
const uc16 separator_;
|
||||
|
||||
template <class Iterator>
|
||||
double StringToIeee(Iterator start_pointer,
|
||||
@ -554,7 +587,7 @@ class StringToDoubleConverter {
|
||||
bool read_as_double,
|
||||
int* processed_characters_count) const;
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter);
|
||||
DC_DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter);
|
||||
};
|
||||
|
||||
} // namespace double_conversion
|
||||
|
2
vendor/double-conversion/upstream/BUILD
vendored
2
vendor/double-conversion/upstream/BUILD
vendored
@ -2,6 +2,8 @@
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
exports_files(["LICENSE"])
|
||||
|
||||
cc_library(
|
||||
name = "double-conversion",
|
||||
srcs = [
|
||||
|
147
vendor/double-conversion/upstream/CMakeLists.txt
vendored
147
vendor/double-conversion/upstream/CMakeLists.txt
vendored
@ -1,27 +1,34 @@
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
project(double-conversion)
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
project(double-conversion VERSION 3.1.1)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
set(headers
|
||||
double-conversion/bignum.h
|
||||
double-conversion/cached-powers.h
|
||||
double-conversion/diy-fp.h
|
||||
double-conversion/double-conversion.h
|
||||
double-conversion/fast-dtoa.h
|
||||
double-conversion/fixed-dtoa.h
|
||||
double-conversion/ieee.h
|
||||
double-conversion/strtod.h
|
||||
double-conversion/utils.h)
|
||||
|
||||
add_library(double-conversion
|
||||
double-conversion/bignum.cc
|
||||
double-conversion/bignum-dtoa.cc
|
||||
double-conversion/cached-powers.cc
|
||||
double-conversion/diy-fp.cc
|
||||
double-conversion/double-conversion.cc
|
||||
double-conversion/fast-dtoa.cc
|
||||
double-conversion/fixed-dtoa.cc
|
||||
double-conversion/strtod.cc
|
||||
${headers})
|
||||
target_include_directories(
|
||||
double-conversion PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
|
||||
|
||||
# pick a version #
|
||||
set(double-conversion_VERSION 2.0.1)
|
||||
set(double-conversion_SOVERSION_MAJOR 1)
|
||||
set(double-conversion_SOVERSION_MINOR 0)
|
||||
set(double-conversion_SOVERSION_PATCH 0)
|
||||
set(double-conversion_SOVERSION
|
||||
${double-conversion_SOVERSION_MAJOR}.${double-conversion_SOVERSION_MINOR}.${double-conversion_SOVERSION_PATCH})
|
||||
set_target_properties(double-conversion PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION 3)
|
||||
|
||||
# set suffix for CMake files used for packaging
|
||||
if(WIN32 AND NOT CYGWIN)
|
||||
set(INSTALL_CMAKE_DIR CMake)
|
||||
else()
|
||||
set(INSTALL_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/double-conversion)
|
||||
endif()
|
||||
|
||||
# Add src subdirectory
|
||||
add_subdirectory(double-conversion)
|
||||
|
||||
#
|
||||
# set up testing if requested
|
||||
option(BUILD_TESTING "Build test programs" OFF)
|
||||
if(BUILD_TESTING)
|
||||
@ -30,41 +37,75 @@ if(BUILD_TESTING)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
||||
#
|
||||
# mention the library target as export library
|
||||
export(TARGETS double-conversion
|
||||
FILE "${PROJECT_BINARY_DIR}/double-conversionLibraryDepends.cmake")
|
||||
####
|
||||
# Installation (https://github.com/forexample/package-example)
|
||||
|
||||
#
|
||||
# set this build as an importable package
|
||||
export(PACKAGE double-conversion)
|
||||
# Layout. This works for all platforms:
|
||||
# * <prefix>/lib/cmake/<PROJECT-NAME>
|
||||
# * <prefix>/lib/
|
||||
# * <prefix>/include/
|
||||
set(config_install_dir "lib/cmake/${PROJECT_NAME}")
|
||||
set(include_install_dir "include")
|
||||
|
||||
#
|
||||
# make a cmake file -- in this case, all that needs defining
|
||||
# is double-conversion_INCLUDE_DIRS
|
||||
configure_file(double-conversionBuildTreeSettings.cmake.in
|
||||
"${PROJECT_BINARY_DIR}/double-conversionBuildTreeSettings.cmake"
|
||||
@ONLY)
|
||||
set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated")
|
||||
|
||||
#
|
||||
# sets up config to be used by CMake find_package
|
||||
configure_file(double-conversionConfig.cmake.in
|
||||
"${PROJECT_BINARY_DIR}/double-conversionConfig.cmake"
|
||||
@ONLY)
|
||||
#
|
||||
# Export version # checked by find_package
|
||||
configure_file(double-conversionConfigVersion.cmake.in
|
||||
"${PROJECT_BINARY_DIR}/double-conversionConfigVersion.cmake"
|
||||
@ONLY)
|
||||
#
|
||||
# install config files for find_package
|
||||
install(FILES
|
||||
"${PROJECT_BINARY_DIR}/double-conversionConfig.cmake"
|
||||
"${PROJECT_BINARY_DIR}/double-conversionConfigVersion.cmake"
|
||||
DESTINATION "${INSTALL_CMAKE_DIR}" COMPONENT dev)
|
||||
# Configuration
|
||||
set(version_config "${generated_dir}/${PROJECT_NAME}ConfigVersion.cmake")
|
||||
set(project_config "${generated_dir}/${PROJECT_NAME}Config.cmake")
|
||||
set(targets_export_name "${PROJECT_NAME}Targets")
|
||||
set(namespace "${PROJECT_NAME}::")
|
||||
|
||||
# Include module with function 'write_basic_package_version_file'
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
#
|
||||
# generates install cmake files to find libraries in installation.
|
||||
install(EXPORT double-conversionLibraryDepends DESTINATION
|
||||
"${INSTALL_CMAKE_DIR}" COMPONENT dev)
|
||||
# Configure '<PROJECT-NAME>ConfigVersion.cmake'
|
||||
# Note: PROJECT_VERSION is used as a VERSION
|
||||
write_basic_package_version_file(
|
||||
"${version_config}" COMPATIBILITY SameMajorVersion
|
||||
)
|
||||
|
||||
# Configure '<PROJECT-NAME>Config.cmake'
|
||||
# Use variables:
|
||||
# * targets_export_name
|
||||
# * PROJECT_NAME
|
||||
configure_package_config_file(
|
||||
"cmake/Config.cmake.in"
|
||||
"${project_config}"
|
||||
INSTALL_DESTINATION "${config_install_dir}"
|
||||
)
|
||||
|
||||
# Targets:
|
||||
# * <prefix>/lib/libdouble-conversion.a
|
||||
# * header location after install: <prefix>/include/double-conversion/*.h
|
||||
# * headers can be included by C++ code `#include <double-conversion/*.h>`
|
||||
install(
|
||||
TARGETS double-conversion
|
||||
EXPORT "${targets_export_name}"
|
||||
LIBRARY DESTINATION "lib"
|
||||
ARCHIVE DESTINATION "lib"
|
||||
RUNTIME DESTINATION "bin"
|
||||
INCLUDES DESTINATION "${include_install_dir}"
|
||||
)
|
||||
|
||||
# Headers:
|
||||
# * double-conversion/*.h -> <prefix>/include/double-conversion/*.h
|
||||
install(
|
||||
FILES ${headers}
|
||||
DESTINATION "${include_install_dir}/double-conversion"
|
||||
)
|
||||
|
||||
# Config
|
||||
# * <prefix>/lib/cmake/double-conversion/double-conversionConfig.cmake
|
||||
# * <prefix>/lib/cmake/double-conversion/double-conversionConfigVersion.cmake
|
||||
install(
|
||||
FILES "${project_config}" "${version_config}"
|
||||
DESTINATION "${config_install_dir}"
|
||||
)
|
||||
|
||||
# Config
|
||||
# * <prefix>/lib/cmake/double-conversion/double-conversionTargets.cmake
|
||||
install(
|
||||
EXPORT "${targets_export_name}"
|
||||
NAMESPACE "${namespace}"
|
||||
DESTINATION "${config_install_dir}"
|
||||
)
|
||||
|
17
vendor/double-conversion/upstream/Changelog
vendored
17
vendor/double-conversion/upstream/Changelog
vendored
@ -1,6 +1,23 @@
|
||||
2018-09-15:
|
||||
Update version numbers. This also updates the shared-library version number.
|
||||
|
||||
2018-09-09:
|
||||
Fix bug where large hex literals would lose their minus sign.
|
||||
Added support for separator characters (which adds a new optional
|
||||
argument). Thus increasing the version number to 3.1.0
|
||||
Added support for hexadecimal float literals.
|
||||
Support for more architectures.
|
||||
|
||||
2017-12-06:
|
||||
Renamed `DISALLOW_COPY_AND_ASSIGN` and `DISALLOW_IMPLICIT_CONSTRUCTORS`
|
||||
macros to `DC_DISALLOW_COPY_AND_ASSIGN` and
|
||||
`DC_DISALLOW_IMPLICIT_CONSTRUCTORS` to make it easier to integrate the
|
||||
library with other libraries that have similar macros.
|
||||
|
||||
2017-08-05:
|
||||
Tagged v3.0.0.
|
||||
Due to the directory rename switching to a new version number.
|
||||
The API for the library itself hasn't changed.
|
||||
|
||||
2017-03-04:
|
||||
Avoid negative shift. Fixes #41.
|
||||
|
2
vendor/double-conversion/upstream/SConstruct
vendored
2
vendor/double-conversion/upstream/SConstruct
vendored
@ -16,7 +16,7 @@ optimize = ARGUMENTS.get('optimize', 0)
|
||||
env.Replace(CXX = ARGUMENTS.get('CXX', 'g++'))
|
||||
|
||||
# for shared lib, requires scons 2.3.0
|
||||
env['SHLIBVERSION'] = '1.0.0'
|
||||
env['SHLIBVERSION'] = '3.0.0'
|
||||
|
||||
CCFLAGS = []
|
||||
if int(debug):
|
||||
|
4
vendor/double-conversion/upstream/cmake/Config.cmake.in
vendored
Normal file
4
vendor/double-conversion/upstream/cmake/Config.cmake.in
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@targets_export_name@.cmake")
|
||||
check_required_components("@PROJECT_NAME@")
|
@ -1,57 +0,0 @@
|
||||
set(headers
|
||||
bignum.h
|
||||
cached-powers.h
|
||||
diy-fp.h
|
||||
double-conversion.h
|
||||
fast-dtoa.h
|
||||
fixed-dtoa.h
|
||||
ieee.h
|
||||
strtod.h
|
||||
utils.h
|
||||
)
|
||||
|
||||
add_library(double-conversion
|
||||
bignum.cc
|
||||
bignum-dtoa.cc
|
||||
cached-powers.cc
|
||||
diy-fp.cc
|
||||
double-conversion.cc
|
||||
fast-dtoa.cc
|
||||
fixed-dtoa.cc
|
||||
strtod.cc
|
||||
${headers}
|
||||
)
|
||||
|
||||
target_include_directories(double-conversion PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>)
|
||||
|
||||
# Add fPIC on x86_64 when supported.
|
||||
include(CheckCXXCompilerFlag)
|
||||
check_cxx_compiler_flag(-fPIC CXX_HAS_FPIC)
|
||||
|
||||
if(CXX_HAS_FPIC AND CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
|
||||
set_target_properties(double-conversion PROPERTIES COMPILE_FLAGS "-fPIC")
|
||||
endif()
|
||||
|
||||
#
|
||||
# associates the list of headers with the library
|
||||
# for the purposes of installation/import into other projects
|
||||
set_target_properties(double-conversion
|
||||
PROPERTIES PUBLIC_HEADER "${headers}")
|
||||
|
||||
if (BUILD_SHARED_LIBS)
|
||||
set_target_properties(double-conversion
|
||||
PROPERTIES VERSION ${double-conversion_SOVERSION}
|
||||
SOVERSION ${double-conversion_SOVERSION_MAJOR})
|
||||
endif()
|
||||
|
||||
#
|
||||
# install command to set up library install
|
||||
# given the above PUBLIC_HEADER property set, this
|
||||
# pulls along all the header files with the library.
|
||||
install(TARGETS double-conversion
|
||||
EXPORT double-conversionLibraryDepends
|
||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT bin
|
||||
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT shlib
|
||||
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib
|
||||
PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/double-conversion"
|
||||
COMPONENT dev)
|
@ -25,12 +25,12 @@
|
||||
// (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 <math.h>
|
||||
#include <cmath>
|
||||
|
||||
#include "bignum-dtoa.h"
|
||||
#include <double-conversion/bignum-dtoa.h>
|
||||
|
||||
#include "bignum.h"
|
||||
#include "ieee.h"
|
||||
#include <double-conversion/bignum.h>
|
||||
#include <double-conversion/ieee.h>
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
#ifndef DOUBLE_CONVERSION_BIGNUM_DTOA_H_
|
||||
#define DOUBLE_CONVERSION_BIGNUM_DTOA_H_
|
||||
|
||||
#include "utils.h"
|
||||
#include <double-conversion/utils.h>
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
|
@ -25,13 +25,13 @@
|
||||
// (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 "bignum.h"
|
||||
#include "utils.h"
|
||||
#include <double-conversion/bignum.h>
|
||||
#include <double-conversion/utils.h>
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
Bignum::Bignum()
|
||||
: bigits_(bigits_buffer_, kBigitCapacity), used_digits_(0), exponent_(0) {
|
||||
: bigits_buffer_(), bigits_(bigits_buffer_, kBigitCapacity), used_digits_(0), exponent_(0) {
|
||||
for (int i = 0; i < kBigitCapacity; ++i) {
|
||||
bigits_[i] = 0;
|
||||
}
|
||||
@ -445,26 +445,27 @@ void Bignum::AssignPowerUInt16(uint16_t base, int power_exponent) {
|
||||
mask >>= 2;
|
||||
uint64_t this_value = base;
|
||||
|
||||
bool delayed_multipliciation = false;
|
||||
bool delayed_multiplication = false;
|
||||
const uint64_t max_32bits = 0xFFFFFFFF;
|
||||
while (mask != 0 && this_value <= max_32bits) {
|
||||
this_value = this_value * this_value;
|
||||
// Verify that there is enough space in this_value to perform the
|
||||
// multiplication. The first bit_size bits must be 0.
|
||||
if ((power_exponent & mask) != 0) {
|
||||
ASSERT(bit_size > 0);
|
||||
uint64_t base_bits_mask =
|
||||
~((static_cast<uint64_t>(1) << (64 - bit_size)) - 1);
|
||||
bool high_bits_zero = (this_value & base_bits_mask) == 0;
|
||||
if (high_bits_zero) {
|
||||
this_value *= base;
|
||||
} else {
|
||||
delayed_multipliciation = true;
|
||||
delayed_multiplication = true;
|
||||
}
|
||||
}
|
||||
mask >>= 1;
|
||||
}
|
||||
AssignUInt64(this_value);
|
||||
if (delayed_multipliciation) {
|
||||
if (delayed_multiplication) {
|
||||
MultiplyByUInt32(base);
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
#ifndef DOUBLE_CONVERSION_BIGNUM_H_
|
||||
#define DOUBLE_CONVERSION_BIGNUM_H_
|
||||
|
||||
#include "utils.h"
|
||||
#include <double-conversion/utils.h>
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
@ -136,7 +136,7 @@ class Bignum {
|
||||
// The Bignum's value equals value(bigits_) * 2^(exponent_ * kBigitSize).
|
||||
int exponent_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Bignum);
|
||||
DC_DISALLOW_COPY_AND_ASSIGN(Bignum);
|
||||
};
|
||||
|
||||
} // namespace double_conversion
|
||||
|
@ -25,13 +25,13 @@
|
||||
// (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 <stdarg.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <climits>
|
||||
#include <cmath>
|
||||
#include <cstdarg>
|
||||
|
||||
#include "utils.h"
|
||||
#include <double-conversion/utils.h>
|
||||
|
||||
#include "cached-powers.h"
|
||||
#include <double-conversion/cached-powers.h>
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
#ifndef DOUBLE_CONVERSION_CACHED_POWERS_H_
|
||||
#define DOUBLE_CONVERSION_CACHED_POWERS_H_
|
||||
|
||||
#include "diy-fp.h"
|
||||
#include <double-conversion/diy-fp.h>
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
|
@ -26,8 +26,8 @@
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
#include "diy-fp.h"
|
||||
#include "utils.h"
|
||||
#include <double-conversion/diy-fp.h>
|
||||
#include <double-conversion/utils.h>
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
#ifndef DOUBLE_CONVERSION_DIY_FP_H_
|
||||
#define DOUBLE_CONVERSION_DIY_FP_H_
|
||||
|
||||
#include "utils.h"
|
||||
#include <double-conversion/utils.h>
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
|
@ -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.h"
|
||||
#include <double-conversion/double-conversion.h>
|
||||
|
||||
#include "bignum-dtoa.h"
|
||||
#include "fast-dtoa.h"
|
||||
#include "fixed-dtoa.h"
|
||||
#include "ieee.h"
|
||||
#include "strtod.h"
|
||||
#include "utils.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>
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
@ -414,21 +415,55 @@ void DoubleToStringConverter::DoubleToAscii(double v,
|
||||
}
|
||||
|
||||
|
||||
// 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);
|
||||
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 || **current != *substring) return false;
|
||||
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_insensibility) {
|
||||
if (allow_case_insensibility) {
|
||||
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_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 +529,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 +537,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 +551,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, char 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,
|
||||
char 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,
|
||||
char 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 +638,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 +693,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 +734,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 +773,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 +792,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 +842,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 +861,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 +881,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 +889,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 +920,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 +941,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 +952,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 +965,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 +985,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 +1001,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 +1017,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 +1027,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 +1072,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,
|
||||
|
@ -28,7 +28,7 @@
|
||||
#ifndef DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_
|
||||
#define DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_
|
||||
|
||||
#include "utils.h"
|
||||
#include <double-conversion/utils.h>
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
@ -294,13 +294,18 @@ class DoubleToStringConverter {
|
||||
// should be at least kBase10MaximalLength + 1 characters long.
|
||||
static const int kBase10MaximalLength = 17;
|
||||
|
||||
// Converts the given double 'v' to ascii. 'v' must not be NaN, +Infinity, or
|
||||
// -Infinity. In SHORTEST_SINGLE-mode this restriction also applies to 'v'
|
||||
// after it has been casted to a single-precision float. That is, in this
|
||||
// mode static_cast<float>(v) must not be NaN, +Infinity or -Infinity.
|
||||
// Converts the given double 'v' to digit characters. 'v' must not be NaN,
|
||||
// +Infinity, or -Infinity. In SHORTEST_SINGLE-mode this restriction also
|
||||
// applies to 'v' after it has been casted to a single-precision float. That
|
||||
// is, in this mode static_cast<float>(v) must not be NaN, +Infinity or
|
||||
// -Infinity.
|
||||
//
|
||||
// The result should be interpreted as buffer * 10^(point-length).
|
||||
//
|
||||
// The digits are written to the buffer in the platform's charset, which is
|
||||
// often UTF-8 (with ASCII-range digits) but may be another charset, such
|
||||
// as EBCDIC.
|
||||
//
|
||||
// The output depends on the given mode:
|
||||
// - SHORTEST: produce the least amount of digits for which the internal
|
||||
// identity requirement is still satisfied. If the digits are printed
|
||||
@ -374,7 +379,7 @@ class DoubleToStringConverter {
|
||||
const int max_leading_padding_zeroes_in_precision_mode_;
|
||||
const int max_trailing_padding_zeroes_in_precision_mode_;
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(DoubleToStringConverter);
|
||||
DC_DISALLOW_IMPLICIT_CONSTRUCTORS(DoubleToStringConverter);
|
||||
};
|
||||
|
||||
|
||||
@ -389,9 +394,13 @@ class StringToDoubleConverter {
|
||||
ALLOW_TRAILING_JUNK = 4,
|
||||
ALLOW_LEADING_SPACES = 8,
|
||||
ALLOW_TRAILING_SPACES = 16,
|
||||
ALLOW_SPACES_AFTER_SIGN = 32
|
||||
ALLOW_SPACES_AFTER_SIGN = 32,
|
||||
ALLOW_CASE_INSENSIBILITY = 64,
|
||||
ALLOW_HEX_FLOATS = 128,
|
||||
};
|
||||
|
||||
static const uc16 kNoSeparator = '\0';
|
||||
|
||||
// Flags should be a bit-or combination of the possible Flags-enum.
|
||||
// - NO_FLAGS: no special flags.
|
||||
// - ALLOW_HEX: recognizes the prefix "0x". Hex numbers may only be integers.
|
||||
@ -421,6 +430,13 @@ class StringToDoubleConverter {
|
||||
// - ALLOW_SPACES_AFTER_SIGN: ignore whitespace after the sign.
|
||||
// Ex: StringToDouble("- 123.2") -> -123.2.
|
||||
// StringToDouble("+ 123.2") -> 123.2
|
||||
// - ALLOW_CASE_INSENSIBILITY: ignore case of characters for special values:
|
||||
// infinity and nan.
|
||||
// - ALLOW_HEX_FLOATS: allows hexadecimal float literals.
|
||||
// This *must* start with "0x" and separate the exponent with "p".
|
||||
// Examples: 0x1.2p3 == 9.0
|
||||
// 0x10.1p0 == 16.0625
|
||||
// ALLOW_HEX and ALLOW_HEX_FLOATS are indendent.
|
||||
//
|
||||
// empty_string_value is returned when an empty string is given as input.
|
||||
// If ALLOW_LEADING_SPACES or ALLOW_TRAILING_SPACES are set, then a string
|
||||
@ -445,6 +461,12 @@ class StringToDoubleConverter {
|
||||
// - they must not have the same first character.
|
||||
// - they must not start with digits.
|
||||
//
|
||||
// If the separator character is not kNoSeparator, then that specific
|
||||
// character is ignored when in between two valid digits of the significant.
|
||||
// It is not allowed to appear in the exponent.
|
||||
// It is not allowed to lead or trail the number.
|
||||
// It is not allowed to appear twice next to each other.
|
||||
//
|
||||
// Examples:
|
||||
// flags = ALLOW_HEX | ALLOW_TRAILING_JUNK,
|
||||
// empty_string_value = 0.0,
|
||||
@ -484,16 +506,26 @@ class StringToDoubleConverter {
|
||||
// StringToDouble("01239E45") -> 1239e45.
|
||||
// StringToDouble("-infinity") -> NaN // junk_string_value.
|
||||
// StringToDouble("NaN") -> NaN // junk_string_value.
|
||||
//
|
||||
// flags = NO_FLAGS,
|
||||
// separator = ' ':
|
||||
// StringToDouble("1 2 3 4") -> 1234.0
|
||||
// StringToDouble("1 2") -> NaN // junk_string_value
|
||||
// StringToDouble("1 000 000.0") -> 1000000.0
|
||||
// StringToDouble("1.000 000") -> 1.0
|
||||
// StringToDouble("1.0e1 000") -> NaN // junk_string_value
|
||||
StringToDoubleConverter(int flags,
|
||||
double empty_string_value,
|
||||
double junk_string_value,
|
||||
const char* infinity_symbol,
|
||||
const char* nan_symbol)
|
||||
const char* nan_symbol,
|
||||
uc16 separator = kNoSeparator)
|
||||
: flags_(flags),
|
||||
empty_string_value_(empty_string_value),
|
||||
junk_string_value_(junk_string_value),
|
||||
infinity_symbol_(infinity_symbol),
|
||||
nan_symbol_(nan_symbol) {
|
||||
nan_symbol_(nan_symbol),
|
||||
separator_(separator) {
|
||||
}
|
||||
|
||||
// Performs the conversion.
|
||||
@ -528,6 +560,7 @@ class StringToDoubleConverter {
|
||||
const double junk_string_value_;
|
||||
const char* const infinity_symbol_;
|
||||
const char* const nan_symbol_;
|
||||
const uc16 separator_;
|
||||
|
||||
template <class Iterator>
|
||||
double StringToIeee(Iterator start_pointer,
|
||||
@ -535,7 +568,7 @@ class StringToDoubleConverter {
|
||||
bool read_as_double,
|
||||
int* processed_characters_count) const;
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter);
|
||||
DC_DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter);
|
||||
};
|
||||
|
||||
} // namespace double_conversion
|
||||
|
@ -25,11 +25,11 @@
|
||||
// (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 "fast-dtoa.h"
|
||||
#include <double-conversion/fast-dtoa.h>
|
||||
|
||||
#include "cached-powers.h"
|
||||
#include "diy-fp.h"
|
||||
#include "ieee.h"
|
||||
#include <double-conversion/cached-powers.h>
|
||||
#include <double-conversion/diy-fp.h>
|
||||
#include <double-conversion/ieee.h>
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
#ifndef DOUBLE_CONVERSION_FAST_DTOA_H_
|
||||
#define DOUBLE_CONVERSION_FAST_DTOA_H_
|
||||
|
||||
#include "utils.h"
|
||||
#include <double-conversion/utils.h>
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
|
@ -25,10 +25,10 @@
|
||||
// (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 <math.h>
|
||||
#include <cmath>
|
||||
|
||||
#include "fixed-dtoa.h"
|
||||
#include "ieee.h"
|
||||
#include <double-conversion/fixed-dtoa.h>
|
||||
#include <double-conversion/ieee.h>
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
#ifndef DOUBLE_CONVERSION_FIXED_DTOA_H_
|
||||
#define DOUBLE_CONVERSION_FIXED_DTOA_H_
|
||||
|
||||
#include "utils.h"
|
||||
#include <double-conversion/utils.h>
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
#ifndef DOUBLE_CONVERSION_DOUBLE_H_
|
||||
#define DOUBLE_CONVERSION_DOUBLE_H_
|
||||
|
||||
#include "diy-fp.h"
|
||||
#include <double-conversion/diy-fp.h>
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
@ -257,7 +257,7 @@ class Double {
|
||||
(biased_exponent << kPhysicalSignificandSize);
|
||||
}
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Double);
|
||||
DC_DISALLOW_COPY_AND_ASSIGN(Double);
|
||||
};
|
||||
|
||||
class Single {
|
||||
@ -394,7 +394,7 @@ class Single {
|
||||
|
||||
const uint32_t d32_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Single);
|
||||
DC_DISALLOW_COPY_AND_ASSIGN(Single);
|
||||
};
|
||||
|
||||
} // namespace double_conversion
|
||||
|
@ -25,13 +25,13 @@
|
||||
// (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 <stdarg.h>
|
||||
#include <limits.h>
|
||||
#include <climits>
|
||||
#include <cstdarg>
|
||||
|
||||
#include "strtod.h"
|
||||
#include "bignum.h"
|
||||
#include "cached-powers.h"
|
||||
#include "ieee.h"
|
||||
#include <double-conversion/bignum.h>
|
||||
#include <double-conversion/cached-powers.h>
|
||||
#include <double-conversion/ieee.h>
|
||||
#include <double-conversion/strtod.h>
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
@ -205,7 +205,7 @@ static bool DoubleStrtod(Vector<const char> trimmed,
|
||||
// Note that the ARM simulator is compiled for 32bits. It therefore exhibits
|
||||
// the same problem.
|
||||
return false;
|
||||
#endif
|
||||
#else
|
||||
if (trimmed.length() <= kMaxExactDoubleIntegerDecimalDigits) {
|
||||
int read_digits;
|
||||
// The trimmed input fits into a double.
|
||||
@ -243,6 +243,7 @@ static bool DoubleStrtod(Vector<const char> trimmed,
|
||||
}
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -471,6 +472,30 @@ double Strtod(Vector<const char> buffer, int exponent) {
|
||||
}
|
||||
}
|
||||
|
||||
static float SanitizedDoubletof(double d) {
|
||||
ASSERT(d >= 0.0);
|
||||
// ASAN has a sanitize check that disallows casting doubles to floats if
|
||||
// they are too big.
|
||||
// https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html#available-checks
|
||||
// The behavior should be covered by IEEE 754, but some projects use this
|
||||
// flag, so work around it.
|
||||
float max_finite = 3.4028234663852885981170418348451692544e+38;
|
||||
// The half-way point between the max-finite and infinity value.
|
||||
// Since infinity has an even significand everything equal or greater than
|
||||
// this value should become infinity.
|
||||
double half_max_finite_infinity =
|
||||
3.40282356779733661637539395458142568448e+38;
|
||||
if (d >= max_finite) {
|
||||
if (d >= half_max_finite_infinity) {
|
||||
return Single::Infinity();
|
||||
} else {
|
||||
return max_finite;
|
||||
}
|
||||
} else {
|
||||
return static_cast<float>(d);
|
||||
}
|
||||
}
|
||||
|
||||
float Strtof(Vector<const char> buffer, int exponent) {
|
||||
char copy_buffer[kMaxSignificantDecimalDigits];
|
||||
Vector<const char> trimmed;
|
||||
@ -482,7 +507,7 @@ float Strtof(Vector<const char> buffer, int exponent) {
|
||||
double double_guess;
|
||||
bool is_correct = ComputeGuess(trimmed, exponent, &double_guess);
|
||||
|
||||
float float_guess = static_cast<float>(double_guess);
|
||||
float float_guess = SanitizedDoubletof(double_guess);
|
||||
if (float_guess == double_guess) {
|
||||
// This shortcut triggers for integer values.
|
||||
return float_guess;
|
||||
@ -505,15 +530,15 @@ float Strtof(Vector<const char> buffer, int exponent) {
|
||||
double double_next = Double(double_guess).NextDouble();
|
||||
double double_previous = Double(double_guess).PreviousDouble();
|
||||
|
||||
float f1 = static_cast<float>(double_previous);
|
||||
float f1 = SanitizedDoubletof(double_previous);
|
||||
float f2 = float_guess;
|
||||
float f3 = static_cast<float>(double_next);
|
||||
float f3 = SanitizedDoubletof(double_next);
|
||||
float f4;
|
||||
if (is_correct) {
|
||||
f4 = f3;
|
||||
} else {
|
||||
double double_next2 = Double(double_next).NextDouble();
|
||||
f4 = static_cast<float>(double_next2);
|
||||
f4 = SanitizedDoubletof(double_next2);
|
||||
}
|
||||
(void) f2; // Mark variable as used.
|
||||
ASSERT(f1 <= f2 && f2 <= f3 && f3 <= f4);
|
||||
@ -528,7 +553,7 @@ float Strtof(Vector<const char> buffer, int exponent) {
|
||||
(f1 == f2 && f2 != f3 && f3 == f4) ||
|
||||
(f1 == f2 && f2 == f3 && f3 != f4));
|
||||
|
||||
// guess and next are the two possible canditates (in the same way that
|
||||
// guess and next are the two possible candidates (in the same way that
|
||||
// double_guess was the lower candidate for a double-precision guess).
|
||||
float guess = f1;
|
||||
float next = f4;
|
||||
|
@ -28,7 +28,7 @@
|
||||
#ifndef DOUBLE_CONVERSION_STRTOD_H_
|
||||
#define DOUBLE_CONVERSION_STRTOD_H_
|
||||
|
||||
#include "utils.h"
|
||||
#include <double-conversion/utils.h>
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
|
@ -28,10 +28,10 @@
|
||||
#ifndef DOUBLE_CONVERSION_UTILS_H_
|
||||
#define DOUBLE_CONVERSION_UTILS_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include <assert.h>
|
||||
#include <cassert>
|
||||
#ifndef ASSERT
|
||||
#define ASSERT(condition) \
|
||||
assert(condition);
|
||||
@ -67,8 +67,24 @@ inline void abort_noreturn() { abort(); }
|
||||
// the output of the division with the expected result. (Inlining must be
|
||||
// disabled.)
|
||||
// On Linux,x86 89255e-22 != Div_double(89255.0/1e22)
|
||||
//
|
||||
// For example:
|
||||
/*
|
||||
// -- in div.c
|
||||
double Div_double(double x, double y) { return x / y; }
|
||||
|
||||
// -- in main.c
|
||||
double Div_double(double x, double y); // Forward declaration.
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return Div_double(89255.0, 1e22) == 89255e-22;
|
||||
}
|
||||
*/
|
||||
// Run as follows ./main || echo "correct"
|
||||
//
|
||||
// If it prints "correct" then the architecture should be here, in the "correct" section.
|
||||
#if defined(_M_X64) || defined(__x86_64__) || \
|
||||
defined(__ARMEL__) || defined(__avr32__) || \
|
||||
defined(__ARMEL__) || defined(__avr32__) || defined(_M_ARM) || defined(_M_ARM64) || \
|
||||
defined(__hppa__) || defined(__ia64__) || \
|
||||
defined(__mips__) || \
|
||||
defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \
|
||||
@ -76,10 +92,13 @@ inline void abort_noreturn() { abort(); }
|
||||
defined(__sparc__) || defined(__sparc) || defined(__s390__) || \
|
||||
defined(__SH4__) || defined(__alpha__) || \
|
||||
defined(_MIPS_ARCH_MIPS32R2) || \
|
||||
defined(__AARCH64EL__) || defined(__aarch64__) || \
|
||||
defined(__riscv)
|
||||
defined(__AARCH64EL__) || defined(__aarch64__) || defined(__AARCH64EB__) || \
|
||||
defined(__riscv) || \
|
||||
defined(__or1k__) || defined(__arc__) || \
|
||||
defined(__EMSCRIPTEN__)
|
||||
#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
|
||||
#elif defined(__mc68000__)
|
||||
#elif defined(__mc68000__) || \
|
||||
defined(__pnacl__) || defined(__native_client__)
|
||||
#undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS
|
||||
#elif defined(_M_IX86) || defined(__i386__) || defined(__i386)
|
||||
#if defined(_WIN32)
|
||||
@ -92,12 +111,6 @@ inline void abort_noreturn() { abort(); }
|
||||
#error Target architecture was not detected as supported by Double-Conversion.
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define DOUBLE_CONVERSION_UNUSED __attribute__((unused))
|
||||
#else
|
||||
#define DOUBLE_CONVERSION_UNUSED
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !defined(__MINGW32__)
|
||||
|
||||
typedef signed char int8_t;
|
||||
@ -136,8 +149,8 @@ typedef uint16_t uc16;
|
||||
|
||||
// A macro to disallow the evil copy constructor and operator= functions
|
||||
// This should be used in the private: declarations for a class
|
||||
#ifndef DISALLOW_COPY_AND_ASSIGN
|
||||
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
||||
#ifndef DC_DISALLOW_COPY_AND_ASSIGN
|
||||
#define DC_DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
||||
TypeName(const TypeName&); \
|
||||
void operator=(const TypeName&)
|
||||
#endif
|
||||
@ -148,10 +161,10 @@ typedef uint16_t uc16;
|
||||
// This should be used in the private: declarations for a class
|
||||
// that wants to prevent anyone from instantiating it. This is
|
||||
// especially useful for classes containing only static methods.
|
||||
#ifndef DISALLOW_IMPLICIT_CONSTRUCTORS
|
||||
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
|
||||
#ifndef DC_DISALLOW_IMPLICIT_CONSTRUCTORS
|
||||
#define DC_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
|
||||
TypeName(); \
|
||||
DISALLOW_COPY_AND_ASSIGN(TypeName)
|
||||
DC_DISALLOW_COPY_AND_ASSIGN(TypeName)
|
||||
#endif
|
||||
|
||||
namespace double_conversion {
|
||||
@ -293,7 +306,7 @@ class StringBuilder {
|
||||
|
||||
bool is_finalized() const { return position_ < 0; }
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
|
||||
DC_DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
|
||||
};
|
||||
|
||||
// The type-based aliasing rule allows the compiler to assume that pointers of
|
||||
@ -324,8 +337,12 @@ template <class Dest, class Source>
|
||||
inline Dest BitCast(const Source& source) {
|
||||
// Compile time assertion: sizeof(Dest) == sizeof(Source)
|
||||
// A compile error here means your Dest and Source have different sizes.
|
||||
DOUBLE_CONVERSION_UNUSED
|
||||
typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];
|
||||
#if __cplusplus >= 201103L
|
||||
static_assert(sizeof(Dest) == sizeof(Source),
|
||||
"source and destination size mismatch");
|
||||
#else
|
||||
typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];
|
||||
#endif
|
||||
|
||||
Dest dest;
|
||||
memmove(&dest, &source, sizeof(dest));
|
||||
|
@ -1,2 +0,0 @@
|
||||
set(double-conversion_INCLUDE_DIRS
|
||||
"@PROJECT_SOURCE_DIR@/src")
|
@ -1,16 +0,0 @@
|
||||
# - Config file for the double-conversion package
|
||||
# It defines the following variables
|
||||
# double-conversion_INCLUDE_DIRS
|
||||
# double-conversion_LIBRARIES
|
||||
|
||||
get_filename_component(double-conversion_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
|
||||
|
||||
if(EXISTS "${double-conversion_CMAKE_DIR}/CMakeCache.txt")
|
||||
include("${double-conversion_CMAKE_DIR}/double-conversionBuildTreeSettings.cmake")
|
||||
else()
|
||||
set(double-conversion_INCLUDE_DIRS "@CMAKE_INSTALL_FULL_INCLUDEDIR@/double-conversion")
|
||||
endif()
|
||||
|
||||
include("@CMAKE_INSTALL_FULL_LIBDIR@/cmake/double-conversion/double-conversionLibraryDepends.cmake")
|
||||
|
||||
set(double-conversion_LIBRARIES double-conversion)
|
@ -1,11 +0,0 @@
|
||||
set(PACKAGE_VERSION "@double-conversion_VERSION@")
|
||||
|
||||
# Check whether the requested PACKAGE_FIND_VERSION is compatible
|
||||
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
|
||||
set(PACKAGE_VERSION_COMPATIBLE FALSE)
|
||||
else()
|
||||
set(PACKAGE_VERSION_COMPATIBLE TRUE)
|
||||
if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
|
||||
set(PACKAGE_VERSION_EXACT TRUE)
|
||||
endif()
|
||||
endif()
|
@ -191,6 +191,11 @@ TEST(BignumDtoaVariousDoubles) {
|
||||
CHECK_EQ("35844466", buffer.start());
|
||||
CHECK_EQ(299, point);
|
||||
|
||||
BignumDtoa(1e-23, BIGNUM_DTOA_SHORTEST, 0,
|
||||
buffer, &length, &point);
|
||||
CHECK_EQ("1", buffer.start());
|
||||
CHECK_EQ(-22, point);
|
||||
|
||||
uint64_t smallest_normal64 = UINT64_2PART_C(0x00100000, 00000000);
|
||||
double v = Double(smallest_normal64).value();
|
||||
BignumDtoa(v, BIGNUM_DTOA_SHORTEST, 0, buffer, &length, &point);
|
||||
|
@ -35,6 +35,10 @@ TEST(DoubleToShortest) {
|
||||
CHECK(dc.ToShortest(1e21, &builder));
|
||||
CHECK_EQ("1e+21", builder.Finalize());
|
||||
|
||||
builder.Reset();
|
||||
CHECK(dc.ToShortest(1e-23, &builder));
|
||||
CHECK_EQ("1e-23", builder.Finalize());
|
||||
|
||||
builder.Reset();
|
||||
CHECK(dc.ToShortest(1e20, &builder));
|
||||
CHECK_EQ("100000000000000000000", builder.Finalize());
|
||||
@ -1720,9 +1724,10 @@ TEST(DoubleToStringJavaScript) {
|
||||
|
||||
static double StrToD16(const uc16* str16, int length, int flags,
|
||||
double empty_string_value,
|
||||
int* processed_characters_count, bool* processed_all) {
|
||||
int* processed_characters_count, bool* processed_all,
|
||||
uc16 separator = StringToDoubleConverter::kNoSeparator) {
|
||||
StringToDoubleConverter converter(flags, empty_string_value, Double::NaN(),
|
||||
NULL, NULL);
|
||||
NULL, NULL, separator);
|
||||
double result =
|
||||
converter.StringToDouble(str16, length, processed_characters_count);
|
||||
*processed_all = (length == *processed_characters_count);
|
||||
@ -1731,9 +1736,10 @@ static double StrToD16(const uc16* str16, int length, int flags,
|
||||
|
||||
|
||||
static double StrToD(const char* str, int flags, double empty_string_value,
|
||||
int* processed_characters_count, bool* processed_all) {
|
||||
int* processed_characters_count, bool* processed_all,
|
||||
uc16 separator = StringToDoubleConverter::kNoSeparator) {
|
||||
StringToDoubleConverter converter(flags, empty_string_value, Double::NaN(),
|
||||
NULL, NULL);
|
||||
NULL, NULL, separator);
|
||||
double result = converter.StringToDouble(str, strlen(str),
|
||||
processed_characters_count);
|
||||
*processed_all =
|
||||
@ -1748,7 +1754,8 @@ static double StrToD(const char* str, int flags, double empty_string_value,
|
||||
int processed_characters_count16;
|
||||
bool processed_all16;
|
||||
double result16 = StrToD16(buffer16, len, flags, empty_string_value,
|
||||
&processed_characters_count16, &processed_all16);
|
||||
&processed_characters_count16, &processed_all16,
|
||||
separator);
|
||||
CHECK_EQ(result, result16);
|
||||
CHECK_EQ(*processed_characters_count, processed_characters_count16);
|
||||
return result;
|
||||
@ -1804,6 +1811,18 @@ TEST(StringToDoubleVarious) {
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
|
||||
flags = StringToDoubleConverter::ALLOW_TRAILING_JUNK;
|
||||
|
||||
CHECK_EQ(123.0, StrToD("123e", flags, 0.0, &processed, &all_used));
|
||||
CHECK_EQ(processed, 3);
|
||||
|
||||
CHECK_EQ(123.0, StrToD("123e-", flags, 0.0, &processed, &all_used));
|
||||
CHECK_EQ(processed, 3);
|
||||
|
||||
CHECK_EQ(123.0, StrToD("123e-a", flags, 0.0, &processed, &all_used));
|
||||
CHECK_EQ(processed, 3);
|
||||
|
||||
|
||||
flags = StringToDoubleConverter::ALLOW_LEADING_SPACES |
|
||||
StringToDoubleConverter::ALLOW_SPACES_AFTER_SIGN |
|
||||
StringToDoubleConverter::ALLOW_TRAILING_SPACES |
|
||||
@ -2514,6 +2533,128 @@ TEST(StringToDoubleHexString) {
|
||||
CHECK_EQ(Double::NaN(), StrToD("x3", flags, 0.0,
|
||||
&processed, &all_used));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(-5.634002666912405e+27, StrToD("-0x123456789012345678901234",
|
||||
flags, 0.0,
|
||||
&processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(72057594037927940.0, StrToD("0x100000000000001", flags, 0.0,
|
||||
&processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(72057594037927940.0, StrToD("0x100000000000000", flags, 0.0,
|
||||
&processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(295147905179352830000.0, StrToD("0x100000000000000001", flags, 0.0,
|
||||
&processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(295147905179352830000.0, StrToD("0x100000000000000000", flags, 0.0,
|
||||
&processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(295147905179352900000.0, StrToD("0x100000000000008001", flags, 0.0,
|
||||
&processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(295147905179352830000.0, StrToD("0x100000000000008000", flags, 0.0,
|
||||
&processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(295147905179352960000.0, StrToD("0x100000000000018001", flags, 0.0,
|
||||
&processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(295147905179352960000.0, StrToD("0x100000000000018000", flags, 0.0,
|
||||
&processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
flags = StringToDoubleConverter::ALLOW_HEX_FLOATS;
|
||||
|
||||
CHECK_EQ(3.0, StrToD("0x3p0", flags, 0.0, &processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(0.0, StrToD("0x.0p0", flags, 0.0, &processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(3.0, StrToD("0x3.0p0", flags, 0.0, &processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(3.0, StrToD("0x3.p0", flags, 0.0, &processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(-5.634002666912405e+27, StrToD("-0x123456789012345678901234p0",
|
||||
flags, 0.0,
|
||||
&processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(72057594037927940.0, StrToD("0x100000000000001p0", flags, 0.0,
|
||||
&processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(72057594037927940.0, StrToD("0x100000000000000p0", flags, 0.0,
|
||||
&processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(295147905179352830000.0, StrToD("0x100000000000000001p0", flags, 0.0,
|
||||
&processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(295147905179352830000.0, StrToD("0x100000000000000000p0", flags, 0.0,
|
||||
&processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(295147905179352900000.0, StrToD("0x100000000000008001p0", flags, 0.0,
|
||||
&processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(295147905179352830000.0, StrToD("0x100000000000008000p0", flags, 0.0,
|
||||
&processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(295147905179352960000.0, StrToD("0x100000000000018001p0", flags, 0.0,
|
||||
&processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(295147905179352960000.0, StrToD("0x100000000000018000p0", flags, 0.0,
|
||||
&processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(4.722366482869645e+21, StrToD("0x100000000000000001p4", flags, 0.0,
|
||||
&processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(4.722366482869645e+21, StrToD("0x100000000000000000p+4", flags, 0.0,
|
||||
&processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(4.722366482869646e+21, StrToD("0x100000000000008001p04", flags, 0.0,
|
||||
&processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(18446744073709552000.0, StrToD("0x100000000000008000p-4", flags, 0.0,
|
||||
&processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(18446744073709560000.0, StrToD("0x100000000000018001p-04", flags, 0.0,
|
||||
&processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(4.722366482869647e+21, StrToD("0x100000000000018000p4", flags, 0.0,
|
||||
&processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(Double::Infinity(), StrToD("0x1p2000", flags, 0.0,
|
||||
&processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(0.0, StrToD("0x1p-2000", flags, 0.0, &processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(-0.0, StrToD("-0x1p-2000", flags, 0.0, &processed, &all_used));
|
||||
CHECK(all_used);
|
||||
}
|
||||
|
||||
|
||||
@ -3062,6 +3203,323 @@ TEST(StringToDoubleOctalString) {
|
||||
}
|
||||
|
||||
|
||||
TEST(StringToDoubleSeparator) {
|
||||
int flags;
|
||||
int processed;
|
||||
bool all_used;
|
||||
char separator;
|
||||
|
||||
separator = '\'';
|
||||
flags = StringToDoubleConverter::NO_FLAGS;
|
||||
|
||||
CHECK_EQ(1.0, StrToD("000'001.0'0", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(1.0, StrToD("0'0'0'0'0'1.0'0", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("'1.0", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("1'.0", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("1.'0", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("0''1.0", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("1.0e1'0", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("1.0e1'", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("1.0e'1", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("1.0'e1", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("+'1.0e1", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("-'1.0e1", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("1.0e+'1", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("1.0e-'1", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("1.0e'+1", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("1.0e'-1", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
separator = ' ';
|
||||
flags = StringToDoubleConverter::NO_FLAGS;
|
||||
|
||||
CHECK_EQ(1.0, StrToD("000 001.0 0", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(1.0, StrToD("0 0 0 0 0 1.0 0", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD(" 1.0", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("1 .0", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("1. 0", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("0 1.0", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("1.0e1 0", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("1.0e1 ", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("1.0e 1", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("1.0 e1", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("+ 1.0e1", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("- 1.0e1", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("1.0e+ 1", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("1.0e- 1", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("1.0e +1", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("1.0e -1", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
separator = ' ';
|
||||
flags = StringToDoubleConverter::ALLOW_LEADING_SPACES |
|
||||
StringToDoubleConverter::ALLOW_TRAILING_SPACES;
|
||||
|
||||
CHECK_EQ(1.0, StrToD("000 001.0 0", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(1.0, StrToD("0 0 0 0 0 1.0 0", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(1.0, StrToD(" 000 001.0 0 ", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(1.0, StrToD(" 0 0 0 0 0 1.0 0 ", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(1.0, StrToD(" 1.0", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("1 .0", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("1. 0", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("0 1.0", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("1.0e1 0", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(10.0, StrToD("1.0e1 ", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("1.0e 1", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("1.0 e1", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("+ 1.0e1", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("- 1.0e1", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("1.0e+ 1", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("1.0e- 1", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("1.0e +1", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("1.0e -1", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
separator = ' ';
|
||||
flags = StringToDoubleConverter::ALLOW_HEX |
|
||||
StringToDoubleConverter::ALLOW_HEX_FLOATS |
|
||||
StringToDoubleConverter::ALLOW_LEADING_SPACES |
|
||||
StringToDoubleConverter::ALLOW_TRAILING_SPACES;
|
||||
|
||||
CHECK_EQ(18.0, StrToD("0x1 2", flags, 0.0, &processed, &all_used, separator));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(0.0, StrToD("0x0 0", flags, 1.0, &processed, &all_used, separator));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(static_cast<double>(0x123456789),
|
||||
StrToD("0x1 2 3 4 5 6 7 8 9", flags, Double::NaN(),
|
||||
&processed, &all_used, separator));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(18.0, StrToD(" 0x1 2 ", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(0.0, StrToD(" 0x0 ", flags, 1.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(static_cast<double>(0x123456789),
|
||||
StrToD(" 0x1 2 3 4 5 6 7 8 9 ", flags, Double::NaN(),
|
||||
&processed, &all_used, separator));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(static_cast<double>(0xabcdef),
|
||||
StrToD("0xa b c d e f", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("0x 1 2", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("0 x0", flags, 1.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(),
|
||||
StrToD("0x1 2 3 4 5 6 7 8 9", flags, Double::NaN(),
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD(" 0 x1 2 ", flags, 0.0,
|
||||
&processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(3.0,
|
||||
StrToD("0x0 3p0", flags, 0.0, &processed, &all_used, separator));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(0.0,
|
||||
StrToD("0x.0 0p0", flags, 0.0, &processed, &all_used, separator));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(3.0,
|
||||
StrToD("0x3.0 0p0", flags, 0.0, &processed, &all_used, separator));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(3.0,
|
||||
StrToD("0x0 3.p0", flags, 0.0, &processed, &all_used, separator));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(Double::NaN(),
|
||||
StrToD("0x 3p0", flags, 0.0, &processed, &all_used));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(),
|
||||
StrToD("0x.0 p0", flags, 0.0, &processed, &all_used));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(),
|
||||
StrToD("0x3.0p0 0", flags, 0.0, &processed, &all_used));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(),
|
||||
StrToD("0x0 3.p 0", flags, 0.0, &processed, &all_used));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(),
|
||||
StrToD("0x3p+ 0", flags, 0.0, &processed, &all_used));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(),
|
||||
StrToD("0x.0p- 0", flags, 0.0, &processed, &all_used));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(),
|
||||
StrToD("0x3.0p +0", flags, 0.0, &processed, &all_used));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(),
|
||||
StrToD("0x0 3.p -0", flags, 0.0, &processed, &all_used));
|
||||
CHECK_EQ(0, processed);
|
||||
}
|
||||
|
||||
TEST(StringToDoubleSpecialValues) {
|
||||
int processed;
|
||||
int flags = StringToDoubleConverter::NO_FLAGS;
|
||||
@ -3184,10 +3642,10 @@ TEST(StringToDoubleCommentExamples) {
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(123.0, StrToD("123e", flags, 0.0, &processed, &all_used));
|
||||
CHECK(all_used);
|
||||
CHECK_EQ(processed, 3);
|
||||
|
||||
CHECK_EQ(123.0, StrToD("123e-", flags, 0.0, &processed, &all_used));
|
||||
CHECK(all_used);
|
||||
CHECK_EQ(processed, 3);
|
||||
|
||||
{
|
||||
StringToDoubleConverter converter(flags, 0.0, 1.0, "infinity", "NaN");
|
||||
@ -3235,6 +3693,28 @@ TEST(StringToDoubleCommentExamples) {
|
||||
|
||||
CHECK_EQ(Double::NaN(), StrToD("NaN", flags, 0.0, &processed, &all_used));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
flags = StringToDoubleConverter::NO_FLAGS;
|
||||
char separator = ' ';
|
||||
CHECK_EQ(1234.0,
|
||||
StrToD("1 2 3 4", flags, 0.0, &processed, &all_used, separator));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(Double::NaN(),
|
||||
StrToD("1 2", flags, 0.0, &processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(1000000.0,
|
||||
StrToD("1 000 000.0", flags, 0.0, &processed, &all_used, separator));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(1.0,
|
||||
StrToD("1.000 000", flags, 0.0, &processed, &all_used, separator));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(Double::NaN(),
|
||||
StrToD("1.0e1 000", flags, 0.0, &processed, &all_used, separator));
|
||||
CHECK_EQ(0, processed);
|
||||
}
|
||||
|
||||
|
||||
@ -3740,13 +4220,30 @@ TEST(StringToFloatHexString) {
|
||||
CHECK_EQ(5.0f, StrToF(" + 0x5 ", flags, 0.0f, &processed, &all_used));
|
||||
CHECK(all_used);
|
||||
|
||||
CHECK_EQ(Single::NaN(), StrToF("- -0x5", flags, 0.0f, &processed, &all_used));
|
||||
CHECK_EQ(Single::NaN(), StrToF("- -0x5", flags, 0.0f,
|
||||
&processed, &all_used));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Single::NaN(), StrToF("- +0x5", flags, 0.0f, &processed, &all_used));
|
||||
CHECK_EQ(Single::NaN(), StrToF("- +0x5", flags, 0.0f,
|
||||
&processed, &all_used));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Single::NaN(), StrToF("+ +0x5", flags, 0.0f, &processed, &all_used));
|
||||
CHECK_EQ(Single::NaN(), StrToF("+ +0x5", flags, 0.0f,
|
||||
&processed, &all_used));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Single::NaN(), StrToF("0x3p0", flags, 0.0f, &processed, &all_used));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Single::NaN(), StrToF("0x.0p0", flags, 0.0f, &processed, &all_used));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Single::NaN(), StrToF("0x3.0p0", flags, 0.0f,
|
||||
&processed, &all_used));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Single::NaN(), StrToF("0x3.p0", flags, 0.0f,
|
||||
&processed, &all_used));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
flags = StringToDoubleConverter::ALLOW_HEX;
|
||||
@ -3843,6 +4340,20 @@ TEST(StringToFloatHexString) {
|
||||
CHECK_EQ(Single::NaN(), StrToF("+ +0x5", flags, 0.0f, &processed, &all_used));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Single::NaN(), StrToF("0x3p0", flags, 0.0f, &processed, &all_used));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Single::NaN(), StrToF("0x.0p0", flags, 0.0f, &processed, &all_used));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Single::NaN(), StrToF("0x3.0p0", flags, 0.0f,
|
||||
&processed, &all_used));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(Single::NaN(), StrToF("0x3.p0", flags, 0.0f,
|
||||
&processed, &all_used));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
flags = StringToDoubleConverter::ALLOW_TRAILING_JUNK |
|
||||
StringToDoubleConverter::ALLOW_HEX;
|
||||
|
||||
@ -3965,6 +4476,19 @@ TEST(StringToFloatHexString) {
|
||||
CHECK_EQ(Single::NaN(), StrToF("+ +0x5", flags, 0.0f, &processed, &all_used));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(3.0f, StrToF("0x3p0", flags, 0.0f, &processed, &all_used));
|
||||
CHECK_EQ(3, processed);
|
||||
|
||||
CHECK_EQ(Single::NaN(), StrToF("0x.0p0", flags, 0.0f, &processed, &all_used));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(3.0f, StrToF("0x3.0p0", flags, 0.0f, &processed, &all_used));
|
||||
CHECK_EQ(3, processed);
|
||||
|
||||
CHECK_EQ(3.0f, StrToF("0x3.p0", flags, 0.0f, &processed, &all_used));
|
||||
CHECK_EQ(3, processed);
|
||||
|
||||
|
||||
flags = StringToDoubleConverter::ALLOW_TRAILING_JUNK |
|
||||
StringToDoubleConverter::ALLOW_LEADING_SPACES |
|
||||
StringToDoubleConverter::ALLOW_TRAILING_SPACES |
|
||||
@ -4710,3 +5234,46 @@ TEST(StringToDoubleFloatWhitespace) {
|
||||
&processed, &all_used));
|
||||
CHECK(all_used);
|
||||
}
|
||||
|
||||
|
||||
TEST(StringToDoubleCaseInsensitiveSpecialValues) {
|
||||
int processed = 0;
|
||||
|
||||
int flags = StringToDoubleConverter::ALLOW_CASE_INSENSIBILITY |
|
||||
StringToDoubleConverter::ALLOW_LEADING_SPACES |
|
||||
StringToDoubleConverter::ALLOW_TRAILING_JUNK |
|
||||
StringToDoubleConverter::ALLOW_TRAILING_SPACES;
|
||||
|
||||
// Use 1.0 as junk_string_value.
|
||||
StringToDoubleConverter converter(flags, 0.0, 1.0, "infinity", "nan");
|
||||
|
||||
CHECK_EQ(Double::NaN(), converter.StringToDouble("+nan", 4, &processed));
|
||||
CHECK_EQ(4, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), converter.StringToDouble("-nAN", 4, &processed));
|
||||
CHECK_EQ(4, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), converter.StringToDouble("nAN", 3, &processed));
|
||||
CHECK_EQ(3, processed);
|
||||
|
||||
CHECK_EQ(Double::NaN(), converter.StringToDouble("nANabc", 6, &processed));
|
||||
CHECK_EQ(3, processed);
|
||||
|
||||
CHECK_EQ(+Double::Infinity(),
|
||||
converter.StringToDouble("+Infinity", 9, &processed));
|
||||
CHECK_EQ(9, processed);
|
||||
|
||||
CHECK_EQ(-Double::Infinity(),
|
||||
converter.StringToDouble("-INFinity", 9, &processed));
|
||||
CHECK_EQ(9, processed);
|
||||
|
||||
CHECK_EQ(Double::Infinity(),
|
||||
converter.StringToDouble("infINITY", 8, &processed));
|
||||
CHECK_EQ(8, processed);
|
||||
|
||||
CHECK_EQ(1.0, converter.StringToDouble("INF", 3, &processed));
|
||||
CHECK_EQ(0, processed);
|
||||
|
||||
CHECK_EQ(1.0, converter.StringToDouble("+inf", 4, &processed));
|
||||
CHECK_EQ(0, processed);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user