summaryrefslogtreecommitdiff
path: root/test/test_deserialize_number.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/test_deserialize_number.cpp')
-rw-r--r--test/test_deserialize_number.cpp503
1 files changed, 503 insertions, 0 deletions
diff --git a/test/test_deserialize_number.cpp b/test/test_deserialize_number.cpp
new file mode 100644
index 0000000..6b3f85c
--- /dev/null
+++ b/test/test_deserialize_number.cpp
@@ -0,0 +1,503 @@
+/*
+ * libfud
+ * Copyright 2024 Dominick Allen
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "fud_array.hpp"
+#include "fud_string.hpp"
+
+#include "gtest/gtest.h"
+
+namespace fud {
+
+template <typename T, typename Func>
+auto testStringToIntegerInvalid(Func&& func)
+{
+ Array<uint8_t, sizeof("7 13 42 0 08 010 0x08")> backing{"7 13 42 0 08 010 0x08"};
+ FudString extString{FudString::withBacking(backing)};
+ StringView view{extString};
+ StringView invalidView{extString};
+ T number = 0;
+ ASSERT_EQ(std::forward<Func>(func)(view, nullptr, 0, nullptr), ExtNullPointer);
+
+ invalidView.data = nullptr;
+ ASSERT_EQ(std::forward<Func>(func)(invalidView, &number, 1, nullptr), ExtNullPointer);
+ invalidView.data = view.data;
+
+ invalidView.length = 0;
+ ASSERT_EQ(std::forward<Func>(func)(invalidView, &number, 0, nullptr), ExtInvalidInput);
+ ASSERT_EQ(std::forward<Func>(func)(view, &number, 1, nullptr), ExtInvalidInput);
+ ASSERT_EQ(std::forward<Func>(func)(view, &number, UINT8_MAX, nullptr), ExtInvalidInput);
+}
+
+template <typename T, size_t BackingSize, size_t WordCount, typename Func>
+auto testStringToNumber(
+ Array<uint8_t, BackingSize>& backing,
+ const Array<size_t, WordCount>& wordSizes,
+ const Array<ExtStatus, WordCount>& statuses,
+ const Array<T, WordCount>& expectedValues,
+ Func&& func,
+ uint8_t radix)
+{
+ FudString extString{FudString::withBacking(backing)};
+ StringView view{extString};
+ T number = 0;
+
+ ASSERT_EQ(std::forward<Func>(func)(view, &number, radix, nullptr), statuses[0]);
+ ASSERT_EQ(number, expectedValues[0]);
+
+ size_t index = 0;
+ for (size_t idx = 0; idx < WordCount; ++idx) {
+
+ T tempNumber{};
+ if (std::forward<Func>(func)(view, &tempNumber, radix, &index) != statuses[idx]) {
+ printf(
+ "どうして? \"%s\" %ld %zu %ld\n",
+ view.data,
+ static_cast<int64_t>(expectedValues[idx]),
+ idx,
+ static_cast<int64_t>(tempNumber));
+ if (idx > 0) {
+ printf("Test: \"%s\"\n", view.data - index);
+ }
+ }
+ EXPECT_EQ(std::forward<Func>(func)(view, &number, radix, &index), statuses[idx]);
+ if (statuses[idx] == ExtSuccess) {
+ ASSERT_EQ(number, expectedValues[idx]);
+ ASSERT_EQ(index, wordSizes[idx]);
+ }
+
+ view.data += wordSizes[idx];
+ view.length -= wordSizes[idx];
+ }
+}
+
+TEST(FudString, StringToUint8Invalid)
+{
+ testStringToIntegerInvalid<uint8_t>(ext_string_to_uint8);
+}
+
+TEST(FudString, StringToUint8RadixUnspec)
+{
+ Array<uint8_t, sizeof("7 13 42 0 018 010 0xFF 0xFF0 256")> backing{"7 13 42 0 018 010 0xFF 0xFF0 256"};
+ constexpr Array<size_t, 10> wordSizes{
+ sizeof("7") - 1,
+ sizeof(" 13") - 1,
+ sizeof(" 42") - 1,
+ sizeof(" 0") - 1,
+ sizeof(" 01") - 1,
+ sizeof("8") - 1,
+ sizeof(" 010") - 1,
+ sizeof(" 0xFF") - 1,
+ sizeof(" 0xFF0") - 1,
+ sizeof(" 256") - 1};
+ constexpr Array<uint8_t, 10> expectedValues{7, 13, 42, 0, 1, 8, 8, 0xFF, 0, 0};
+ constexpr Array<ExtStatus, 10> statuses{
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtInvalidInput,
+ ExtInvalidInput};
+ testStringToNumber(backing, wordSizes, statuses, expectedValues, ext_string_to_uint8, 0);
+}
+
+TEST(FudString, StringToUint8Octal)
+{
+ Array<uint8_t, sizeof("7 13 42 0 018 010 377 0xFF0")> backing{"7 13 42 0 018 010 377 0xFF0"};
+ constexpr Array<uint8_t, 10> expectedValues{7, 8 + 3, 8 * 4 + 2, 0, 1, 0, 8, 255, 0, 0};
+ constexpr Array<size_t, 10> wordSizes{
+ sizeof("7") - 1,
+ sizeof(" 13") - 1,
+ sizeof(" 42") - 1,
+ sizeof(" 0") - 1,
+ sizeof(" 01") - 1,
+ sizeof("8") - 1,
+ sizeof(" 010") - 1,
+ sizeof(" 377") - 1,
+ sizeof(" 0") - 1,
+ sizeof("xFF0") - 1};
+ constexpr Array<ExtStatus, 10> statuses{
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtInvalidInput,
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtInvalidInput};
+ testStringToNumber(backing, wordSizes, statuses, expectedValues, ext_string_to_uint8, ExtRadixOctal);
+}
+
+TEST(FudString, StringToUint8Hex)
+{
+ Array<uint8_t, sizeof("7 13 0x42 0 018 010 FF 0xFF0")> backing{"7 13 0x42 0 018 010 FF 0xFF0"};
+ constexpr Array<uint8_t, 8> expectedValues{7, 16 + 3, 16 * 4 + 2, 0, 16 + 8, 16, 255, 0};
+ constexpr Array<size_t, 8> wordSizes{
+ sizeof("7") - 1,
+ sizeof(" 13") - 1,
+ sizeof(" 0x42") - 1,
+ sizeof(" 0") - 1,
+ sizeof(" 018") - 1,
+ sizeof(" 010") - 1,
+ sizeof(" FF") - 1,
+ sizeof(" 0xFF0") - 1};
+ constexpr Array<ExtStatus, 8>
+ statuses{ExtSuccess, ExtSuccess, ExtSuccess, ExtSuccess, ExtSuccess, ExtSuccess, ExtSuccess, ExtInvalidInput};
+ testStringToNumber(backing, wordSizes, statuses, expectedValues, ext_string_to_uint8, ExtRadixHexadecimal);
+}
+
+TEST(FudString, StringToUint16Invalid)
+{
+ testStringToIntegerInvalid<uint16_t>(ext_string_to_uint16);
+}
+
+TEST(FudString, StringToUint16RadixUnspec)
+{
+ Array<uint8_t, sizeof("7 65535 0x42 0 010 0xFFFF 0xFFFF0")> backing{
+ "7 65535 0x42 0 010 0xFFFF 0xFFFF0"};
+ constexpr Array<uint16_t, 7> expectedValues{7, 0xFFFF, 0x42, 0, 8, 0xFFFF, 0};
+ constexpr Array<size_t, 7> wordSizes{
+ sizeof("7") - 1,
+ sizeof(" 65535") - 1,
+ sizeof(" 0x42") - 1,
+ sizeof(" 0") - 1,
+ sizeof(" 010") - 1,
+ sizeof(" 0xFFFF") - 1,
+ sizeof(" 0xFFFF0") - 1};
+ constexpr Array<ExtStatus, 7> statuses{
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtInvalidInput};
+ testStringToNumber(backing, wordSizes, statuses, expectedValues, ext_string_to_uint16, 0);
+}
+
+TEST(FudString, StringToUint16Octal)
+{
+ Array<uint8_t, sizeof("7 13 42 0 010 177777 200000")> backing{"7 13 42 0 010 177777 200000"};
+ constexpr Array<uint16_t, 7> expectedValues{7, 8 + 3, 8 * 4 + 2, 0, 8, 0xFFFF, 0};
+ constexpr Array<size_t, 7> wordSizes{
+ sizeof("7") - 1,
+ sizeof(" 13") - 1,
+ sizeof(" 42") - 1,
+ sizeof(" 0") - 1,
+ sizeof(" 010") - 1,
+ sizeof(" 177777") - 1,
+ sizeof(" 200000") - 1};
+ constexpr Array<ExtStatus, 7> statuses{
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtInvalidInput};
+ testStringToNumber(backing, wordSizes, statuses, expectedValues, ext_string_to_uint16, ExtRadixOctal);
+}
+
+TEST(FudString, StringToUint16Hex)
+{
+ Array<uint8_t, sizeof("7 13 0x42 0 018 010 FFFF 0x10000")> backing{"7 13 0x42 0 018 010 FFFF 0x10000"};
+ constexpr Array<uint16_t, 8> expectedValues{7, 16 + 3, 16 * 4 + 2, 0, 16 + 8, 16, 0xFFFF, 0};
+ constexpr Array<size_t, 8> wordSizes{
+ sizeof("7") - 1,
+ sizeof(" 13") - 1,
+ sizeof(" 0x42") - 1,
+ sizeof(" 0") - 1,
+ sizeof(" 018") - 1,
+ sizeof(" 010") - 1,
+ sizeof(" FFFF") - 1,
+ sizeof(" 200000") - 1};
+ constexpr Array<ExtStatus, 8>
+ statuses{ExtSuccess, ExtSuccess, ExtSuccess, ExtSuccess, ExtSuccess, ExtSuccess, ExtSuccess, ExtInvalidInput};
+ testStringToNumber(backing, wordSizes, statuses, expectedValues, ext_string_to_uint16, ExtRadixHexadecimal);
+}
+
+TEST(FudString, StringToUint64Hex)
+{
+ Array<uint8_t, sizeof("7 13 0x7FFFFFFFFFFFFFFF 0 018 010 -8000000000000000 0xFFFFFFFFFFFFFFFF -8000000000000001")>
+ backing{"7 13 0x7FFFFFFFFFFFFFFF 0 018 010 -8000000000000000 0xFFFFFFFFFFFFFFFF -8000000000000001"};
+ constexpr Array<uint64_t, 9> expectedValues{
+ 7,
+ 16 + 3,
+ std::numeric_limits<int64_t>::max(),
+ 0,
+ 16 + 8,
+ 16,
+ 0,
+ std::numeric_limits<uint64_t>::max(),
+ 0};
+ constexpr Array<size_t, 9> wordSizes{
+ sizeof("7") - 1,
+ sizeof(" 13") - 1,
+ sizeof(" 0x7FFFFFFFFFFFFFFF") - 1,
+ sizeof(" 0") - 1,
+ sizeof(" 018") - 1,
+ sizeof(" 010") - 1,
+ sizeof(" -8000000000000000") - 1,
+ sizeof(" 0xFFFFFFFFFFFFFFFF") - 1,
+ sizeof(" -8000000000000001") - 1};
+ constexpr Array<ExtStatus, 9> statuses{
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtInvalidInput,
+ ExtSuccess,
+ ExtInvalidInput};
+ testStringToNumber(backing, wordSizes, statuses, expectedValues, ext_string_to_uint64, ExtRadixHexadecimal);
+}
+
+TEST(FudString, StringToInt8Invalid)
+{
+ testStringToIntegerInvalid<int8_t>(ext_string_to_int8);
+}
+
+TEST(FudString, StringToInt8RadixUnspec)
+{
+ Array<uint8_t, sizeof("7 13 127 0 018 010 -0x80 0x80")> backing{"7 13 127 0 018 010 -0x80 0x80"};
+ constexpr Array<int8_t, 8> expectedValues{7, 13, 127, 0, 0, 8, -0x80, 0};
+ constexpr Array<size_t, 8> wordSizes{
+ sizeof("7") - 1,
+ sizeof(" 13") - 1,
+ sizeof(" 127") - 1,
+ sizeof(" 0") - 1,
+ sizeof(" 018") - 1,
+ sizeof(" 010") - 1,
+ sizeof(" -0x80") - 1,
+ sizeof(" 0x80") - 1};
+ constexpr Array<ExtStatus, 8> statuses{
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtInvalidInput,
+ ExtSuccess,
+ ExtSuccess,
+ ExtInvalidInput};
+ testStringToNumber(backing, wordSizes, statuses, expectedValues, ext_string_to_int8, 0);
+}
+
+TEST(FudString, StringToInt8Octal)
+{
+ Array<uint8_t, sizeof("7 13 177 0 018 010 -200 0xFF0 -201")> backing{"7 13 177 0 018 010 -200 0xFF0 -201"};
+ constexpr Array<int8_t, 9> expectedValues{7, 8 + 3, 127, 0, 0, 8, -128, 0};
+ constexpr Array<size_t, 9> wordSizes{
+ sizeof("7") - 1,
+ sizeof(" 13") - 1,
+ sizeof(" 177") - 1,
+ sizeof(" 0") - 1,
+ sizeof(" 018") - 1,
+ sizeof(" 010") - 1,
+ sizeof(" -200") - 1,
+ sizeof(" 0xFF0") - 1,
+ sizeof(" -201") - 1};
+ constexpr Array<ExtStatus, 9> statuses{
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtInvalidInput,
+ ExtSuccess,
+ ExtSuccess,
+ ExtInvalidInput,
+ ExtInvalidInput};
+ testStringToNumber(backing, wordSizes, statuses, expectedValues, ext_string_to_int8, ExtRadixOctal);
+}
+
+TEST(FudString, StringToInt8Hex)
+{
+ Array<uint8_t, sizeof("7 13 0x7F 0 018 010 -80 0xFF0")> backing{"7 13 0x7F 0 018 010 -80 0xFF0"};
+ constexpr Array<int8_t, 8> expectedValues{7, 16 + 3, 127, 0, 16 + 8, 16, -128, 0};
+ constexpr Array<size_t, 8> wordSizes{
+ sizeof("7") - 1,
+ sizeof(" 13") - 1,
+ sizeof(" 0x7F") - 1,
+ sizeof(" 0") - 1,
+ sizeof(" 018") - 1,
+ sizeof(" 010") - 1,
+ sizeof(" -80") - 1,
+ sizeof(" 0xFF0") - 1};
+ constexpr Array<ExtStatus, 8>
+ statuses{ExtSuccess, ExtSuccess, ExtSuccess, ExtSuccess, ExtSuccess, ExtSuccess, ExtSuccess, ExtInvalidInput};
+ testStringToNumber(backing, wordSizes, statuses, expectedValues, ext_string_to_int8, ExtRadixHexadecimal);
+}
+
+TEST(FudString, StringToInt32Decimal)
+{
+ Array<uint8_t, sizeof("01 13 0x7F 0 018 010 -80 0xFF0")> backing{"01 13 0x7F 0 018 010 -80 0xFF0"};
+ constexpr Array<int8_t, 8> expectedValues{1, 13, 0, 0, 18, 10, -80, 0};
+ constexpr Array<size_t, 8> wordSizes{
+ sizeof("01") - 1,
+ sizeof(" 13") - 1,
+ sizeof(" 0x7F") - 1,
+ sizeof(" 0") - 1,
+ sizeof(" 018") - 1,
+ sizeof(" 010") - 1,
+ sizeof(" -80") - 1,
+ sizeof(" 0xFF0") - 1};
+ constexpr Array<ExtStatus, 8>
+ statuses{ExtSuccess, ExtSuccess, ExtInvalidInput, ExtSuccess, ExtSuccess, ExtSuccess, ExtSuccess, ExtInvalidInput};
+ testStringToNumber(backing, wordSizes, statuses, expectedValues, ext_string_to_int8, ExtRadixDecimal);
+}
+
+TEST(FudString, StringToInt64Hex)
+{
+ Array<uint8_t, sizeof("+7 13 0x7FFFFFFFFFFFFFFF 0 018 010 -8000000000000000 0x8000000000000000 -8000000000000001")>
+ backing{"+7 13 0x7FFFFFFFFFFFFFFF 0 018 010 -8000000000000000 0x8000000000000000 -8000000000000001"};
+ constexpr Array<int64_t, 9> expectedValues{
+ 7,
+ 16 + 3,
+ std::numeric_limits<int64_t>::max(),
+ 0,
+ 16 + 8,
+ 16,
+ std::numeric_limits<int64_t>::min(),
+ 0,
+ 0};
+ constexpr Array<size_t, 9> wordSizes{
+ sizeof("+7") - 1,
+ sizeof(" 13") - 1,
+ sizeof(" 0x7FFFFFFFFFFFFFFF") - 1,
+ sizeof(" 0") - 1,
+ sizeof(" 018") - 1,
+ sizeof(" 010") - 1,
+ sizeof(" -8000000000000000") - 1,
+ sizeof(" 0x8000000000000000") - 1,
+ sizeof(" -8000000000000001") - 1};
+ constexpr Array<ExtStatus, 9> statuses{
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtSuccess,
+ ExtInvalidInput,
+ ExtInvalidInput};
+ testStringToNumber(backing, wordSizes, statuses, expectedValues, ext_string_to_int64, ExtRadixHexadecimal);
+}
+
+template <typename T>
+struct TestStringToFloatParams {
+ T value{0.0};
+ size_t wordSize{0};
+ ExtStatus status{ExtInvalidInput};
+ bool isNaN{false};
+};
+
+template <typename T, size_t BackingSize, size_t WordCount, typename Func>
+auto testStringToFloat(
+ Array<uint8_t, BackingSize>& backing,
+ const Array<TestStringToFloatParams<T>, WordCount>& testParams,
+ Func&& func)
+{
+ FudString extString{FudString::withBacking(backing)};
+ StringView view{extString};
+ T number = 0;
+
+ ASSERT_EQ(std::forward<Func>(func)(view, &number, nullptr), testParams[0].status);
+ ASSERT_EQ(number, testParams[0].value);
+
+ size_t index = 0;
+ for (size_t idx = 0; idx < WordCount; ++idx) {
+ ASSERT_EQ(std::forward<Func>(func)(view, &number, &index), testParams[idx].status);
+ if (testParams[idx].status == ExtSuccess) {
+ if (!testParams[idx].isNaN) {
+ ASSERT_EQ(number, testParams[idx].value);
+ } else {
+ ASSERT_NE(number, number);
+ }
+ ASSERT_EQ(index, testParams[idx].wordSize);
+ }
+
+ view.data += testParams[idx].wordSize;
+ view.length -= testParams[idx].wordSize;
+ }
+}
+
+TEST(FudString, StringToFloat)
+{
+ Array<uint8_t, sizeof("123 -7 123.5 .25 0.25 -.125 -2.0625 NaN -inf inF")> backing{
+ "123 -7 123.5 .25 0.25 -.125 -2.0625 NaN -inf inF"};
+ /* N.B. In the following expressions, sizeof includes null, but excludes one leading space. */
+ constexpr Array<TestStringToFloatParams<float>, 10> testParams{
+ {{123.0, sizeof("123") - 1, ExtSuccess},
+ {-7.0, sizeof("-7"), ExtSuccess},
+ {123.5, sizeof("123.5"), ExtSuccess},
+ {.25, sizeof(".25"), ExtSuccess},
+ {.25, sizeof("0.25"), ExtSuccess},
+ {-.125, sizeof("-.125"), ExtSuccess},
+ {-2.0625, sizeof("-2.0625"), ExtSuccess},
+ {std::numeric_limits<float>::quiet_NaN(), sizeof("NaN"), ExtSuccess, true},
+ {-1.0F * std::numeric_limits<float>::infinity(), sizeof("-inf"), ExtSuccess},
+ {std::numeric_limits<float>::infinity(), sizeof("inF"), ExtSuccess}}};
+
+ testStringToFloat(backing, testParams, ext_string_to_float);
+}
+
+TEST(FudString, StringToDouble)
+{
+ Array<uint8_t, sizeof("123 -7 123.5 .25 0.25 -.125 -2.0625 NaN -inf inF")> backing{
+ "123 -7 123.5 .25 0.25 -.125 -2.0625 NaN -inf inF"};
+ /* N.B. In the following expressions, sizeof includes null, but excludes one leading space. */
+ constexpr Array<TestStringToFloatParams<double>, 10> testParams{
+ {{123.0, sizeof("123") - 1, ExtSuccess},
+ {-7.0, sizeof("-7"), ExtSuccess},
+ {123.5, sizeof("123.5"), ExtSuccess},
+ {.25, sizeof(".25"), ExtSuccess},
+ {.25, sizeof("0.25"), ExtSuccess},
+ {-.125, sizeof("-.125"), ExtSuccess},
+ {-2.0625, sizeof("-2.0625"), ExtSuccess},
+ {std::numeric_limits<double>::quiet_NaN(), sizeof("NaN"), ExtSuccess, true},
+ {-1.0 * std::numeric_limits<double>::infinity(), sizeof("-inf"), ExtSuccess},
+ {std::numeric_limits<double>::infinity(), sizeof("inF"), ExtSuccess}}};
+
+ testStringToFloat(backing, testParams, ext_string_to_double);
+}
+
+TEST(FudString, StringToDoubleExpt)
+{
+ Array<uint8_t, sizeof("1.25e01 1.25e+01 0.125e2 12.5e0 125.e-1 125e-1 1250.e-02 1250.0e-02")> backing{
+ "1.25e01 1.25e+01 0.125e2 12.5e0 125.e-1 125e-1 1250.e-02 1250.0e-02"};
+ /* N.B. In the following expressions, sizeof includes null, but excludes one leading space. */
+ constexpr Array<TestStringToFloatParams<double>, 8> testParams{
+ {{12.5, sizeof("1.25e01") - 1, ExtSuccess},
+ {12.5, sizeof("1.25e+01"), ExtSuccess},
+ {12.5, sizeof("0.125e2"), ExtSuccess},
+ {12.5, sizeof("12.5e0"), ExtSuccess},
+ {12.5, sizeof("125.e-1"), ExtSuccess},
+ {12.5, sizeof("125e-1"), ExtSuccess},
+ {12.5, sizeof("1250.e-02"), ExtSuccess},
+ {12.5, sizeof("1250.0e-02"), ExtSuccess}
+ }};
+
+ testStringToFloat(backing, testParams, ext_string_to_double);
+}
+
+
+} // namespace fud