From 5d6b2651c9ebdccf04ab99083cbf24919ebf25b9 Mon Sep 17 00:00:00 2001 From: "Paul J. Davis" Date: Wed, 15 Jul 2015 15:27:04 -0500 Subject: [PATCH] Update double-conversion to latest master --- c_src/double-conversion/AUTHORS | 2 + c_src/double-conversion/DOWNLOADED | 3 - c_src/double-conversion/README | 45 +++- c_src/double-conversion/VERSION | 2 + c_src/double-conversion/bignum-dtoa.cc | 11 +- c_src/double-conversion/bignum-dtoa.h | 2 +- c_src/double-conversion/bignum.cc | 30 +-- c_src/double-conversion/bignum.h | 3 +- c_src/double-conversion/cached-powers.cc | 3 +- c_src/double-conversion/diy-fp.cc | 4 +- c_src/double-conversion/diy-fp.h | 24 +- c_src/double-conversion/double-conversion.cc | 221 +++++++++++++------ c_src/double-conversion/double-conversion.h | 35 +-- c_src/double-conversion/fast-dtoa.cc | 21 +- c_src/double-conversion/fast-dtoa.h | 2 +- c_src/double-conversion/fixed-dtoa.cc | 12 +- c_src/double-conversion/fixed-dtoa.h | 2 +- c_src/double-conversion/ieee.h | 4 + c_src/double-conversion/strtod.cc | 5 +- c_src/double-conversion/strtod.h | 2 +- c_src/double-conversion/utils.h | 43 ++-- 21 files changed, 315 insertions(+), 161 deletions(-) delete mode 100644 c_src/double-conversion/DOWNLOADED create mode 100644 c_src/double-conversion/VERSION diff --git a/c_src/double-conversion/AUTHORS b/c_src/double-conversion/AUTHORS index ff2a5f4..88b38ae 100644 --- a/c_src/double-conversion/AUTHORS +++ b/c_src/double-conversion/AUTHORS @@ -10,3 +10,5 @@ Mozilla Foundation Jeff Muizelaar Mike Hommey Martin Olsson +Kent Williams +Elan Ruusamäe diff --git a/c_src/double-conversion/DOWNLOADED b/c_src/double-conversion/DOWNLOADED deleted file mode 100644 index 64724d8..0000000 --- a/c_src/double-conversion/DOWNLOADED +++ /dev/null @@ -1,3 +0,0 @@ -Downloaded: 2013-02-24 - -https://double-conversion.googlecode.com/files/double-conversion-1.1.1.tar.gz diff --git a/c_src/double-conversion/README b/c_src/double-conversion/README index f186b42..fc54116 100644 --- a/c_src/double-conversion/README +++ b/c_src/double-conversion/README @@ -1,4 +1,4 @@ -http://code.google.com/p/double-conversion +https://github.com/google/double-conversion/ This project (double-conversion) provides binary-decimal and decimal-binary routines for IEEE doubles. @@ -9,3 +9,46 @@ it can be used more easily in other projects. There is extensive documentation in src/double-conversion.h. Other examples can be found in test/cctest/test-conversions.cc. + + +Building +======== + +This library can be built with scons [0] or cmake [1]. +The checked-in Makefile simply forwards to scons, and provides a +shortcut to run all tests: + + make + make test + +Scons +----- + +The easiest way to install this library is to use `scons`. It builds +the static and shared library, and is set up to install those at the +correct locations: + + scons install + +Use the `DESTDIR` option to change the target directory: + + scons DESTDIR=alternative_directory install + +Cmake +----- + +To use cmake run `cmake .` in the root directory. This overwrites the +existing Makefile. + +Use `-DBUILD_SHARED_LIBS=ON` to enable the compilation of shared libraries. +Note that this disables static libraries. There is currently no way to +build both libraries at the same time with cmake. + +Use `-DBUILD_TESTING=ON` to build the test executable. + + cmake . -DBUILD_TESTING=ON + make + test/cctest/cctest --list | tr -d '<' | xargs test/cctest/cctest + +[0]: http://www.scons.org +[1]: http://www.cmake.org diff --git a/c_src/double-conversion/VERSION b/c_src/double-conversion/VERSION new file mode 100644 index 0000000..2adab47 --- /dev/null +++ b/c_src/double-conversion/VERSION @@ -0,0 +1,2 @@ +Clone from: https://github.com/google/double-conversion +Version: v2.0.1-23-gc3e0c97 diff --git a/c_src/double-conversion/bignum-dtoa.cc b/c_src/double-conversion/bignum-dtoa.cc index b6c2e85..f1ad7a5 100644 --- a/c_src/double-conversion/bignum-dtoa.cc +++ b/c_src/double-conversion/bignum-dtoa.cc @@ -192,13 +192,13 @@ static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator, delta_plus = delta_minus; } *length = 0; - while (true) { + for (;;) { uint16_t digit; digit = numerator->DivideModuloIntBignum(*denominator); ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive. // digit = numerator / denominator (integer division). // numerator = numerator % denominator. - buffer[(*length)++] = digit + '0'; + buffer[(*length)++] = static_cast(digit + '0'); // Can we stop already? // If the remainder of the division is less than the distance to the lower @@ -282,7 +282,7 @@ static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator, // exponent (decimal_point), when rounding upwards. static void GenerateCountedDigits(int count, int* decimal_point, Bignum* numerator, Bignum* denominator, - Vector(buffer), int* length) { + Vector buffer, int* length) { ASSERT(count >= 0); for (int i = 0; i < count - 1; ++i) { uint16_t digit; @@ -290,7 +290,7 @@ static void GenerateCountedDigits(int count, int* decimal_point, ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive. // digit = numerator / denominator (integer division). // numerator = numerator % denominator. - buffer[i] = digit + '0'; + buffer[i] = static_cast(digit + '0'); // Prepare for next iteration. numerator->Times10(); } @@ -300,7 +300,8 @@ static void GenerateCountedDigits(int count, int* decimal_point, if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) { digit++; } - buffer[count - 1] = digit + '0'; + ASSERT(digit <= 10); + buffer[count - 1] = static_cast(digit + '0'); // Correct bad digits (in case we had a sequence of '9's). Propagate the // carry until we hat a non-'9' or til we reach the first digit. for (int i = count - 1; i > 0; --i) { diff --git a/c_src/double-conversion/bignum-dtoa.h b/c_src/double-conversion/bignum-dtoa.h index 34b9619..92455ec 100644 --- a/c_src/double-conversion/bignum-dtoa.h +++ b/c_src/double-conversion/bignum-dtoa.h @@ -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 { diff --git a/c_src/double-conversion/bignum.cc b/c_src/double-conversion/bignum.cc index 3c88303..89c0ab2 100644 --- a/c_src/double-conversion/bignum.cc +++ b/c_src/double-conversion/bignum.cc @@ -25,8 +25,8 @@ // (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 { @@ -40,6 +40,7 @@ Bignum::Bignum() template static int BitSize(S value) { + (void) value; // Mark variable as used. return 8 * sizeof(value); } @@ -103,7 +104,7 @@ void Bignum::AssignDecimalString(Vector value) { const int kMaxUint64DecimalDigits = 19; Zero(); int length = value.length(); - unsigned int pos = 0; + int pos = 0; // Let's just say that each digit needs 4 bits. while (length >= kMaxUint64DecimalDigits) { uint64_t digits = ReadUInt64(value, pos, kMaxUint64DecimalDigits); @@ -122,9 +123,8 @@ void Bignum::AssignDecimalString(Vector value) { static int HexCharValue(char c) { if ('0' <= c && c <= '9') return c - '0'; if ('a' <= c && c <= 'f') return 10 + c - 'a'; - if ('A' <= c && c <= 'F') return 10 + c - 'A'; - UNREACHABLE(); - return 0; // To make compiler happy. + ASSERT('A' <= c && c <= 'F'); + return 10 + c - 'A'; } @@ -501,13 +501,14 @@ uint16_t Bignum::DivideModuloIntBignum(const Bignum& other) { // Start by removing multiples of 'other' until both numbers have the same // number of digits. while (BigitLength() > other.BigitLength()) { - // This naive approach is extremely inefficient if the this divided other - // might be big. This function is implemented for doubleToString where + // This naive approach is extremely inefficient if `this` divided by other + // is big. This function is implemented for doubleToString where // the result should be small (less than 10). ASSERT(other.bigits_[other.used_digits_ - 1] >= ((1 << kBigitSize) / 16)); + ASSERT(bigits_[used_digits_ - 1] < 0x10000); // Remove the multiples of the first digit. // Example this = 23 and other equals 9. -> Remove 2 multiples. - result += bigits_[used_digits_ - 1]; + result += static_cast(bigits_[used_digits_ - 1]); SubtractTimes(other, bigits_[used_digits_ - 1]); } @@ -523,13 +524,15 @@ uint16_t Bignum::DivideModuloIntBignum(const Bignum& other) { // Shortcut for easy (and common) case. int quotient = this_bigit / other_bigit; bigits_[used_digits_ - 1] = this_bigit - other_bigit * quotient; - result += quotient; + ASSERT(quotient < 0x10000); + result += static_cast(quotient); Clamp(); return result; } int division_estimate = this_bigit / (other_bigit + 1); - result += division_estimate; + ASSERT(division_estimate < 0x10000); + result += static_cast(division_estimate); SubtractTimes(other, division_estimate); if (other_bigit * (division_estimate + 1) > this_bigit) { @@ -560,8 +563,8 @@ static int SizeInHexChars(S number) { static char HexCharOfValue(int value) { ASSERT(0 <= value && value <= 16); - if (value < 10) return value + '0'; - return value - 10 + 'A'; + if (value < 10) return static_cast(value + '0'); + return static_cast(value - 10 + 'A'); } @@ -755,7 +758,6 @@ void Bignum::SubtractTimes(const Bignum& other, int factor) { Chunk difference = bigits_[i] - borrow; bigits_[i] = difference & kBigitMask; borrow = difference >> (kChunkSize - 1); - ++i; } Clamp(); } diff --git a/c_src/double-conversion/bignum.h b/c_src/double-conversion/bignum.h index 5ec3544..57e4230 100644 --- a/c_src/double-conversion/bignum.h +++ b/c_src/double-conversion/bignum.h @@ -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 { @@ -49,7 +49,6 @@ class Bignum { void AssignPowerUInt16(uint16_t base, int exponent); - void AddUInt16(uint16_t operand); void AddUInt64(uint64_t operand); void AddBignum(const Bignum& other); // Precondition: this >= other. diff --git a/c_src/double-conversion/cached-powers.cc b/c_src/double-conversion/cached-powers.cc index c676429..6cbc09b 100644 --- a/c_src/double-conversion/cached-powers.cc +++ b/c_src/double-conversion/cached-powers.cc @@ -29,7 +29,7 @@ #include #include -#include "utils.h" +#include "double-conversion/utils.h" #include "cached-powers.h" @@ -152,6 +152,7 @@ void PowersOfTenCache::GetCachedPowerForBinaryExponentRange( ASSERT(0 <= index && index < kCachedPowersLength); CachedPower cached_power = kCachedPowers[index]; ASSERT(min_exponent <= cached_power.binary_exponent); + (void) max_exponent; // Mark variable as used. ASSERT(cached_power.binary_exponent <= max_exponent); *decimal_exponent = cached_power.decimal_exponent; *power = DiyFp(cached_power.significand, cached_power.binary_exponent); diff --git a/c_src/double-conversion/diy-fp.cc b/c_src/double-conversion/diy-fp.cc index ddd1891..60b805e 100644 --- a/c_src/double-conversion/diy-fp.cc +++ b/c_src/double-conversion/diy-fp.cc @@ -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 { diff --git a/c_src/double-conversion/diy-fp.h b/c_src/double-conversion/diy-fp.h index 9dcf8fb..a0c0c15 100644 --- a/c_src/double-conversion/diy-fp.h +++ b/c_src/double-conversion/diy-fp.h @@ -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 { @@ -42,7 +42,7 @@ class DiyFp { static const int kSignificandSize = 64; DiyFp() : f_(0), e_(0) {} - DiyFp(uint64_t f, int e) : f_(f), e_(e) {} + DiyFp(uint64_t significand, int exponent) : f_(significand), e_(exponent) {} // this = this - other. // The exponents of both numbers must be the same and the significand of this @@ -76,22 +76,22 @@ class DiyFp { void Normalize() { ASSERT(f_ != 0); - uint64_t f = f_; - int e = e_; + uint64_t significand = f_; + int exponent = e_; // This method is mainly called for normalizing boundaries. In general // boundaries need to be shifted by 10 bits. We thus optimize for this case. const uint64_t k10MSBits = UINT64_2PART_C(0xFFC00000, 00000000); - while ((f & k10MSBits) == 0) { - f <<= 10; - e -= 10; + while ((significand & k10MSBits) == 0) { + significand <<= 10; + exponent -= 10; } - while ((f & kUint64MSB) == 0) { - f <<= 1; - e--; + while ((significand & kUint64MSB) == 0) { + significand <<= 1; + exponent--; } - f_ = f; - e_ = e; + f_ = significand; + e_ = exponent; } static DiyFp Normalize(const DiyFp& a) { diff --git a/c_src/double-conversion/double-conversion.cc b/c_src/double-conversion/double-conversion.cc index a79fe92..a6fc0de 100644 --- a/c_src/double-conversion/double-conversion.cc +++ b/c_src/double-conversion/double-conversion.cc @@ -28,14 +28,14 @@ #include #include -#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 { @@ -348,7 +348,6 @@ static BignumDtoaMode DtoaToBignumDtoaMode( case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISION; default: UNREACHABLE(); - return BIGNUM_DTOA_SHORTEST; // To silence compiler. } } @@ -403,8 +402,8 @@ void DoubleToStringConverter::DoubleToAscii(double v, vector, length, point); break; default: - UNREACHABLE(); fast_worked = false; + UNREACHABLE(); } if (fast_worked) return; @@ -417,8 +416,9 @@ void DoubleToStringConverter::DoubleToAscii(double v, // Consumes the given substring from the iterator. // Returns false, if the substring does not match. -static bool ConsumeSubString(const char** current, - const char* end, +template +static bool ConsumeSubString(Iterator* current, + Iterator end, const char* substring) { ASSERT(**current == *substring); for (substring++; *substring != '\0'; substring++) { @@ -440,10 +440,36 @@ static bool ConsumeSubString(const char** current, const int kMaxSignificantDigits = 772; +static const char kWhitespaceTable7[] = { 32, 13, 10, 9, 11, 12 }; +static const int kWhitespaceTable7Length = ARRAY_SIZE(kWhitespaceTable7); + + +static const uc16 kWhitespaceTable16[] = { + 160, 8232, 8233, 5760, 6158, 8192, 8193, 8194, 8195, + 8196, 8197, 8198, 8199, 8200, 8201, 8202, 8239, 8287, 12288, 65279 +}; +static const int kWhitespaceTable16Length = ARRAY_SIZE(kWhitespaceTable16); + + +static bool isWhitespace(int x) { + if (x < 128) { + for (int i = 0; i < kWhitespaceTable7Length; i++) { + if (kWhitespaceTable7[i] == x) return true; + } + } else { + for (int i = 0; i < kWhitespaceTable16Length; i++) { + if (kWhitespaceTable16[i] == x) return true; + } + } + return false; +} + + // Returns true if a nonspace found and false if the end has reached. -static inline bool AdvanceToNonspace(const char** current, const char* end) { +template +static inline bool AdvanceToNonspace(Iterator* current, Iterator end) { while (*current != end) { - if (**current != ' ') return true; + if (!isWhitespace(**current)) return true; ++*current; } return false; @@ -462,26 +488,57 @@ static double SignedZero(bool sign) { } +// Returns true if 'c' is a decimal digit that is valid for the given radix. +// +// The function is small and could be inlined, but VS2012 emitted a warning +// because it constant-propagated the radix and concluded that the last +// condition was always true. By moving it into a separate function the +// compiler wouldn't warn anymore. +#if _MSC_VER +#pragma optimize("",off) +static bool IsDecimalDigitForRadix(int c, int radix) { + return '0' <= c && c <= '9' && (c - '0') < radix; +} +#pragma optimize("",on) +#else +static bool inline IsDecimalDigitForRadix(int c, int radix) { + return '0' <= c && c <= '9' && (c - '0') < radix; +} +#endif +// Returns true if 'c' is a character digit that is valid for the given radix. +// The 'a_character' should be 'a' or 'A'. +// +// The function is small and could be inlined, but VS2012 emitted a warning +// because it constant-propagated the radix and concluded that the first +// condition was always false. By moving it into a separate function the +// compiler wouldn't warn anymore. +static bool IsCharacterDigitForRadix(int c, int radix, char a_character) { + return radix > 10 && c >= a_character && c < a_character + radix - 10; +} + + // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end. -template -static double RadixStringToIeee(const char* current, - const char* end, +template +static double RadixStringToIeee(Iterator* current, + Iterator end, bool sign, bool allow_trailing_junk, double junk_string_value, bool read_as_double, - const char** trailing_pointer) { - ASSERT(current != end); + bool* result_is_junk) { + ASSERT(*current != end); const int kDoubleSize = Double::kSignificandSize; const int kSingleSize = Single::kSignificandSize; const int kSignificandSize = read_as_double? kDoubleSize: kSingleSize; + *result_is_junk = true; + // Skip leading 0s. - while (*current == '0') { - ++current; - if (current == end) { - *trailing_pointer = end; + while (**current == '0') { + ++(*current); + if (*current == end) { + *result_is_junk = false; return SignedZero(sign); } } @@ -492,14 +549,14 @@ static double RadixStringToIeee(const char* current, do { int digit; - if (*current >= '0' && *current <= '9' && *current < '0' + radix) { - digit = static_cast(*current) - '0'; - } else if (radix > 10 && *current >= 'a' && *current < 'a' + radix - 10) { - digit = static_cast(*current) - 'a' + 10; - } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) { - digit = static_cast(*current) - 'A' + 10; + if (IsDecimalDigitForRadix(**current, radix)) { + digit = static_cast(**current) - '0'; + } else if (IsCharacterDigitForRadix(**current, radix, 'a')) { + digit = static_cast(**current) - 'a' + 10; + } else if (IsCharacterDigitForRadix(**current, radix, 'A')) { + digit = static_cast(**current) - 'A' + 10; } else { - if (allow_trailing_junk || !AdvanceToNonspace(¤t, end)) { + if (allow_trailing_junk || !AdvanceToNonspace(current, end)) { break; } else { return junk_string_value; @@ -523,14 +580,14 @@ static double RadixStringToIeee(const char* current, exponent = overflow_bits_count; bool zero_tail = true; - while (true) { - ++current; - if (current == end || !isDigit(*current, radix)) break; - zero_tail = zero_tail && *current == '0'; + for (;;) { + ++(*current); + if (*current == end || !isDigit(**current, radix)) break; + zero_tail = zero_tail && **current == '0'; exponent += radix_log_2; } - if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { + if (!allow_trailing_junk && AdvanceToNonspace(current, end)) { return junk_string_value; } @@ -552,13 +609,13 @@ static double RadixStringToIeee(const char* current, } break; } - ++current; - } while (current != end); + ++(*current); + } while (*current != end); ASSERT(number < ((int64_t)1 << kSignificandSize)); ASSERT(static_cast(static_cast(number)) == number); - *trailing_pointer = current; + *result_is_junk = false; if (exponent == 0) { if (sign) { @@ -573,13 +630,14 @@ static double RadixStringToIeee(const char* current, } +template double StringToDoubleConverter::StringToIeee( - const char* input, + Iterator input, int length, - int* processed_characters_count, - bool read_as_double) { - const char* current = input; - const char* end = input + length; + bool read_as_double, + int* processed_characters_count) const { + Iterator current = input; + Iterator end = input + length; *processed_characters_count = 0; @@ -600,7 +658,7 @@ double StringToDoubleConverter::StringToIeee( if (allow_leading_spaces || allow_trailing_spaces) { if (!AdvanceToNonspace(¤t, end)) { - *processed_characters_count = current - input; + *processed_characters_count = static_cast(current - input); return empty_string_value_; } if (!allow_leading_spaces && (input != current)) { @@ -626,7 +684,7 @@ double StringToDoubleConverter::StringToIeee( if (*current == '+' || *current == '-') { sign = (*current == '-'); ++current; - const char* next_non_space = current; + Iterator next_non_space = current; // Skip following spaces (if allowed). if (!AdvanceToNonspace(&next_non_space, end)) return junk_string_value_; if (!allow_spaces_after_sign && (current != next_non_space)) { @@ -649,7 +707,7 @@ double StringToDoubleConverter::StringToIeee( } ASSERT(buffer_pos == 0); - *processed_characters_count = current - input; + *processed_characters_count = static_cast(current - input); return sign ? -Double::Infinity() : Double::Infinity(); } } @@ -668,7 +726,7 @@ double StringToDoubleConverter::StringToIeee( } ASSERT(buffer_pos == 0); - *processed_characters_count = current - input; + *processed_characters_count = static_cast(current - input); return sign ? -Double::NaN() : Double::NaN(); } } @@ -677,7 +735,7 @@ double StringToDoubleConverter::StringToIeee( if (*current == '0') { ++current; if (current == end) { - *processed_characters_count = current - input; + *processed_characters_count = static_cast(current - input); return SignedZero(sign); } @@ -690,17 +748,17 @@ double StringToDoubleConverter::StringToIeee( return junk_string_value_; // "0x". } - const char* tail_pointer = NULL; - double result = RadixStringToIeee<4>(current, + bool result_is_junk; + double result = RadixStringToIeee<4>(¤t, end, sign, allow_trailing_junk, junk_string_value_, read_as_double, - &tail_pointer); - if (tail_pointer != NULL) { - if (allow_trailing_spaces) AdvanceToNonspace(&tail_pointer, end); - *processed_characters_count = tail_pointer - input; + &result_is_junk); + if (!result_is_junk) { + if (allow_trailing_spaces) AdvanceToNonspace(¤t, end); + *processed_characters_count = static_cast(current - input); } return result; } @@ -709,7 +767,7 @@ double StringToDoubleConverter::StringToIeee( while (*current == '0') { ++current; if (current == end) { - *processed_characters_count = current - input; + *processed_characters_count = static_cast(current - input); return SignedZero(sign); } } @@ -757,7 +815,7 @@ double StringToDoubleConverter::StringToIeee( while (*current == '0') { ++current; if (current == end) { - *processed_characters_count = current - input; + *processed_characters_count = static_cast(current - input); return SignedZero(sign); } exponent--; // Move this 0 into the exponent. @@ -801,9 +859,9 @@ double StringToDoubleConverter::StringToIeee( return junk_string_value_; } } - char sign = '+'; + char exponen_sign = '+'; if (*current == '+' || *current == '-') { - sign = static_cast(*current); + exponen_sign = static_cast(*current); ++current; if (current == end) { if (allow_trailing_junk) { @@ -837,7 +895,7 @@ double StringToDoubleConverter::StringToIeee( ++current; } while (current != end && *current >= '0' && *current <= '9'); - exponent += (sign == '-' ? -num : num); + exponent += (exponen_sign == '-' ? -num : num); } if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) { @@ -855,16 +913,17 @@ double StringToDoubleConverter::StringToIeee( if (octal) { double result; - const char* tail_pointer = NULL; - result = RadixStringToIeee<3>(buffer, + bool result_is_junk; + char* start = buffer; + result = RadixStringToIeee<3>(&start, buffer + buffer_pos, sign, allow_trailing_junk, junk_string_value_, read_as_double, - &tail_pointer); - ASSERT(tail_pointer != NULL); - *processed_characters_count = current - input; + &result_is_junk); + ASSERT(!result_is_junk); + *processed_characters_count = static_cast(current - input); return result; } @@ -882,8 +941,42 @@ double StringToDoubleConverter::StringToIeee( } else { converted = Strtof(Vector(buffer, buffer_pos), exponent); } - *processed_characters_count = current - input; + *processed_characters_count = static_cast(current - input); return sign? -converted: converted; } + +double StringToDoubleConverter::StringToDouble( + const char* buffer, + int length, + int* processed_characters_count) const { + return StringToIeee(buffer, length, true, processed_characters_count); +} + + +double StringToDoubleConverter::StringToDouble( + const uc16* buffer, + int length, + int* processed_characters_count) const { + return StringToIeee(buffer, length, true, processed_characters_count); +} + + +float StringToDoubleConverter::StringToFloat( + const char* buffer, + int length, + int* processed_characters_count) const { + return static_cast(StringToIeee(buffer, length, false, + processed_characters_count)); +} + + +float StringToDoubleConverter::StringToFloat( + const uc16* buffer, + int length, + int* processed_characters_count) const { + return static_cast(StringToIeee(buffer, length, false, + processed_characters_count)); +} + } // namespace double_conversion diff --git a/c_src/double-conversion/double-conversion.h b/c_src/double-conversion/double-conversion.h index f98edae..11fbcb8 100644 --- a/c_src/double-conversion/double-conversion.h +++ b/c_src/double-conversion/double-conversion.h @@ -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 { @@ -415,9 +415,10 @@ class StringToDoubleConverter { // junk, too. // - ALLOW_TRAILING_JUNK: ignore trailing characters that are not part of // a double literal. - // - ALLOW_LEADING_SPACES: skip over leading spaces. - // - ALLOW_TRAILING_SPACES: ignore trailing spaces. - // - ALLOW_SPACES_AFTER_SIGN: ignore spaces after the sign. + // - ALLOW_LEADING_SPACES: skip over leading whitespace, including spaces, + // new-lines, and tabs. + // - ALLOW_TRAILING_SPACES: ignore trailing whitespace. + // - ALLOW_SPACES_AFTER_SIGN: ignore whitespace after the sign. // Ex: StringToDouble("- 123.2") -> -123.2. // StringToDouble("+ 123.2") -> 123.2 // @@ -502,19 +503,24 @@ class StringToDoubleConverter { // in the 'processed_characters_count'. Trailing junk is never included. double StringToDouble(const char* buffer, int length, - int* processed_characters_count) { - return StringToIeee(buffer, length, processed_characters_count, true); - } + int* processed_characters_count) const; + + // Same as StringToDouble above but for 16 bit characters. + double StringToDouble(const uc16* buffer, + int length, + int* processed_characters_count) const; // Same as StringToDouble but reads a float. // Note that this is not equivalent to static_cast(StringToDouble(...)) // due to potential double-rounding. float StringToFloat(const char* buffer, int length, - int* processed_characters_count) { - return static_cast(StringToIeee(buffer, length, - processed_characters_count, false)); - } + int* processed_characters_count) const; + + // Same as StringToFloat above but for 16 bit characters. + float StringToFloat(const uc16* buffer, + int length, + int* processed_characters_count) const; private: const int flags_; @@ -523,10 +529,11 @@ class StringToDoubleConverter { const char* const infinity_symbol_; const char* const nan_symbol_; - double StringToIeee(const char* buffer, + template + double StringToIeee(Iterator start_pointer, int length, - int* processed_characters_count, - bool read_as_double); + bool read_as_double, + int* processed_characters_count) const; DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter); }; diff --git a/c_src/double-conversion/fast-dtoa.cc b/c_src/double-conversion/fast-dtoa.cc index b2f7b8d..6135038 100644 --- a/c_src/double-conversion/fast-dtoa.cc +++ b/c_src/double-conversion/fast-dtoa.cc @@ -248,13 +248,8 @@ static void BiggestPowerTen(uint32_t number, // Note: kPowersOf10[i] == 10^(i-1). exponent_plus_one_guess++; // We don't have any guarantees that 2^number_bits <= number. - // TODO(floitsch): can we change the 'while' into an 'if'? We definitely see - // number < (2^number_bits - 1), but I haven't encountered - // number < (2^number_bits - 2) yet. - while (number < kSmallPowersOfTen[exponent_plus_one_guess]) { + if (number < kSmallPowersOfTen[exponent_plus_one_guess]) { exponent_plus_one_guess--; - if (exponent_plus_one_guess <= 0) - break; } *power = kSmallPowersOfTen[exponent_plus_one_guess]; *exponent_plus_one = exponent_plus_one_guess; @@ -352,7 +347,8 @@ static bool DigitGen(DiyFp low, // that is smaller than integrals. while (*kappa > 0) { int digit = integrals / divisor; - buffer[*length] = '0' + digit; + ASSERT(digit <= 9); + buffer[*length] = static_cast('0' + digit); (*length)++; integrals %= divisor; (*kappa)--; @@ -381,13 +377,14 @@ static bool DigitGen(DiyFp low, ASSERT(one.e() >= -60); ASSERT(fractionals < one.f()); ASSERT(UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF) / 10 >= one.f()); - while (true) { + for (;;) { fractionals *= 10; unit *= 10; unsafe_interval.set_f(unsafe_interval.f() * 10); // Integer division by one. int digit = static_cast(fractionals >> -one.e()); - buffer[*length] = '0' + digit; + ASSERT(digit <= 9); + buffer[*length] = static_cast('0' + digit); (*length)++; fractionals &= one.f() - 1; // Modulo by one. (*kappa)--; @@ -461,7 +458,8 @@ static bool DigitGenCounted(DiyFp w, // that is smaller than 'integrals'. while (*kappa > 0) { int digit = integrals / divisor; - buffer[*length] = '0' + digit; + ASSERT(digit <= 9); + buffer[*length] = static_cast('0' + digit); (*length)++; requested_digits--; integrals %= divisor; @@ -494,7 +492,8 @@ static bool DigitGenCounted(DiyFp w, w_error *= 10; // Integer division by one. int digit = static_cast(fractionals >> -one.e()); - buffer[*length] = '0' + digit; + ASSERT(digit <= 9); + buffer[*length] = static_cast('0' + digit); (*length)++; requested_digits--; fractionals &= one.f() - 1; // Modulo by one. diff --git a/c_src/double-conversion/fast-dtoa.h b/c_src/double-conversion/fast-dtoa.h index 5f1e8ee..259ee3a 100644 --- a/c_src/double-conversion/fast-dtoa.h +++ b/c_src/double-conversion/fast-dtoa.h @@ -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 { diff --git a/c_src/double-conversion/fixed-dtoa.cc b/c_src/double-conversion/fixed-dtoa.cc index d56b144..aef65fd 100644 --- a/c_src/double-conversion/fixed-dtoa.cc +++ b/c_src/double-conversion/fixed-dtoa.cc @@ -133,7 +133,7 @@ static void FillDigits32(uint32_t number, Vector buffer, int* length) { while (number != 0) { int digit = number % 10; number /= 10; - buffer[(*length) + number_length] = '0' + digit; + buffer[(*length) + number_length] = static_cast('0' + digit); number_length++; } // Exchange the digits. @@ -150,7 +150,7 @@ static void FillDigits32(uint32_t number, Vector buffer, int* length) { } -static void FillDigits64FixedLength(uint64_t number, int requested_length, +static void FillDigits64FixedLength(uint64_t number, Vector buffer, int* length) { const uint32_t kTen7 = 10000000; // For efficiency cut the number into 3 uint32_t parts, and print those. @@ -253,7 +253,8 @@ static void FillFractionals(uint64_t fractionals, int exponent, fractionals *= 5; point--; int digit = static_cast(fractionals >> point); - buffer[*length] = '0' + digit; + ASSERT(digit <= 9); + buffer[*length] = static_cast('0' + digit); (*length)++; fractionals -= static_cast(digit) << point; } @@ -274,7 +275,8 @@ static void FillFractionals(uint64_t fractionals, int exponent, fractionals128.Multiply(5); point--; int digit = fractionals128.DivModPowerOf2(point); - buffer[*length] = '0' + digit; + ASSERT(digit <= 9); + buffer[*length] = static_cast('0' + digit); (*length)++; } if (fractionals128.BitAt(point - 1) == 1) { @@ -358,7 +360,7 @@ bool FastFixedDtoa(double v, remainder = (dividend % divisor) << exponent; } FillDigits32(quotient, buffer, length); - FillDigits64FixedLength(remainder, divisor_power, buffer, length); + FillDigits64FixedLength(remainder, buffer, length); *decimal_point = *length; } else if (exponent >= 0) { // 0 <= exponent <= 11 diff --git a/c_src/double-conversion/fixed-dtoa.h b/c_src/double-conversion/fixed-dtoa.h index 3bdd08e..43de94e 100644 --- a/c_src/double-conversion/fixed-dtoa.h +++ b/c_src/double-conversion/fixed-dtoa.h @@ -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 { diff --git a/c_src/double-conversion/ieee.h b/c_src/double-conversion/ieee.h index 839dc47..661141d 100644 --- a/c_src/double-conversion/ieee.h +++ b/c_src/double-conversion/ieee.h @@ -256,6 +256,8 @@ class Double { return (significand & kSignificandMask) | (biased_exponent << kPhysicalSignificandSize); } + + DISALLOW_COPY_AND_ASSIGN(Double); }; class Single { @@ -391,6 +393,8 @@ class Single { static const uint32_t kNaN = 0x7FC00000; const uint32_t d32_; + + DISALLOW_COPY_AND_ASSIGN(Single); }; } // namespace double_conversion diff --git a/c_src/double-conversion/strtod.cc b/c_src/double-conversion/strtod.cc index 9758989..17abcbb 100644 --- a/c_src/double-conversion/strtod.cc +++ b/c_src/double-conversion/strtod.cc @@ -137,6 +137,7 @@ static void TrimAndCut(Vector buffer, int exponent, Vector right_trimmed = TrimTrailingZeros(left_trimmed); exponent += left_trimmed.length() - right_trimmed.length(); if (right_trimmed.length() > kMaxSignificantDecimalDigits) { + (void) space_size; // Mark variable as used. ASSERT(space_size >= kMaxSignificantDecimalDigits); CutToMaxSignificantDigits(right_trimmed, exponent, buffer_copy_space, updated_exponent); @@ -263,7 +264,6 @@ static DiyFp AdjustmentPowerOfTen(int exponent) { case 7: return DiyFp(UINT64_2PART_C(0x98968000, 00000000), -40); default: UNREACHABLE(); - return DiyFp(0, 0); } } @@ -286,7 +286,7 @@ static bool DiyFpStrtod(Vector buffer, const int kDenominator = 1 << kDenominatorLog; // Move the remaining decimals into the exponent. exponent += remaining_decimals; - int error = (remaining_decimals == 0 ? 0 : kDenominator / 2); + uint64_t error = (remaining_decimals == 0 ? 0 : kDenominator / 2); int old_e = input.e(); input.Normalize(); @@ -515,6 +515,7 @@ float Strtof(Vector buffer, int exponent) { double double_next2 = Double(double_next).NextDouble(); f4 = static_cast(double_next2); } + (void) f2; // Mark variable as used. ASSERT(f1 <= f2 && f2 <= f3 && f3 <= f4); // If the guess doesn't lie near a single-precision boundary we can simply diff --git a/c_src/double-conversion/strtod.h b/c_src/double-conversion/strtod.h index ed0293b..00cf8a7 100644 --- a/c_src/double-conversion/strtod.h +++ b/c_src/double-conversion/strtod.h @@ -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 { diff --git a/c_src/double-conversion/utils.h b/c_src/double-conversion/utils.h index 9ebb9ee..ce41e62 100644 --- a/c_src/double-conversion/utils.h +++ b/c_src/double-conversion/utils.h @@ -33,7 +33,8 @@ #include #ifndef ASSERT -#define ASSERT(condition) (assert(condition)) +#define ASSERT(condition) \ + assert(condition); #endif #ifndef UNIMPLEMENTED #define UNIMPLEMENTED() (abort()) @@ -55,11 +56,16 @@ #if defined(_M_X64) || defined(__x86_64__) || \ defined(__ARMEL__) || defined(__avr32__) || \ defined(__hppa__) || defined(__ia64__) || \ - defined(__mips__) || defined(__powerpc__) || \ + defined(__mips__) || \ + defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \ + defined(_POWER) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \ defined(__sparc__) || defined(__sparc) || defined(__s390__) || \ defined(__SH4__) || defined(__alpha__) || \ - defined(_MIPS_ARCH_MIPS32R2) + defined(_MIPS_ARCH_MIPS32R2) || \ + defined(__AARCH64EL__) || defined(__aarch64__) #define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1 +#elif defined(__mc68000__) +#undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS #elif defined(_M_IX86) || defined(__i386__) || defined(__i386) #if defined(_WIN32) // Windows uses a 64bit wide floating point stack. @@ -71,6 +77,11 @@ #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__) @@ -90,6 +101,8 @@ typedef unsigned __int64 uint64_t; #endif +typedef uint16_t uc16; + // The following macro works on both 32 and 64-bit platforms. // Usage: instead of writing 0x1234567890123456 // write UINT64_2PART_C(0x12345678,90123456); @@ -155,8 +168,8 @@ template class Vector { public: Vector() : start_(NULL), length_(0) {} - Vector(T* data, int length) : start_(data), length_(length) { - ASSERT(length == 0 || (length > 0 && data != NULL)); + Vector(T* data, int len) : start_(data), length_(len) { + ASSERT(len == 0 || (len > 0 && data != NULL)); } // Returns a vector using the same backing storage as this one, @@ -198,8 +211,8 @@ class Vector { // buffer bounds on all operations in debug mode. class StringBuilder { public: - StringBuilder(char* buffer, int size) - : buffer_(buffer, size), position_(0) { } + StringBuilder(char* buffer, int buffer_size) + : buffer_(buffer, buffer_size), position_(0) { } ~StringBuilder() { if (!is_finalized()) Finalize(); } @@ -292,24 +305,12 @@ class StringBuilder { // you can use BitCast to cast one pointer type to another. This confuses gcc // enough that it can no longer see that you have cast one pointer type to // another thus avoiding the warning. -// -// Adding an unused attribute for this static check. Apparently GCC 4.8 -// now throws an error for unused typedefs which triggers -Werror. -// -// PJD: 4-24-2013 -// - -#if defined(__GNUC__) -#define UNUSED __attribute__((unused)) -#else -#define UNUSED -#endif - template 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. - UNUSED typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1]; + DOUBLE_CONVERSION_UNUSED + typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1]; Dest dest; memmove(&dest, &source, sizeof(dest));