From 0a695cf09ef48650e925045809218e3ec720aeee Mon Sep 17 00:00:00 2001 From: ado Date: Sun, 25 Feb 2024 17:46:35 +0100 Subject: [PATCH] Add ss::uint8 and ss::int8, add unit tests for them --- include/ss/extract.hpp | 51 +++++++++- ssp.hpp | 51 +++++++++- test/test_converter.cpp | 205 +++++++++++++++++++------------------- test/test_extractions.cpp | 176 ++++++++++++++++---------------- 4 files changed, 294 insertions(+), 189 deletions(-) diff --git a/include/ss/extract.hpp b/include/ss/extract.hpp index b49a6d8..64b6b1b 100644 --- a/include/ss/extract.hpp +++ b/include/ss/extract.hpp @@ -77,6 +77,38 @@ std::enable_if_t, std::optional> to_num( #endif +//////////////// +// numeric_wrapper +//////////////// + +template +struct numeric_wrapper { + using type = T; + + numeric_wrapper() = default; + numeric_wrapper(numeric_wrapper&&) = default; + numeric_wrapper(const numeric_wrapper&) = default; + + numeric_wrapper& operator=(numeric_wrapper&&) = default; + numeric_wrapper& operator=(const numeric_wrapper&) = default; + + numeric_wrapper(T other) : value{other} { + } + + operator T() { + return value; + } + + operator T() const { + return value; + } + + T value; +}; + +using int8 = numeric_wrapper; +using uint8 = numeric_wrapper; + template std::enable_if_t, std::optional> to_num( const char* const begin, const char* const end) { @@ -89,6 +121,18 @@ std::enable_if_t, std::optional> to_num( return ret; } +template +std::enable_if_t, std::optional> to_num( + const char* const begin, const char* const end) { + T ret; + auto [ptr, ec] = std::from_chars(begin, end, ret.value); + + if (ec != std::errc() || ptr != end) { + return std::nullopt; + } + return ret; +} + //////////////// // extract //////////////// @@ -103,7 +147,8 @@ struct unsupported_type { template std::enable_if_t && !std::is_floating_point_v && !is_instance_of_v && - !is_instance_of_v, + !is_instance_of_v && + !is_instance_of_v, bool> extract(const char*, const char*, T&) { static_assert(error::unsupported_type::value, @@ -112,7 +157,9 @@ extract(const char*, const char*, T&) { } template -std::enable_if_t || std::is_floating_point_v, bool> +std::enable_if_t || std::is_floating_point_v || + is_instance_of_v, + bool> extract(const char* begin, const char* end, T& value) { auto optional_value = to_num(begin, end); if (!optional_value) { diff --git a/ssp.hpp b/ssp.hpp index 6f0ea8d..e6578b5 100644 --- a/ssp.hpp +++ b/ssp.hpp @@ -1531,6 +1531,38 @@ std::enable_if_t, std::optional> to_num( #endif +//////////////// +// numeric_wrapper +//////////////// + +template +struct numeric_wrapper { + using type = T; + + numeric_wrapper() = default; + numeric_wrapper(numeric_wrapper&&) = default; + numeric_wrapper(const numeric_wrapper&) = default; + + numeric_wrapper& operator=(numeric_wrapper&&) = default; + numeric_wrapper& operator=(const numeric_wrapper&) = default; + + numeric_wrapper(T other) : value{other} { + } + + operator T() { + return value; + } + + operator T() const { + return value; + } + + T value; +}; + +using int8 = numeric_wrapper; +using uint8 = numeric_wrapper; + template std::enable_if_t, std::optional> to_num( const char* const begin, const char* const end) { @@ -1543,6 +1575,18 @@ std::enable_if_t, std::optional> to_num( return ret; } +template +std::enable_if_t, std::optional> to_num( + const char* const begin, const char* const end) { + T ret; + auto [ptr, ec] = std::from_chars(begin, end, ret.value); + + if (ec != std::errc() || ptr != end) { + return std::nullopt; + } + return ret; +} + //////////////// // extract //////////////// @@ -1557,7 +1601,8 @@ struct unsupported_type { template std::enable_if_t && !std::is_floating_point_v && !is_instance_of_v && - !is_instance_of_v, + !is_instance_of_v && + !is_instance_of_v, bool> extract(const char*, const char*, T&) { static_assert(error::unsupported_type::value, @@ -1566,7 +1611,9 @@ extract(const char*, const char*, T&) { } template -std::enable_if_t || std::is_floating_point_v, bool> +std::enable_if_t || std::is_floating_point_v || + is_instance_of_v, + bool> extract(const char* begin, const char* end, T& value) { auto optional_value = to_num(begin, end); if (!optional_value) { diff --git a/test/test_converter.cpp b/test/test_converter.cpp index 6dd4562..29312b7 100644 --- a/test/test_converter.cpp +++ b/test/test_converter.cpp @@ -46,90 +46,88 @@ TEST_CASE("converter test split with exceptions") { } } -TEST_CASE("converter test valid conversions") { +TEST_CASE_TEMPLATE("converter test valid conversions", T, int, ss::uint8) { ss::converter c; { - auto tup = c.convert("5"); + auto tup = c.convert("5"); REQUIRE(c.valid()); CHECK_EQ(tup, 5); } { - auto tup = c.convert("5,junk"); + auto tup = c.convert("5,junk"); REQUIRE(c.valid()); CHECK_EQ(tup, 5); } { - auto tup = c.convert("junk,5"); + auto tup = c.convert("junk,5"); REQUIRE(c.valid()); CHECK_EQ(tup, 5); } { - auto tup = c.convert("5\njunk\njunk", "\n"); + auto tup = c.convert("5\njunk\njunk", "\n"); REQUIRE(c.valid()); CHECK_EQ(tup, 5); } { - auto tup = c.convert("junk 5 junk", " "); + auto tup = c.convert("junk 5 junk", " "); REQUIRE(c.valid()); CHECK_EQ(tup, 5); } { - auto tup = c.convert("junk\tjunk\t5", "\t"); + auto tup = c.convert("junk\tjunk\t5", "\t"); REQUIRE(c.valid()); CHECK_EQ(tup, 5); } { auto tup = - c.convert>("junk\tjunk\t5", "\t"); + c.convert>("junk\tjunk\t5", "\t"); REQUIRE(c.valid()); REQUIRE(tup.has_value()); CHECK_EQ(tup, 5); } { - auto tup = c.convert("5,6.6,junk"); + auto tup = c.convert("5,6.6,junk"); REQUIRE(c.valid()); CHECK_EQ(tup, std::make_tuple(5, 6.6)); } { - auto tup = c.convert("5,junk,6.6"); + auto tup = c.convert("5,junk,6.6"); REQUIRE(c.valid()); CHECK_EQ(tup, std::make_tuple(5, 6.6)); } { - auto tup = c.convert("junk;5;6.6", ";"); + auto tup = c.convert("junk;5;6.6", ";"); REQUIRE(c.valid()); CHECK_EQ(tup, std::make_tuple(5, 6.6)); } { - auto tup = - c.convert, double>("junk;5;6.6", ";"); + auto tup = c.convert, double>("junk;5;6.6", ";"); REQUIRE(c.valid()); REQUIRE(std::get<0>(tup).has_value()); CHECK_EQ(tup, std::make_tuple(5, 6.6)); } { auto tup = - c.convert, double>("junk;5.4;6.6", ";"); + c.convert, double>("junk;5.4;6.6", ";"); REQUIRE(c.valid()); REQUIRE_FALSE(std::get<0>(tup).has_value()); - CHECK_EQ(tup, std::make_tuple(std::optional{}, 6.6)); + CHECK_EQ(tup, std::make_tuple(std::optional{}, 6.6)); } { auto tup = - c.convert, double>("junk;5;6.6", - ";"); + c.convert, double>("junk;5;6.6", ";"); REQUIRE(c.valid()); - REQUIRE(std::holds_alternative(std::get<0>(tup))); - CHECK_EQ(tup, std::make_tuple(std::variant{5}, 6.6)); + REQUIRE(std::holds_alternative(std::get<0>(tup))); + CHECK_EQ(tup, std::make_tuple(std::variant{5}, 6.6)); } { auto tup = - c.convert, double>("junk;5.5;6.6", - ";"); + c.convert, double>("junk;5.5;6.6", + ";"); REQUIRE(c.valid()); REQUIRE(std::holds_alternative(std::get<0>(tup))); - CHECK_EQ(tup, std::make_tuple(std::variant{5.5}, 6.6)); + CHECK_EQ(tup, std::make_tuple(std::variant{5.5}, 6.6)); } { auto tup = c.convert c; try { - auto tup = c.convert("5"); + auto tup = c.convert("5"); REQUIRE(c.valid()); CHECK_EQ(tup, 5); } catch (ss::exception& e) { @@ -152,7 +151,7 @@ TEST_CASE("converter test valid conversions with exceptions") { } try { - auto tup = c.convert("5,junk"); + auto tup = c.convert("5,junk"); REQUIRE(c.valid()); CHECK_EQ(tup, 5); } catch (ss::exception& e) { @@ -160,7 +159,7 @@ TEST_CASE("converter test valid conversions with exceptions") { } try { - auto tup = c.convert("junk,5"); + auto tup = c.convert("junk,5"); REQUIRE(c.valid()); CHECK_EQ(tup, 5); } catch (ss::exception& e) { @@ -168,7 +167,7 @@ TEST_CASE("converter test valid conversions with exceptions") { } try { - auto tup = c.convert("5\njunk\njunk", "\n"); + auto tup = c.convert("5\njunk\njunk", "\n"); REQUIRE(c.valid()); CHECK_EQ(tup, 5); } catch (ss::exception& e) { @@ -176,7 +175,7 @@ TEST_CASE("converter test valid conversions with exceptions") { } try { - auto tup = c.convert("junk 5 junk", " "); + auto tup = c.convert("junk 5 junk", " "); REQUIRE(c.valid()); CHECK_EQ(tup, 5); } catch (ss::exception& e) { @@ -184,7 +183,7 @@ TEST_CASE("converter test valid conversions with exceptions") { } try { - auto tup = c.convert("junk\tjunk\t5", "\t"); + auto tup = c.convert("junk\tjunk\t5", "\t"); REQUIRE(c.valid()); CHECK_EQ(tup, 5); } catch (ss::exception& e) { @@ -193,7 +192,7 @@ TEST_CASE("converter test valid conversions with exceptions") { try { auto tup = - c.convert>("junk\tjunk\t5", "\t"); + c.convert>("junk\tjunk\t5", "\t"); REQUIRE(c.valid()); REQUIRE(tup.has_value()); CHECK_EQ(tup, 5); @@ -202,7 +201,7 @@ TEST_CASE("converter test valid conversions with exceptions") { } try { - auto tup = c.convert("5,6.6,junk"); + auto tup = c.convert("5,6.6,junk"); REQUIRE(c.valid()); CHECK_EQ(tup, std::make_tuple(5, 6.6)); } catch (ss::exception& e) { @@ -210,7 +209,7 @@ TEST_CASE("converter test valid conversions with exceptions") { } try { - auto tup = c.convert("5,junk,6.6"); + auto tup = c.convert("5,junk,6.6"); REQUIRE(c.valid()); CHECK_EQ(tup, std::make_tuple(5, 6.6)); } catch (ss::exception& e) { @@ -218,7 +217,7 @@ TEST_CASE("converter test valid conversions with exceptions") { } try { - auto tup = c.convert("junk;5;6.6", ";"); + auto tup = c.convert("junk;5;6.6", ";"); REQUIRE(c.valid()); CHECK_EQ(tup, std::make_tuple(5, 6.6)); } catch (ss::exception& e) { @@ -226,8 +225,7 @@ TEST_CASE("converter test valid conversions with exceptions") { } try { - auto tup = - c.convert, double>("junk;5;6.6", ";"); + auto tup = c.convert, double>("junk;5;6.6", ";"); REQUIRE(c.valid()); REQUIRE(std::get<0>(tup).has_value()); CHECK_EQ(tup, std::make_tuple(5, 6.6)); @@ -237,32 +235,31 @@ TEST_CASE("converter test valid conversions with exceptions") { try { auto tup = - c.convert, double>("junk;5.4;6.6", ";"); + c.convert, double>("junk;5.4;6.6", ";"); REQUIRE(c.valid()); REQUIRE_FALSE(std::get<0>(tup).has_value()); - CHECK_EQ(tup, std::make_tuple(std::optional{}, 6.6)); + CHECK_EQ(tup, std::make_tuple(std::optional{}, 6.6)); } catch (ss::exception& e) { FAIL(std::string{e.what()}); } try { auto tup = - c.convert, double>("junk;5;6.6", - ";"); + c.convert, double>("junk;5;6.6", ";"); REQUIRE(c.valid()); - REQUIRE(std::holds_alternative(std::get<0>(tup))); - CHECK_EQ(tup, std::make_tuple(std::variant{5}, 6.6)); + REQUIRE(std::holds_alternative(std::get<0>(tup))); + CHECK_EQ(tup, std::make_tuple(std::variant{5}, 6.6)); } catch (ss::exception& e) { FAIL(std::string{e.what()}); } try { auto tup = - c.convert, double>("junk;5.5;6.6", - ";"); + c.convert, double>("junk;5.5;6.6", + ";"); REQUIRE(c.valid()); REQUIRE(std::holds_alternative(std::get<0>(tup))); - CHECK_EQ(tup, std::make_tuple(std::variant{5.5}, 6.6)); + CHECK_EQ(tup, std::make_tuple(std::variant{5.5}, 6.6)); } catch (ss::exception& e) { FAIL(std::string{e.what()}); } @@ -278,110 +275,114 @@ TEST_CASE("converter test valid conversions with exceptions") { } } -TEST_CASE("converter test invalid conversions") { +TEST_CASE_TEMPLATE("converter test invalid conversions", T, int, ss::uint8) { ss::converter c; - c.convert(""); + c.convert(""); REQUIRE_FALSE(c.valid()); - c.convert("1", ""); + c.convert("1", ""); REQUIRE_FALSE(c.valid()); - c.convert("10", ""); + c.convert("10", ""); REQUIRE_FALSE(c.valid()); - c.convert(""); + c.convert(""); REQUIRE_FALSE(c.valid()); - c.convert(",junk"); + c.convert(",junk"); REQUIRE_FALSE(c.valid()); - c.convert("junk,"); + c.convert("junk,"); REQUIRE_FALSE(c.valid()); - c.convert("x"); + c.convert("x"); REQUIRE_FALSE(c.valid()); - c.convert("x"); + c.convert("x"); REQUIRE_FALSE(c.valid()); - c.convert("x,junk"); + c.convert("x,junk"); REQUIRE_FALSE(c.valid()); - c.convert("junk,x"); + c.convert("junk,x"); REQUIRE_FALSE(c.valid()); - c.convert, double>("junk;.5.5;6", ";"); + c.convert, double>("junk;.5.5;6", ";"); REQUIRE_FALSE(c.valid()); } -TEST_CASE("converter test invalid conversions with exceptions") { +TEST_CASE_TEMPLATE("converter test invalid conversions with exceptions", T, int, + ss::uint8) { ss::converter c; - REQUIRE_EXCEPTION(c.convert("")); - REQUIRE_EXCEPTION(c.convert("1", "")); - REQUIRE_EXCEPTION(c.convert("10", "")); - REQUIRE_EXCEPTION(c.convert("")); - REQUIRE_EXCEPTION(c.convert(",junk")); - REQUIRE_EXCEPTION(c.convert("junk,")); - REQUIRE_EXCEPTION(c.convert("x")); - REQUIRE_EXCEPTION(c.convert("x")); - REQUIRE_EXCEPTION(c.convert("x,junk")); - REQUIRE_EXCEPTION(c.convert("junk,x")); + REQUIRE_EXCEPTION(c.convert("")); + REQUIRE_EXCEPTION(c.convert("1", "")); + REQUIRE_EXCEPTION(c.convert("10", "")); + REQUIRE_EXCEPTION(c.convert("")); + REQUIRE_EXCEPTION(c.convert(",junk")); + REQUIRE_EXCEPTION(c.convert("junk,")); + REQUIRE_EXCEPTION(c.convert("x")); + REQUIRE_EXCEPTION(c.convert("x")); + REQUIRE_EXCEPTION(c.convert("x,junk")); + REQUIRE_EXCEPTION(c.convert("junk,x")); REQUIRE_EXCEPTION( - c.convert, double>("junk;.5.5;6", ";")); + c.convert, double>("junk;.5.5;6", ";")); } -TEST_CASE("converter test ss:ax restriction (all except)") { +TEST_CASE_TEMPLATE("converter test ss:ax restriction (all except)", T, int, + ss::uint8) { ss::converter c; - c.convert>("0"); + c.convert>("0"); REQUIRE_FALSE(c.valid()); - c.convert>("1"); + c.convert>("1"); REQUIRE_FALSE(c.valid()); - c.convert>("junk,c,1"); + c.convert>("junk,c,1"); REQUIRE_FALSE(c.valid()); - c.convert, char>("1,c"); + c.convert, char>("1,c"); REQUIRE_FALSE(c.valid()); { - int tup = c.convert>("3"); + T tup = c.convert>("3"); REQUIRE(c.valid()); CHECK_EQ(tup, 3); } { - std::tuple tup = c.convert>("c,3"); + std::tuple tup = c.convert>("c,3"); REQUIRE(c.valid()); CHECK_EQ(tup, std::make_tuple('c', 3)); } { - std::tuple tup = c.convert, char>("3,c"); + std::tuple tup = c.convert, char>("3,c"); REQUIRE(c.valid()); CHECK_EQ(tup, std::make_tuple(3, 'c')); } } -TEST_CASE("converter test ss:ax restriction (all except) with exceptions") { +TEST_CASE_TEMPLATE( + "converter test ss:ax restriction (all except) with exceptions", T, int, + ss::uint8) { ss::converter c; - REQUIRE_EXCEPTION(c.convert>("0")); - REQUIRE_EXCEPTION(c.convert>("1")); - REQUIRE_EXCEPTION(c.convert>("junk,c,1")); - REQUIRE_EXCEPTION(c.convert, char>("1,c")); + REQUIRE_EXCEPTION(c.convert>("0")); + REQUIRE_EXCEPTION(c.convert>("1")); + REQUIRE_EXCEPTION(c.convert>("junk,c,1")); + REQUIRE_EXCEPTION(c.convert, char>("1,c")); try { { - int tup = c.convert>("3"); + T tup = c.convert>("3"); CHECK_EQ(tup, 3); } { - std::tuple tup = c.convert>("c,3"); + std::tuple tup = c.convert>("c,3"); CHECK_EQ(tup, std::make_tuple('c', 3)); } { - std::tuple tup = c.convert, char>("3,c"); + std::tuple tup = c.convert, char>("3,c"); CHECK_EQ(tup, std::make_tuple(3, 'c')); } } catch (ss::exception& e) { @@ -456,65 +457,68 @@ TEST_CASE("converter test ss:nx restriction (none except) with exceptions") { } } -TEST_CASE("converter test ss:ir restriction (in range)") { +TEST_CASE_TEMPLATE("converter test ss:ir restriction (in range)", T, int, + ss::uint8) { ss::converter c; - c.convert>("3"); + c.convert>("3"); REQUIRE_FALSE(c.valid()); - c.convert>("c,3"); + c.convert>("c,3"); REQUIRE_FALSE(c.valid()); - c.convert, char>("3,c"); + c.convert, char>("3,c"); REQUIRE_FALSE(c.valid()); { - auto tup = c.convert>("3"); + auto tup = c.convert>("3"); REQUIRE(c.valid()); CHECK_EQ(tup, 3); } { - auto tup = c.convert>("2"); + auto tup = c.convert>("2"); REQUIRE(c.valid()); CHECK_EQ(tup, 2); } { - auto tup = c.convert>("c,junk,1"); + auto tup = c.convert>("c,junk,1"); REQUIRE(c.valid()); CHECK_EQ(tup, std::make_tuple('c', 1)); } { - auto tup = c.convert, char>("1,c"); + auto tup = c.convert, char>("1,c"); REQUIRE(c.valid()); CHECK_EQ(tup, std::make_tuple(1, 'c')); } } -TEST_CASE("converter test ss:ir restriction (in range) with exceptions") { +TEST_CASE_TEMPLATE( + "converter test ss:ir restriction (in range) with exceptions", T, int, + ss::uint8) { ss::converter c; - REQUIRE_EXCEPTION(c.convert>("3")); - REQUIRE_EXCEPTION(c.convert>("c,3")); - REQUIRE_EXCEPTION(c.convert, char>("3,c")); + REQUIRE_EXCEPTION(c.convert>("3")); + REQUIRE_EXCEPTION(c.convert>("c,3")); + REQUIRE_EXCEPTION(c.convert, char>("3,c")); try { { - auto tup = c.convert>("3"); + auto tup = c.convert>("3"); REQUIRE(c.valid()); CHECK_EQ(tup, 3); } { - auto tup = c.convert>("2"); + auto tup = c.convert>("2"); REQUIRE(c.valid()); CHECK_EQ(tup, 2); } { - auto tup = c.convert>("c,junk,1"); + auto tup = c.convert>("c,junk,1"); REQUIRE(c.valid()); CHECK_EQ(tup, std::make_tuple('c', 1)); } { - auto tup = c.convert, char>("1,c"); + auto tup = c.convert, char>("1,c"); REQUIRE(c.valid()); CHECK_EQ(tup, std::make_tuple(1, 'c')); } @@ -978,4 +982,3 @@ TEST_CASE("converter test invalid split conversions with exceptions") { buff(R"(just,some,2,"strings\")"))); CHECK(c.unterminated_quote()); } - diff --git a/test/test_extractions.cpp b/test/test_extractions.cpp index 4cab853..1765809 100644 --- a/test/test_extractions.cpp +++ b/test/test_extractions.cpp @@ -2,6 +2,16 @@ #include #include +template +struct std::numeric_limits> + : public std::numeric_limits {}; + +template +struct std::is_signed> : public std::is_signed {}; + +template +struct std::is_unsigned> : public std::is_unsigned {}; + TEST_CASE("testing extract functions for floating point values") { CHECK_FLOATING_CONVERSION(123.456, float); CHECK_FLOATING_CONVERSION(123.456, double); @@ -22,18 +32,18 @@ TEST_CASE("testing extract functions for floating point values") { #define CHECK_DECIMAL_CONVERSION(input, type) \ { \ std::string s = #input; \ - auto t = ss::to_num(s.c_str(), s.c_str() + s.size()); \ - REQUIRE(t.has_value()); \ - CHECK_EQ(t.value(), type(input)); \ + type value; \ + bool valid = ss::extract(s.c_str(), s.c_str() + s.size(), value); \ + REQUIRE(valid); \ + CHECK_EQ(value, type(input)); \ } \ - { \ - /* check negative too */ \ - if (std::is_signed_v) { \ - auto s = std::string("-") + #input; \ - auto t = ss::to_num(s.c_str(), s.c_str() + s.size()); \ - REQUIRE(t.has_value()); \ - CHECK_EQ(t.value(), type(-input)); \ - } \ + /* check negative too */ \ + if (std::is_signed_v) { \ + std::string s = std::string("-") + #input; \ + type value; \ + bool valid = ss::extract(s.c_str(), s.c_str() + s.size(), value); \ + REQUIRE(valid); \ + CHECK_EQ(value, type(-input)); \ } using us = unsigned short; @@ -43,6 +53,8 @@ using ll = long long; using ull = unsigned long long; TEST_CASE("extract test functions for decimal values") { + CHECK_DECIMAL_CONVERSION(12, ss::int8); + CHECK_DECIMAL_CONVERSION(12, ss::uint8); CHECK_DECIMAL_CONVERSION(1234, short); CHECK_DECIMAL_CONVERSION(1234, us); CHECK_DECIMAL_CONVERSION(1234, int); @@ -54,6 +66,9 @@ TEST_CASE("extract test functions for decimal values") { } TEST_CASE("extract test functions for numbers with invalid inputs") { + // negative unsigned value for numeric_wrapper + CHECK_INVALID_CONVERSION("-12", ss::uint8); + // negative unsigned value CHECK_INVALID_CONVERSION("-1234", ul); @@ -70,46 +85,38 @@ TEST_CASE("extract test functions for numbers with invalid inputs") { CHECK_INVALID_CONVERSION("", int); } -#define CHECK_OUT_OF_RANGE_CONVERSION(type) \ - { \ - std::string s = std::to_string(std::numeric_limits::max()); \ - auto t = ss::to_num(s.c_str(), s.c_str() + s.size()); \ - CHECK(t.has_value()); \ - for (auto& i : s) { \ - if (i != '9' && i != '.') { \ - i = '9'; \ - break; \ - } \ - } \ - t = ss::to_num(s.c_str(), s.c_str() + s.size()); \ - CHECK_FALSE(t.has_value()); \ - } \ - { \ - std::string s = std::to_string(std::numeric_limits::min()); \ - auto t = ss::to_num(s.c_str(), s.c_str() + s.size()); \ - CHECK(t.has_value()); \ - for (auto& i : s) { \ - if (std::is_signed_v && i != '9' && i != '.') { \ - i = '9'; \ - break; \ - } else if (std::is_unsigned_v) { \ - s = "-1"; \ - break; \ - } \ - } \ - t = ss::to_num(s.c_str(), s.c_str() + s.size()); \ - CHECK_FALSE(t.has_value()); \ +TEST_CASE_TEMPLATE( + "extract test functions for numbers with out of range inputs", T, short, us, + int, ui, long, ul, ll, ull, ss::uint8) { + { + std::string s = std::to_string(std::numeric_limits::max()); + auto t = ss::to_num(s.c_str(), s.c_str() + s.size()); + CHECK(t.has_value()); + for (auto& i : s) { + if (i != '9' && i != '.') { + i = '9'; + break; + } + } + t = ss::to_num(s.c_str(), s.c_str() + s.size()); + CHECK_FALSE(t.has_value()); + } + { + std::string s = std::to_string(std::numeric_limits::min()); + auto t = ss::to_num(s.c_str(), s.c_str() + s.size()); + CHECK(t.has_value()); + for (auto& i : s) { + if (std::is_signed_v && i != '9' && i != '.') { + i = '9'; + break; + } else if (std::is_unsigned_v) { + s = "-1"; + break; + } + } + t = ss::to_num(s.c_str(), s.c_str() + s.size()); + CHECK_FALSE(t.has_value()); } - -TEST_CASE("extract test functions for numbers with out of range inputs") { - CHECK_OUT_OF_RANGE_CONVERSION(short); - CHECK_OUT_OF_RANGE_CONVERSION(us); - CHECK_OUT_OF_RANGE_CONVERSION(int); - CHECK_OUT_OF_RANGE_CONVERSION(ui); - CHECK_OUT_OF_RANGE_CONVERSION(long); - CHECK_OUT_OF_RANGE_CONVERSION(ul); - CHECK_OUT_OF_RANGE_CONVERSION(ll); - CHECK_OUT_OF_RANGE_CONVERSION(ull); } TEST_CASE("extract test functions for boolean values") { @@ -142,12 +149,12 @@ TEST_CASE("extract test functions for char values") { } } -TEST_CASE("extract test functions for std::optional") { - for (const auto& [i, s] : - {std::pair, std::string>{1, "1"}, - {69, "69"}, - {-4, "-4"}}) { - std::optional v; +TEST_CASE_TEMPLATE("extract test functions for std::optional", T, int, + ss::int8) { + for (const auto& [i, s] : {std::pair, std::string>{1, "1"}, + {69, "69"}, + {-4, "-4"}}) { + std::optional v; REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), v)); REQUIRE(v.has_value()); CHECK_EQ(*v, i); @@ -164,7 +171,7 @@ TEST_CASE("extract test functions for std::optional") { } for (const std::string s : {"aa", "xxx", ""}) { - std::optional v; + std::optional v; REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), v)); CHECK_FALSE(v.has_value()); } @@ -176,56 +183,57 @@ TEST_CASE("extract test functions for std::optional") { } } -TEST_CASE("extract test functions for std::variant") { +TEST_CASE_TEMPLATE("extract test functions for std::variant", T, int, + ss::uint8) { { std::string s = "22"; { - std::variant var; + std::variant var; REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var)); CHECK_NOT_VARIANT(var, double); CHECK_NOT_VARIANT(var, std::string); - REQUIRE_VARIANT(var, 22, int); + REQUIRE_VARIANT(var, 22, T); } { - std::variant var; + std::variant var; REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var)); - CHECK_NOT_VARIANT(var, int); + CHECK_NOT_VARIANT(var, T); CHECK_NOT_VARIANT(var, std::string); REQUIRE_VARIANT(var, 22, double); } { - std::variant var; + std::variant var; REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var)); - CHECK_NOT_VARIANT(var, int); + CHECK_NOT_VARIANT(var, T); CHECK_NOT_VARIANT(var, double); REQUIRE_VARIANT(var, "22", std::string); } { - std::variant var; + std::variant var; REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var)); - REQUIRE_VARIANT(var, 22, int); + REQUIRE_VARIANT(var, 22, T); } } { std::string s = "22.2"; { - std::variant var; + std::variant var; REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var)); - CHECK_NOT_VARIANT(var, int); + CHECK_NOT_VARIANT(var, T); CHECK_NOT_VARIANT(var, std::string); REQUIRE_VARIANT(var, 22.2, double); } { - std::variant var; + std::variant var; REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var)); - CHECK_NOT_VARIANT(var, int); + CHECK_NOT_VARIANT(var, T); CHECK_NOT_VARIANT(var, std::string); REQUIRE_VARIANT(var, 22.2, double); } { - std::variant var; + std::variant var; REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var)); - CHECK_NOT_VARIANT(var, int); + CHECK_NOT_VARIANT(var, T); CHECK_NOT_VARIANT(var, double); REQUIRE_VARIANT(var, "22.2", std::string); } @@ -233,45 +241,45 @@ TEST_CASE("extract test functions for std::variant") { { std::string s = "2.2.2"; { - std::variant var; + std::variant var; REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var)); - CHECK_NOT_VARIANT(var, int); + CHECK_NOT_VARIANT(var, T); CHECK_NOT_VARIANT(var, double); REQUIRE_VARIANT(var, "2.2.2", std::string); } { - std::variant var; + std::variant var; REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var)); - CHECK_NOT_VARIANT(var, int); + CHECK_NOT_VARIANT(var, T); CHECK_NOT_VARIANT(var, double); REQUIRE_VARIANT(var, "2.2.2", std::string); } { - std::variant var; + std::variant var; REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var)); - CHECK_NOT_VARIANT(var, int); + CHECK_NOT_VARIANT(var, T); CHECK_NOT_VARIANT(var, double); REQUIRE_VARIANT(var, "2.2.2", std::string); } { - std::variant var; + std::variant var; REQUIRE_FALSE(ss::extract(s.c_str(), s.c_str() + s.size(), var)); - REQUIRE_VARIANT(var, int{}, int); + REQUIRE_VARIANT(var, T{}, T); CHECK_NOT_VARIANT(var, double); } { - std::variant var; + std::variant var; REQUIRE_FALSE(ss::extract(s.c_str(), s.c_str() + s.size(), var)); REQUIRE_VARIANT(var, double{}, double); - CHECK_NOT_VARIANT(var, int); + CHECK_NOT_VARIANT(var, T); } { - std::variant var; + std::variant var; REQUIRE_FALSE(ss::extract(s.c_str(), s.c_str() + s.size(), var)); - REQUIRE_VARIANT(var, int{}, int); + REQUIRE_VARIANT(var, T{}, T); } } }