From eee1a4544fda1fd70f93412ad7a210d40693ef1c Mon Sep 17 00:00:00 2001 From: Niels Dekker Date: Sun, 11 Apr 2021 00:27:02 +0200 Subject: [PATCH] Add `StringToDoubleConverter::StringTo` member function templates (#158) Allowed users to write generic code more easily, like this (when `T` is either `float` or `double`): converter.StringTo(buffer, length, &processed); Included a unit test, `TEST(StringToTemplate)`. Fixes #157. --- double-conversion/string-to-double.cc | 36 +++++++++++ double-conversion/string-to-double.h | 12 ++++ test/cctest/test-conversions.cc | 86 +++++++++++++++++++++++++++ 3 files changed, 134 insertions(+) diff --git a/double-conversion/string-to-double.cc b/double-conversion/string-to-double.cc index 85c3a082..fe633aac 100644 --- a/double-conversion/string-to-double.cc +++ b/double-conversion/string-to-double.cc @@ -779,4 +779,40 @@ float StringToDoubleConverter::StringToFloat( processed_characters_count)); } + +template<> +double StringToDoubleConverter::StringTo( + const char* buffer, + int length, + int* processed_characters_count) const { + return StringToDouble(buffer, length, processed_characters_count); +} + + +template<> +float StringToDoubleConverter::StringTo( + const char* buffer, + int length, + int* processed_characters_count) const { + return StringToFloat(buffer, length, processed_characters_count); +} + + +template<> +double StringToDoubleConverter::StringTo( + const uc16* buffer, + int length, + int* processed_characters_count) const { + return StringToDouble(buffer, length, processed_characters_count); +} + + +template<> +float StringToDoubleConverter::StringTo( + const uc16* buffer, + int length, + int* processed_characters_count) const { + return StringToFloat(buffer, length, processed_characters_count); +} + } // namespace double_conversion diff --git a/double-conversion/string-to-double.h b/double-conversion/string-to-double.h index ecd6c761..770ccbc3 100644 --- a/double-conversion/string-to-double.h +++ b/double-conversion/string-to-double.h @@ -204,6 +204,18 @@ class StringToDoubleConverter { int length, int* processed_characters_count) const; + // Same as StringToDouble for T = double, and StringToFloat for T = float. + template + T StringTo(const char* buffer, + int length, + int* processed_characters_count) const; + + // Same as StringTo above but for 16 bit characters. + template + T StringTo(const uc16* buffer, + int length, + int* processed_characters_count) const; + private: const int flags_; const double empty_string_value_; diff --git a/test/cctest/test-conversions.cc b/test/cctest/test-conversions.cc index 325b7a15..504d946b 100644 --- a/test/cctest/test-conversions.cc +++ b/test/cctest/test-conversions.cc @@ -5889,3 +5889,89 @@ TEST(StringToDoubleCaseInsensitiveSpecialValues) { CHECK_EQ(1.0, converter.StringToDouble("+inf", 4, &processed)); CHECK_EQ(0, processed); } + + +TEST(StringToTemplate) { + // Test StringToDoubleConverter::StringTo. + + const StringToDoubleConverter converter(StringToDoubleConverter::ALLOW_HEX, 0.0, Double::NaN(), "inf", "nan"); + + // First simply check conversion from "0" and "1": + for (int i = 0; i <= 1; ++i) + { + const char c = '0' + i; + + int processed = 0; + CHECK_EQ(static_cast(i), converter.StringTo(&c, 1, &processed)); + CHECK_EQ(1, processed); + + processed = 0; + CHECK_EQ(static_cast(i), converter.StringTo(&c, 1, &processed)); + CHECK_EQ(1, processed); + + const uc16 buffer16[1] = { static_cast(c) }; + + processed = 0; + CHECK_EQ(static_cast(i), converter.StringTo(buffer16, 1, &processed)); + CHECK_EQ(1, processed); + + processed = 0; + CHECK_EQ(static_cast(i), converter.StringTo(buffer16, 1, &processed)); + CHECK_EQ(1, processed); + } + { + // A number that can be represented by a double, but not by a float. + // Allows testing that StringTo behaves like StringToDouble + // (and not like StringToFloat). + const char buffer[] = "1e+100"; + const int length = DOUBLE_CONVERSION_ARRAY_SIZE(buffer) - 1; + + int processed1 = 1; + int processed2 = 2; + + CHECK_EQ(converter.StringToDouble(buffer, length, &processed1), + converter.StringTo(buffer, length, &processed2)); + CHECK_EQ(processed1, processed2); + + uc16 buffer16[DOUBLE_CONVERSION_ARRAY_SIZE(buffer)]; + + for (int i = 0; i <= length; ++i) { + buffer16[i] = buffer[i]; + } + + processed1 = 1; + processed2 = 2; + + CHECK_EQ(converter.StringToDouble(buffer16, length, &processed1), + converter.StringTo(buffer16, length, &processed2)); + CHECK_EQ(processed1, processed2); + } + { + // The double rounding example from TEST(StringToFloatHexString), which + // yields a slightly different result from StringToFloat than from + // StringToDouble. Allows testing that StringTo behaves like + // StringToFloat (rather than like StringToDouble). + const char buffer[] = "0x100000100000008"; + const int length = DOUBLE_CONVERSION_ARRAY_SIZE(buffer) - 1; + + int processed1 = 1; + int processed2 = 2; + + CHECK_EQ(converter.StringToFloat(buffer, length, &processed1), + converter.StringTo(buffer, length, &processed2)); + CHECK_EQ(processed1, processed2); + + uc16 buffer16[DOUBLE_CONVERSION_ARRAY_SIZE(buffer)]; + + for (int i = 0; i <= length; ++i) { + buffer16[i] = buffer[i]; + } + + processed1 = 1; + processed2 = 2; + + CHECK_EQ(converter.StringToFloat(buffer16, length, &processed1), + converter.StringTo(buffer16, length, &processed2)); + CHECK_EQ(processed1, processed2); + } +}