Compare commits

..

5 Commits

Author SHA1 Message Date
ado
b660310acf [skip ci] Merge with master 2024-02-25 18:27:26 +01:00
ado
0a695cf09e Add ss::uint8 and ss::int8, add unit tests for them 2024-02-25 17:46:35 +01:00
ado
f8e14b1fcf [skip ci] Add std:: to invoked C std lib functions 2024-02-25 13:03:52 +01:00
red0124
a27fd121a1
Merge pull request #34 from red0124/improvement/getline_update
Fix reallocation issues with non-POSIX get_line
2024-02-23 23:04:19 +01:00
ado
c0d3087f85 Fix reallocation issues with non-POSIX get_line 2024-02-23 21:56:44 +01:00
9 changed files with 329 additions and 226 deletions

View File

@ -29,7 +29,7 @@ inline void assert_throw_on_error_not_defined() {
} }
inline void* strict_realloc(void* ptr, size_t size) { inline void* strict_realloc(void* ptr, size_t size) {
ptr = realloc(ptr, size); ptr = std::realloc(ptr, size);
if (!ptr) { if (!ptr) {
throw std::bad_alloc{}; throw std::bad_alloc{};
} }
@ -62,18 +62,17 @@ ssize_t get_line_file(char** lineptr, size_t* n, FILE* fp) {
(*lineptr)[0] = '\0'; (*lineptr)[0] = '\0';
size_t line_used = 0; size_t line_used = 0;
while (fgets(buff, sizeof(buff), fp) != nullptr) { while (std::fgets(buff, sizeof(buff), fp) != nullptr) {
line_used = strlen(*lineptr); line_used = std::strlen(*lineptr);
size_t buff_used = strlen(buff); size_t buff_used = std::strlen(buff);
if (*n <= buff_used + line_used) { if (*n <= buff_used + line_used) {
size_t new_n = *n * 2; size_t new_n = *n * 2;
*lineptr = static_cast<char*>(strict_realloc(*lineptr, new_n)); *lineptr = static_cast<char*>(strict_realloc(*lineptr, new_n));
*n = new_n; *n = new_n;
} }
memcpy(*lineptr + line_used, buff, buff_used); std::memcpy(*lineptr + line_used, buff, buff_used);
line_used += buff_used; line_used += buff_used;
(*lineptr)[line_used] = '\0'; (*lineptr)[line_used] = '\0';

View File

@ -77,6 +77,38 @@ std::enable_if_t<std::is_floating_point_v<T>, std::optional<T>> to_num(
#endif #endif
////////////////
// numeric_wrapper
////////////////
template <typename T>
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<int8_t>;
using uint8 = numeric_wrapper<uint8_t>;
template <typename T> template <typename T>
std::enable_if_t<std::is_integral_v<T>, std::optional<T>> to_num( std::enable_if_t<std::is_integral_v<T>, std::optional<T>> to_num(
const char* const begin, const char* const end) { const char* const begin, const char* const end) {
@ -89,6 +121,18 @@ std::enable_if_t<std::is_integral_v<T>, std::optional<T>> to_num(
return ret; return ret;
} }
template <typename T>
std::enable_if_t<is_instance_of_v<numeric_wrapper, T>, std::optional<T>> 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 // extract
//////////////// ////////////////
@ -103,7 +147,8 @@ struct unsupported_type {
template <typename T> template <typename T>
std::enable_if_t<!std::is_integral_v<T> && !std::is_floating_point_v<T> && std::enable_if_t<!std::is_integral_v<T> && !std::is_floating_point_v<T> &&
!is_instance_of_v<std::optional, T> && !is_instance_of_v<std::optional, T> &&
!is_instance_of_v<std::variant, T>, !is_instance_of_v<std::variant, T> &&
!is_instance_of_v<numeric_wrapper, T>,
bool> bool>
extract(const char*, const char*, T&) { extract(const char*, const char*, T&) {
static_assert(error::unsupported_type<T>::value, static_assert(error::unsupported_type<T>::value,
@ -112,7 +157,9 @@ extract(const char*, const char*, T&) {
} }
template <typename T> template <typename T>
std::enable_if_t<std::is_integral_v<T> || std::is_floating_point_v<T>, bool> std::enable_if_t<std::is_integral_v<T> || std::is_floating_point_v<T> ||
is_instance_of_v<numeric_wrapper, T>,
bool>
extract(const char* begin, const char* end, T& value) { extract(const char* begin, const char* end, T& value) {
auto optional_value = to_num<T>(begin, end); auto optional_value = to_num<T>(begin, end);
if (!optional_value) { if (!optional_value) {
@ -169,9 +216,9 @@ inline bool extract(const char* begin, const char* end, bool& value) {
} }
} else { } else {
size_t size = end - begin; size_t size = end - begin;
if (size == 4 && strncmp(begin, "true", size) == 0) { if (size == 4 && std::strncmp(begin, "true", size) == 0) {
value = true; value = true;
} else if (size == 5 && strncmp(begin, "false", size) == 0) { } else if (size == 5 && std::strncmp(begin, "false", size) == 0) {
value = false; value = false;
} else { } else {
return false; return false;

View File

@ -675,7 +675,7 @@ private:
struct reader { struct reader {
reader(const std::string& file_name_, const std::string& delim) reader(const std::string& file_name_, const std::string& delim)
: delim_{delim}, file_{fopen(file_name_.c_str(), "rb")} { : delim_{delim}, file_{std::fopen(file_name_.c_str(), "rb")} {
} }
reader(const char* const buffer, size_t csv_data_size, reader(const char* const buffer, size_t csv_data_size,
@ -736,12 +736,12 @@ private:
} }
~reader() { ~reader() {
free(buffer_); std::free(buffer_);
free(next_line_buffer_); std::free(next_line_buffer_);
free(helper_buffer_); std::free(helper_buffer_);
if (file_) { if (file_) {
fclose(file_); std::fclose(file_);
} }
} }
@ -800,7 +800,7 @@ private:
if (file_) { if (file_) {
ssize = get_line_file(&next_line_buffer_, ssize = get_line_file(&next_line_buffer_,
&next_line_buffer_size_, file_); &next_line_buffer_size_, file_);
curr_char_ = ftell(file_); curr_char_ = std::ftell(file_);
} else { } else {
ssize = get_line_buffer(&next_line_buffer_, ssize = get_line_buffer(&next_line_buffer_,
&next_line_buffer_size_, &next_line_buffer_size_,

View File

@ -199,7 +199,7 @@ private:
}; };
bool match(const char* const curr, const std::string& delim) { bool match(const char* const curr, const std::string& delim) {
return strncmp(curr, delim.c_str(), delim.size()) == 0; return std::strncmp(curr, delim.c_str(), delim.size()) == 0;
}; };
size_t delimiter_size(char) { size_t delimiter_size(char) {

80
ssp.hpp
View File

@ -641,7 +641,7 @@ inline void assert_throw_on_error_not_defined() {
} }
inline void* strict_realloc(void* ptr, size_t size) { inline void* strict_realloc(void* ptr, size_t size) {
ptr = realloc(ptr, size); ptr = std::realloc(ptr, size);
if (!ptr) { if (!ptr) {
throw std::bad_alloc{}; throw std::bad_alloc{};
} }
@ -674,18 +674,17 @@ ssize_t get_line_file(char** lineptr, size_t* n, FILE* fp) {
(*lineptr)[0] = '\0'; (*lineptr)[0] = '\0';
size_t line_used = 0; size_t line_used = 0;
while (fgets(buff, sizeof(buff), fp) != nullptr) { while (std::fgets(buff, sizeof(buff), fp) != nullptr) {
line_used = strlen(*lineptr); line_used = std::strlen(*lineptr);
size_t buff_used = strlen(buff); size_t buff_used = std::strlen(buff);
if (*n <= buff_used + line_used) { if (*n <= buff_used + line_used) {
size_t new_n = *n * 2; size_t new_n = *n * 2;
*lineptr = static_cast<char*>(strict_realloc(*lineptr, new_n)); *lineptr = static_cast<char*>(strict_realloc(*lineptr, new_n));
*n = new_n; *n = new_n;
} }
memcpy(*lineptr + line_used, buff, buff_used); std::memcpy(*lineptr + line_used, buff, buff_used);
line_used += buff_used; line_used += buff_used;
(*lineptr)[line_used] = '\0'; (*lineptr)[line_used] = '\0';
@ -1183,7 +1182,7 @@ private:
}; };
bool match(const char* const curr, const std::string& delim) { bool match(const char* const curr, const std::string& delim) {
return strncmp(curr, delim.c_str(), delim.size()) == 0; return std::strncmp(curr, delim.c_str(), delim.size()) == 0;
}; };
size_t delimiter_size(char) { size_t delimiter_size(char) {
@ -1531,6 +1530,38 @@ std::enable_if_t<std::is_floating_point_v<T>, std::optional<T>> to_num(
#endif #endif
////////////////
// numeric_wrapper
////////////////
template <typename T>
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<int8_t>;
using uint8 = numeric_wrapper<uint8_t>;
template <typename T> template <typename T>
std::enable_if_t<std::is_integral_v<T>, std::optional<T>> to_num( std::enable_if_t<std::is_integral_v<T>, std::optional<T>> to_num(
const char* const begin, const char* const end) { const char* const begin, const char* const end) {
@ -1543,6 +1574,18 @@ std::enable_if_t<std::is_integral_v<T>, std::optional<T>> to_num(
return ret; return ret;
} }
template <typename T>
std::enable_if_t<is_instance_of_v<numeric_wrapper, T>, std::optional<T>> 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 // extract
//////////////// ////////////////
@ -1557,7 +1600,8 @@ struct unsupported_type {
template <typename T> template <typename T>
std::enable_if_t<!std::is_integral_v<T> && !std::is_floating_point_v<T> && std::enable_if_t<!std::is_integral_v<T> && !std::is_floating_point_v<T> &&
!is_instance_of_v<std::optional, T> && !is_instance_of_v<std::optional, T> &&
!is_instance_of_v<std::variant, T>, !is_instance_of_v<std::variant, T> &&
!is_instance_of_v<numeric_wrapper, T>,
bool> bool>
extract(const char*, const char*, T&) { extract(const char*, const char*, T&) {
static_assert(error::unsupported_type<T>::value, static_assert(error::unsupported_type<T>::value,
@ -1566,7 +1610,9 @@ extract(const char*, const char*, T&) {
} }
template <typename T> template <typename T>
std::enable_if_t<std::is_integral_v<T> || std::is_floating_point_v<T>, bool> std::enable_if_t<std::is_integral_v<T> || std::is_floating_point_v<T> ||
is_instance_of_v<numeric_wrapper, T>,
bool>
extract(const char* begin, const char* end, T& value) { extract(const char* begin, const char* end, T& value) {
auto optional_value = to_num<T>(begin, end); auto optional_value = to_num<T>(begin, end);
if (!optional_value) { if (!optional_value) {
@ -1623,9 +1669,9 @@ inline bool extract(const char* begin, const char* end, bool& value) {
} }
} else { } else {
size_t size = end - begin; size_t size = end - begin;
if (size == 4 && strncmp(begin, "true", size) == 0) { if (size == 4 && std::strncmp(begin, "true", size) == 0) {
value = true; value = true;
} else if (size == 5 && strncmp(begin, "false", size) == 0) { } else if (size == 5 && std::strncmp(begin, "false", size) == 0) {
value = false; value = false;
} else { } else {
return false; return false;
@ -2805,7 +2851,7 @@ private:
struct reader { struct reader {
reader(const std::string& file_name_, const std::string& delim) reader(const std::string& file_name_, const std::string& delim)
: delim_{delim}, file_{fopen(file_name_.c_str(), "rb")} { : delim_{delim}, file_{std::fopen(file_name_.c_str(), "rb")} {
} }
reader(const char* const buffer, size_t csv_data_size, reader(const char* const buffer, size_t csv_data_size,
@ -2866,12 +2912,12 @@ private:
} }
~reader() { ~reader() {
free(buffer_); std::free(buffer_);
free(next_line_buffer_); std::free(next_line_buffer_);
free(helper_buffer_); std::free(helper_buffer_);
if (file_) { if (file_) {
fclose(file_); std::fclose(file_);
} }
} }
@ -2930,7 +2976,7 @@ private:
if (file_) { if (file_) {
ssize = get_line_file(&next_line_buffer_, ssize = get_line_file(&next_line_buffer_,
&next_line_buffer_size_, file_); &next_line_buffer_size_, file_);
curr_char_ = ftell(file_); curr_char_ = std::ftell(file_);
} else { } else {
ssize = get_line_buffer(&next_line_buffer_, ssize = get_line_buffer(&next_line_buffer_,
&next_line_buffer_size_, &next_line_buffer_size_,

View File

@ -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; ss::converter c;
{ {
auto tup = c.convert<int>("5"); auto tup = c.convert<T>("5");
REQUIRE(c.valid()); REQUIRE(c.valid());
CHECK_EQ(tup, 5); CHECK_EQ(tup, 5);
} }
{ {
auto tup = c.convert<int, void>("5,junk"); auto tup = c.convert<T, void>("5,junk");
REQUIRE(c.valid()); REQUIRE(c.valid());
CHECK_EQ(tup, 5); CHECK_EQ(tup, 5);
} }
{ {
auto tup = c.convert<void, int>("junk,5"); auto tup = c.convert<void, T>("junk,5");
REQUIRE(c.valid()); REQUIRE(c.valid());
CHECK_EQ(tup, 5); CHECK_EQ(tup, 5);
} }
{ {
auto tup = c.convert<int, void, void>("5\njunk\njunk", "\n"); auto tup = c.convert<T, void, void>("5\njunk\njunk", "\n");
REQUIRE(c.valid()); REQUIRE(c.valid());
CHECK_EQ(tup, 5); CHECK_EQ(tup, 5);
} }
{ {
auto tup = c.convert<void, int, void>("junk 5 junk", " "); auto tup = c.convert<void, T, void>("junk 5 junk", " ");
REQUIRE(c.valid()); REQUIRE(c.valid());
CHECK_EQ(tup, 5); CHECK_EQ(tup, 5);
} }
{ {
auto tup = c.convert<void, void, int>("junk\tjunk\t5", "\t"); auto tup = c.convert<void, void, T>("junk\tjunk\t5", "\t");
REQUIRE(c.valid()); REQUIRE(c.valid());
CHECK_EQ(tup, 5); CHECK_EQ(tup, 5);
} }
{ {
auto tup = auto tup =
c.convert<void, void, std::optional<int>>("junk\tjunk\t5", "\t"); c.convert<void, void, std::optional<T>>("junk\tjunk\t5", "\t");
REQUIRE(c.valid()); REQUIRE(c.valid());
REQUIRE(tup.has_value()); REQUIRE(tup.has_value());
CHECK_EQ(tup, 5); CHECK_EQ(tup, 5);
} }
{ {
auto tup = c.convert<int, double, void>("5,6.6,junk"); auto tup = c.convert<T, double, void>("5,6.6,junk");
REQUIRE(c.valid()); REQUIRE(c.valid());
CHECK_EQ(tup, std::make_tuple(5, 6.6)); CHECK_EQ(tup, std::make_tuple(5, 6.6));
} }
{ {
auto tup = c.convert<int, void, double>("5,junk,6.6"); auto tup = c.convert<T, void, double>("5,junk,6.6");
REQUIRE(c.valid()); REQUIRE(c.valid());
CHECK_EQ(tup, std::make_tuple(5, 6.6)); CHECK_EQ(tup, std::make_tuple(5, 6.6));
} }
{ {
auto tup = c.convert<void, int, double>("junk;5;6.6", ";"); auto tup = c.convert<void, T, double>("junk;5;6.6", ";");
REQUIRE(c.valid()); REQUIRE(c.valid());
CHECK_EQ(tup, std::make_tuple(5, 6.6)); CHECK_EQ(tup, std::make_tuple(5, 6.6));
} }
{ {
auto tup = auto tup = c.convert<void, std::optional<T>, double>("junk;5;6.6", ";");
c.convert<void, std::optional<int>, double>("junk;5;6.6", ";");
REQUIRE(c.valid()); REQUIRE(c.valid());
REQUIRE(std::get<0>(tup).has_value()); REQUIRE(std::get<0>(tup).has_value());
CHECK_EQ(tup, std::make_tuple(5, 6.6)); CHECK_EQ(tup, std::make_tuple(5, 6.6));
} }
{ {
auto tup = auto tup =
c.convert<void, std::optional<int>, double>("junk;5.4;6.6", ";"); c.convert<void, std::optional<T>, double>("junk;5.4;6.6", ";");
REQUIRE(c.valid()); REQUIRE(c.valid());
REQUIRE_FALSE(std::get<0>(tup).has_value()); REQUIRE_FALSE(std::get<0>(tup).has_value());
CHECK_EQ(tup, std::make_tuple(std::optional<int>{}, 6.6)); CHECK_EQ(tup, std::make_tuple(std::optional<T>{}, 6.6));
} }
{ {
auto tup = auto tup =
c.convert<void, std::variant<int, double>, double>("junk;5;6.6", c.convert<void, std::variant<T, double>, double>("junk;5;6.6", ";");
";");
REQUIRE(c.valid()); REQUIRE(c.valid());
REQUIRE(std::holds_alternative<int>(std::get<0>(tup))); REQUIRE(std::holds_alternative<T>(std::get<0>(tup)));
CHECK_EQ(tup, std::make_tuple(std::variant<int, double>{5}, 6.6)); CHECK_EQ(tup, std::make_tuple(std::variant<T, double>{5}, 6.6));
} }
{ {
auto tup = auto tup =
c.convert<void, std::variant<int, double>, double>("junk;5.5;6.6", c.convert<void, std::variant<T, double>, double>("junk;5.5;6.6",
";"); ";");
REQUIRE(c.valid()); REQUIRE(c.valid());
REQUIRE(std::holds_alternative<double>(std::get<0>(tup))); REQUIRE(std::holds_alternative<double>(std::get<0>(tup)));
CHECK_EQ(tup, std::make_tuple(std::variant<int, double>{5.5}, 6.6)); CHECK_EQ(tup, std::make_tuple(std::variant<T, double>{5.5}, 6.6));
} }
{ {
auto tup = c.convert<void, std::string_view, double, auto tup = c.convert<void, std::string_view, double,
@ -140,11 +138,12 @@ TEST_CASE("converter test valid conversions") {
} }
} }
TEST_CASE("converter test valid conversions with exceptions") { TEST_CASE_TEMPLATE("converter test valid conversions with exceptions", T, int,
ss::uint8) {
ss::converter<ss::throw_on_error> c; ss::converter<ss::throw_on_error> c;
try { try {
auto tup = c.convert<int>("5"); auto tup = c.convert<T>("5");
REQUIRE(c.valid()); REQUIRE(c.valid());
CHECK_EQ(tup, 5); CHECK_EQ(tup, 5);
} catch (ss::exception& e) { } catch (ss::exception& e) {
@ -152,7 +151,7 @@ TEST_CASE("converter test valid conversions with exceptions") {
} }
try { try {
auto tup = c.convert<int, void>("5,junk"); auto tup = c.convert<T, void>("5,junk");
REQUIRE(c.valid()); REQUIRE(c.valid());
CHECK_EQ(tup, 5); CHECK_EQ(tup, 5);
} catch (ss::exception& e) { } catch (ss::exception& e) {
@ -160,7 +159,7 @@ TEST_CASE("converter test valid conversions with exceptions") {
} }
try { try {
auto tup = c.convert<void, int>("junk,5"); auto tup = c.convert<void, T>("junk,5");
REQUIRE(c.valid()); REQUIRE(c.valid());
CHECK_EQ(tup, 5); CHECK_EQ(tup, 5);
} catch (ss::exception& e) { } catch (ss::exception& e) {
@ -168,7 +167,7 @@ TEST_CASE("converter test valid conversions with exceptions") {
} }
try { try {
auto tup = c.convert<int, void, void>("5\njunk\njunk", "\n"); auto tup = c.convert<T, void, void>("5\njunk\njunk", "\n");
REQUIRE(c.valid()); REQUIRE(c.valid());
CHECK_EQ(tup, 5); CHECK_EQ(tup, 5);
} catch (ss::exception& e) { } catch (ss::exception& e) {
@ -176,7 +175,7 @@ TEST_CASE("converter test valid conversions with exceptions") {
} }
try { try {
auto tup = c.convert<void, int, void>("junk 5 junk", " "); auto tup = c.convert<void, T, void>("junk 5 junk", " ");
REQUIRE(c.valid()); REQUIRE(c.valid());
CHECK_EQ(tup, 5); CHECK_EQ(tup, 5);
} catch (ss::exception& e) { } catch (ss::exception& e) {
@ -184,7 +183,7 @@ TEST_CASE("converter test valid conversions with exceptions") {
} }
try { try {
auto tup = c.convert<void, void, int>("junk\tjunk\t5", "\t"); auto tup = c.convert<void, void, T>("junk\tjunk\t5", "\t");
REQUIRE(c.valid()); REQUIRE(c.valid());
CHECK_EQ(tup, 5); CHECK_EQ(tup, 5);
} catch (ss::exception& e) { } catch (ss::exception& e) {
@ -193,7 +192,7 @@ TEST_CASE("converter test valid conversions with exceptions") {
try { try {
auto tup = auto tup =
c.convert<void, void, std::optional<int>>("junk\tjunk\t5", "\t"); c.convert<void, void, std::optional<T>>("junk\tjunk\t5", "\t");
REQUIRE(c.valid()); REQUIRE(c.valid());
REQUIRE(tup.has_value()); REQUIRE(tup.has_value());
CHECK_EQ(tup, 5); CHECK_EQ(tup, 5);
@ -202,7 +201,7 @@ TEST_CASE("converter test valid conversions with exceptions") {
} }
try { try {
auto tup = c.convert<int, double, void>("5,6.6,junk"); auto tup = c.convert<T, double, void>("5,6.6,junk");
REQUIRE(c.valid()); REQUIRE(c.valid());
CHECK_EQ(tup, std::make_tuple(5, 6.6)); CHECK_EQ(tup, std::make_tuple(5, 6.6));
} catch (ss::exception& e) { } catch (ss::exception& e) {
@ -210,7 +209,7 @@ TEST_CASE("converter test valid conversions with exceptions") {
} }
try { try {
auto tup = c.convert<int, void, double>("5,junk,6.6"); auto tup = c.convert<T, void, double>("5,junk,6.6");
REQUIRE(c.valid()); REQUIRE(c.valid());
CHECK_EQ(tup, std::make_tuple(5, 6.6)); CHECK_EQ(tup, std::make_tuple(5, 6.6));
} catch (ss::exception& e) { } catch (ss::exception& e) {
@ -218,7 +217,7 @@ TEST_CASE("converter test valid conversions with exceptions") {
} }
try { try {
auto tup = c.convert<void, int, double>("junk;5;6.6", ";"); auto tup = c.convert<void, T, double>("junk;5;6.6", ";");
REQUIRE(c.valid()); REQUIRE(c.valid());
CHECK_EQ(tup, std::make_tuple(5, 6.6)); CHECK_EQ(tup, std::make_tuple(5, 6.6));
} catch (ss::exception& e) { } catch (ss::exception& e) {
@ -226,8 +225,7 @@ TEST_CASE("converter test valid conversions with exceptions") {
} }
try { try {
auto tup = auto tup = c.convert<void, std::optional<T>, double>("junk;5;6.6", ";");
c.convert<void, std::optional<int>, double>("junk;5;6.6", ";");
REQUIRE(c.valid()); REQUIRE(c.valid());
REQUIRE(std::get<0>(tup).has_value()); REQUIRE(std::get<0>(tup).has_value());
CHECK_EQ(tup, std::make_tuple(5, 6.6)); CHECK_EQ(tup, std::make_tuple(5, 6.6));
@ -237,32 +235,31 @@ TEST_CASE("converter test valid conversions with exceptions") {
try { try {
auto tup = auto tup =
c.convert<void, std::optional<int>, double>("junk;5.4;6.6", ";"); c.convert<void, std::optional<T>, double>("junk;5.4;6.6", ";");
REQUIRE(c.valid()); REQUIRE(c.valid());
REQUIRE_FALSE(std::get<0>(tup).has_value()); REQUIRE_FALSE(std::get<0>(tup).has_value());
CHECK_EQ(tup, std::make_tuple(std::optional<int>{}, 6.6)); CHECK_EQ(tup, std::make_tuple(std::optional<T>{}, 6.6));
} catch (ss::exception& e) { } catch (ss::exception& e) {
FAIL(std::string{e.what()}); FAIL(std::string{e.what()});
} }
try { try {
auto tup = auto tup =
c.convert<void, std::variant<int, double>, double>("junk;5;6.6", c.convert<void, std::variant<T, double>, double>("junk;5;6.6", ";");
";");
REQUIRE(c.valid()); REQUIRE(c.valid());
REQUIRE(std::holds_alternative<int>(std::get<0>(tup))); REQUIRE(std::holds_alternative<T>(std::get<0>(tup)));
CHECK_EQ(tup, std::make_tuple(std::variant<int, double>{5}, 6.6)); CHECK_EQ(tup, std::make_tuple(std::variant<T, double>{5}, 6.6));
} catch (ss::exception& e) { } catch (ss::exception& e) {
FAIL(std::string{e.what()}); FAIL(std::string{e.what()});
} }
try { try {
auto tup = auto tup =
c.convert<void, std::variant<int, double>, double>("junk;5.5;6.6", c.convert<void, std::variant<T, double>, double>("junk;5.5;6.6",
";"); ";");
REQUIRE(c.valid()); REQUIRE(c.valid());
REQUIRE(std::holds_alternative<double>(std::get<0>(tup))); REQUIRE(std::holds_alternative<double>(std::get<0>(tup)));
CHECK_EQ(tup, std::make_tuple(std::variant<int, double>{5.5}, 6.6)); CHECK_EQ(tup, std::make_tuple(std::variant<T, double>{5.5}, 6.6));
} catch (ss::exception& e) { } catch (ss::exception& e) {
FAIL(std::string{e.what()}); 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; ss::converter c;
c.convert<int>(""); c.convert<T>("");
REQUIRE_FALSE(c.valid()); REQUIRE_FALSE(c.valid());
c.convert<int>("1", ""); c.convert<T>("1", "");
REQUIRE_FALSE(c.valid()); REQUIRE_FALSE(c.valid());
c.convert<int>("10", ""); c.convert<T>("10", "");
REQUIRE_FALSE(c.valid()); REQUIRE_FALSE(c.valid());
c.convert<int, void>(""); c.convert<T, void>("");
REQUIRE_FALSE(c.valid()); REQUIRE_FALSE(c.valid());
c.convert<int, void>(",junk"); c.convert<T, void>(",junk");
REQUIRE_FALSE(c.valid()); REQUIRE_FALSE(c.valid());
c.convert<void, int>("junk,"); c.convert<void, T>("junk,");
REQUIRE_FALSE(c.valid()); REQUIRE_FALSE(c.valid());
c.convert<int>("x"); c.convert<T>("x");
REQUIRE_FALSE(c.valid()); REQUIRE_FALSE(c.valid());
c.convert<int, void>("x"); c.convert<T, void>("x");
REQUIRE_FALSE(c.valid()); REQUIRE_FALSE(c.valid());
c.convert<int, void>("x,junk"); c.convert<T, void>("x,junk");
REQUIRE_FALSE(c.valid()); REQUIRE_FALSE(c.valid());
c.convert<void, int>("junk,x"); c.convert<void, T>("junk,x");
REQUIRE_FALSE(c.valid()); REQUIRE_FALSE(c.valid());
c.convert<void, std::variant<int, double>, double>("junk;.5.5;6", ";"); c.convert<void, std::variant<T, double>, double>("junk;.5.5;6", ";");
REQUIRE_FALSE(c.valid()); 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<ss::throw_on_error> c; ss::converter<ss::throw_on_error> c;
REQUIRE_EXCEPTION(c.convert<int>("")); REQUIRE_EXCEPTION(c.convert<T>(""));
REQUIRE_EXCEPTION(c.convert<int>("1", "")); REQUIRE_EXCEPTION(c.convert<T>("1", ""));
REQUIRE_EXCEPTION(c.convert<int>("10", "")); REQUIRE_EXCEPTION(c.convert<T>("10", ""));
REQUIRE_EXCEPTION(c.convert<int, void>("")); REQUIRE_EXCEPTION(c.convert<T, void>(""));
REQUIRE_EXCEPTION(c.convert<int, void>(",junk")); REQUIRE_EXCEPTION(c.convert<T, void>(",junk"));
REQUIRE_EXCEPTION(c.convert<void, int>("junk,")); REQUIRE_EXCEPTION(c.convert<void, T>("junk,"));
REQUIRE_EXCEPTION(c.convert<int>("x")); REQUIRE_EXCEPTION(c.convert<T>("x"));
REQUIRE_EXCEPTION(c.convert<int, void>("x")); REQUIRE_EXCEPTION(c.convert<T, void>("x"));
REQUIRE_EXCEPTION(c.convert<int, void>("x,junk")); REQUIRE_EXCEPTION(c.convert<T, void>("x,junk"));
REQUIRE_EXCEPTION(c.convert<void, int>("junk,x")); REQUIRE_EXCEPTION(c.convert<void, T>("junk,x"));
REQUIRE_EXCEPTION( REQUIRE_EXCEPTION(
c.convert<void, std::variant<int, double>, double>("junk;.5.5;6", ";")); c.convert<void, std::variant<T, double>, 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; ss::converter c;
c.convert<ss::ax<int, 0>>("0"); c.convert<ss::ax<T, 0>>("0");
REQUIRE_FALSE(c.valid()); REQUIRE_FALSE(c.valid());
c.convert<ss::ax<int, 0, 1, 2>>("1"); c.convert<ss::ax<T, 0, 1, 2>>("1");
REQUIRE_FALSE(c.valid()); REQUIRE_FALSE(c.valid());
c.convert<void, char, ss::ax<int, 0, 1, 2>>("junk,c,1"); c.convert<void, char, ss::ax<T, 0, 1, 2>>("junk,c,1");
REQUIRE_FALSE(c.valid()); REQUIRE_FALSE(c.valid());
c.convert<ss::ax<int, 1>, char>("1,c"); c.convert<ss::ax<T, 1>, char>("1,c");
REQUIRE_FALSE(c.valid()); REQUIRE_FALSE(c.valid());
{ {
int tup = c.convert<ss::ax<int, 1>>("3"); T tup = c.convert<ss::ax<T, 1>>("3");
REQUIRE(c.valid()); REQUIRE(c.valid());
CHECK_EQ(tup, 3); CHECK_EQ(tup, 3);
} }
{ {
std::tuple<char, int> tup = c.convert<char, ss::ax<int, 1>>("c,3"); std::tuple<char, T> tup = c.convert<char, ss::ax<T, 1>>("c,3");
REQUIRE(c.valid()); REQUIRE(c.valid());
CHECK_EQ(tup, std::make_tuple('c', 3)); CHECK_EQ(tup, std::make_tuple('c', 3));
} }
{ {
std::tuple<int, char> tup = c.convert<ss::ax<int, 1>, char>("3,c"); std::tuple<T, char> tup = c.convert<ss::ax<T, 1>, char>("3,c");
REQUIRE(c.valid()); REQUIRE(c.valid());
CHECK_EQ(tup, std::make_tuple(3, 'c')); 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<ss::throw_on_error> c; ss::converter<ss::throw_on_error> c;
REQUIRE_EXCEPTION(c.convert<ss::ax<int, 0>>("0")); REQUIRE_EXCEPTION(c.convert<ss::ax<T, 0>>("0"));
REQUIRE_EXCEPTION(c.convert<ss::ax<int, 0, 1, 2>>("1")); REQUIRE_EXCEPTION(c.convert<ss::ax<T, 0, 1, 2>>("1"));
REQUIRE_EXCEPTION(c.convert<void, char, ss::ax<int, 0, 1, 2>>("junk,c,1")); REQUIRE_EXCEPTION(c.convert<void, char, ss::ax<T, 0, 1, 2>>("junk,c,1"));
REQUIRE_EXCEPTION(c.convert<ss::ax<int, 1>, char>("1,c")); REQUIRE_EXCEPTION(c.convert<ss::ax<T, 1>, char>("1,c"));
try { try {
{ {
int tup = c.convert<ss::ax<int, 1>>("3"); T tup = c.convert<ss::ax<T, 1>>("3");
CHECK_EQ(tup, 3); CHECK_EQ(tup, 3);
} }
{ {
std::tuple<char, int> tup = c.convert<char, ss::ax<int, 1>>("c,3"); std::tuple<char, T> tup = c.convert<char, ss::ax<T, 1>>("c,3");
CHECK_EQ(tup, std::make_tuple('c', 3)); CHECK_EQ(tup, std::make_tuple('c', 3));
} }
{ {
std::tuple<int, char> tup = c.convert<ss::ax<int, 1>, char>("3,c"); std::tuple<T, char> tup = c.convert<ss::ax<T, 1>, char>("3,c");
CHECK_EQ(tup, std::make_tuple(3, 'c')); CHECK_EQ(tup, std::make_tuple(3, 'c'));
} }
} catch (ss::exception& e) { } 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; ss::converter c;
c.convert<ss::ir<int, 0, 2>>("3"); c.convert<ss::ir<T, 0, 2>>("3");
REQUIRE_FALSE(c.valid()); REQUIRE_FALSE(c.valid());
c.convert<char, ss::ir<int, 4, 69>>("c,3"); c.convert<char, ss::ir<T, 4, 69>>("c,3");
REQUIRE_FALSE(c.valid()); REQUIRE_FALSE(c.valid());
c.convert<ss::ir<int, 1, 2>, char>("3,c"); c.convert<ss::ir<T, 1, 2>, char>("3,c");
REQUIRE_FALSE(c.valid()); REQUIRE_FALSE(c.valid());
{ {
auto tup = c.convert<ss::ir<int, 1, 5>>("3"); auto tup = c.convert<ss::ir<T, 1, 5>>("3");
REQUIRE(c.valid()); REQUIRE(c.valid());
CHECK_EQ(tup, 3); CHECK_EQ(tup, 3);
} }
{ {
auto tup = c.convert<ss::ir<int, 0, 2>>("2"); auto tup = c.convert<ss::ir<T, 0, 2>>("2");
REQUIRE(c.valid()); REQUIRE(c.valid());
CHECK_EQ(tup, 2); CHECK_EQ(tup, 2);
} }
{ {
auto tup = c.convert<char, void, ss::ir<int, 0, 1>>("c,junk,1"); auto tup = c.convert<char, void, ss::ir<T, 0, 1>>("c,junk,1");
REQUIRE(c.valid()); REQUIRE(c.valid());
CHECK_EQ(tup, std::make_tuple('c', 1)); CHECK_EQ(tup, std::make_tuple('c', 1));
} }
{ {
auto tup = c.convert<ss::ir<int, 1, 20>, char>("1,c"); auto tup = c.convert<ss::ir<T, 1, 20>, char>("1,c");
REQUIRE(c.valid()); REQUIRE(c.valid());
CHECK_EQ(tup, std::make_tuple(1, 'c')); 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<ss::throw_on_error> c; ss::converter<ss::throw_on_error> c;
REQUIRE_EXCEPTION(c.convert<ss::ir<int, 0, 2>>("3")); REQUIRE_EXCEPTION(c.convert<ss::ir<T, 0, 2>>("3"));
REQUIRE_EXCEPTION(c.convert<char, ss::ir<int, 4, 69>>("c,3")); REQUIRE_EXCEPTION(c.convert<char, ss::ir<T, 4, 69>>("c,3"));
REQUIRE_EXCEPTION(c.convert<ss::ir<int, 1, 2>, char>("3,c")); REQUIRE_EXCEPTION(c.convert<ss::ir<T, 1, 2>, char>("3,c"));
try { try {
{ {
auto tup = c.convert<ss::ir<int, 1, 5>>("3"); auto tup = c.convert<ss::ir<T, 1, 5>>("3");
REQUIRE(c.valid()); REQUIRE(c.valid());
CHECK_EQ(tup, 3); CHECK_EQ(tup, 3);
} }
{ {
auto tup = c.convert<ss::ir<int, 0, 2>>("2"); auto tup = c.convert<ss::ir<T, 0, 2>>("2");
REQUIRE(c.valid()); REQUIRE(c.valid());
CHECK_EQ(tup, 2); CHECK_EQ(tup, 2);
} }
{ {
auto tup = c.convert<char, void, ss::ir<int, 0, 1>>("c,junk,1"); auto tup = c.convert<char, void, ss::ir<T, 0, 1>>("c,junk,1");
REQUIRE(c.valid()); REQUIRE(c.valid());
CHECK_EQ(tup, std::make_tuple('c', 1)); CHECK_EQ(tup, std::make_tuple('c', 1));
} }
{ {
auto tup = c.convert<ss::ir<int, 1, 20>, char>("1,c"); auto tup = c.convert<ss::ir<T, 1, 20>, char>("1,c");
REQUIRE(c.valid()); REQUIRE(c.valid());
CHECK_EQ(tup, std::make_tuple(1, 'c')); 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\")"))); buff(R"(just,some,2,"strings\")")));
CHECK(c.unterminated_quote()); CHECK(c.unterminated_quote());
} }

View File

@ -2,6 +2,16 @@
#include <algorithm> #include <algorithm>
#include <ss/extract.hpp> #include <ss/extract.hpp>
template <typename T>
struct std::numeric_limits<ss::numeric_wrapper<T>>
: public std::numeric_limits<T> {};
template <typename T>
struct std::is_signed<ss::numeric_wrapper<T>> : public std::is_signed<T> {};
template <typename T>
struct std::is_unsigned<ss::numeric_wrapper<T>> : public std::is_unsigned<T> {};
TEST_CASE("testing extract functions for floating point values") { TEST_CASE("testing extract functions for floating point values") {
CHECK_FLOATING_CONVERSION(123.456, float); CHECK_FLOATING_CONVERSION(123.456, float);
CHECK_FLOATING_CONVERSION(123.456, double); 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) \ #define CHECK_DECIMAL_CONVERSION(input, type) \
{ \ { \
std::string s = #input; \ std::string s = #input; \
auto t = ss::to_num<type>(s.c_str(), s.c_str() + s.size()); \ type value; \
REQUIRE(t.has_value()); \ bool valid = ss::extract(s.c_str(), s.c_str() + s.size(), value); \
CHECK_EQ(t.value(), type(input)); \ REQUIRE(valid); \
CHECK_EQ(value, type(input)); \
} \ } \
{ \ /* check negative too */ \
/* check negative too */ \ if (std::is_signed_v<type>) { \
if (std::is_signed_v<type>) { \ std::string s = std::string("-") + #input; \
auto s = std::string("-") + #input; \ type value; \
auto t = ss::to_num<type>(s.c_str(), s.c_str() + s.size()); \ bool valid = ss::extract(s.c_str(), s.c_str() + s.size(), value); \
REQUIRE(t.has_value()); \ REQUIRE(valid); \
CHECK_EQ(t.value(), type(-input)); \ CHECK_EQ(value, type(-input)); \
} \
} }
using us = unsigned short; using us = unsigned short;
@ -43,6 +53,8 @@ using ll = long long;
using ull = unsigned long long; using ull = unsigned long long;
TEST_CASE("extract test functions for decimal values") { 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, short);
CHECK_DECIMAL_CONVERSION(1234, us); CHECK_DECIMAL_CONVERSION(1234, us);
CHECK_DECIMAL_CONVERSION(1234, int); 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") { 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 // negative unsigned value
CHECK_INVALID_CONVERSION("-1234", ul); CHECK_INVALID_CONVERSION("-1234", ul);
@ -70,46 +85,38 @@ TEST_CASE("extract test functions for numbers with invalid inputs") {
CHECK_INVALID_CONVERSION("", int); CHECK_INVALID_CONVERSION("", int);
} }
#define CHECK_OUT_OF_RANGE_CONVERSION(type) \ TEST_CASE_TEMPLATE(
{ \ "extract test functions for numbers with out of range inputs", T, short, us,
std::string s = std::to_string(std::numeric_limits<type>::max()); \ int, ui, long, ul, ll, ull, ss::uint8) {
auto t = ss::to_num<type>(s.c_str(), s.c_str() + s.size()); \ {
CHECK(t.has_value()); \ std::string s = std::to_string(std::numeric_limits<T>::max());
for (auto& i : s) { \ auto t = ss::to_num<T>(s.c_str(), s.c_str() + s.size());
if (i != '9' && i != '.') { \ CHECK(t.has_value());
i = '9'; \ for (auto& i : s) {
break; \ if (i != '9' && i != '.') {
} \ i = '9';
} \ break;
t = ss::to_num<type>(s.c_str(), s.c_str() + s.size()); \ }
CHECK_FALSE(t.has_value()); \ }
} \ t = ss::to_num<T>(s.c_str(), s.c_str() + s.size());
{ \ CHECK_FALSE(t.has_value());
std::string s = std::to_string(std::numeric_limits<type>::min()); \ }
auto t = ss::to_num<type>(s.c_str(), s.c_str() + s.size()); \ {
CHECK(t.has_value()); \ std::string s = std::to_string(std::numeric_limits<T>::min());
for (auto& i : s) { \ auto t = ss::to_num<T>(s.c_str(), s.c_str() + s.size());
if (std::is_signed_v<type> && i != '9' && i != '.') { \ CHECK(t.has_value());
i = '9'; \ for (auto& i : s) {
break; \ if (std::is_signed_v<T> && i != '9' && i != '.') {
} else if (std::is_unsigned_v<type>) { \ i = '9';
s = "-1"; \ break;
break; \ } else if (std::is_unsigned_v<T>) {
} \ s = "-1";
} \ break;
t = ss::to_num<type>(s.c_str(), s.c_str() + s.size()); \ }
CHECK_FALSE(t.has_value()); \ }
t = ss::to_num<T>(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") { 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") { TEST_CASE_TEMPLATE("extract test functions for std::optional", T, int,
for (const auto& [i, s] : ss::int8) {
{std::pair<std::optional<int>, std::string>{1, "1"}, for (const auto& [i, s] : {std::pair<std::optional<T>, std::string>{1, "1"},
{69, "69"}, {69, "69"},
{-4, "-4"}}) { {-4, "-4"}}) {
std::optional<int> v; std::optional<T> v;
REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), v)); REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), v));
REQUIRE(v.has_value()); REQUIRE(v.has_value());
CHECK_EQ(*v, i); CHECK_EQ(*v, i);
@ -164,7 +171,7 @@ TEST_CASE("extract test functions for std::optional") {
} }
for (const std::string s : {"aa", "xxx", ""}) { for (const std::string s : {"aa", "xxx", ""}) {
std::optional<int> v; std::optional<T> v;
REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), v)); REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), v));
CHECK_FALSE(v.has_value()); 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::string s = "22";
{ {
std::variant<int, double, std::string> var; std::variant<T, double, std::string> var;
REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var)); REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var));
CHECK_NOT_VARIANT(var, double); CHECK_NOT_VARIANT(var, double);
CHECK_NOT_VARIANT(var, std::string); CHECK_NOT_VARIANT(var, std::string);
REQUIRE_VARIANT(var, 22, int); REQUIRE_VARIANT(var, 22, T);
} }
{ {
std::variant<double, int, std::string> var; std::variant<double, T, std::string> var;
REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), 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); CHECK_NOT_VARIANT(var, std::string);
REQUIRE_VARIANT(var, 22, double); REQUIRE_VARIANT(var, 22, double);
} }
{ {
std::variant<std::string, double, int> var; std::variant<std::string, double, T> var;
REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), 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); CHECK_NOT_VARIANT(var, double);
REQUIRE_VARIANT(var, "22", std::string); REQUIRE_VARIANT(var, "22", std::string);
} }
{ {
std::variant<int> var; std::variant<T> var;
REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), 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::string s = "22.2";
{ {
std::variant<int, double, std::string> var; std::variant<T, double, std::string> var;
REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), 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); CHECK_NOT_VARIANT(var, std::string);
REQUIRE_VARIANT(var, 22.2, double); REQUIRE_VARIANT(var, 22.2, double);
} }
{ {
std::variant<double, int, std::string> var; std::variant<double, T, std::string> var;
REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), 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); CHECK_NOT_VARIANT(var, std::string);
REQUIRE_VARIANT(var, 22.2, double); REQUIRE_VARIANT(var, 22.2, double);
} }
{ {
std::variant<std::string, double, int> var; std::variant<std::string, double, T> var;
REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), 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); CHECK_NOT_VARIANT(var, double);
REQUIRE_VARIANT(var, "22.2", std::string); 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::string s = "2.2.2";
{ {
std::variant<int, double, std::string> var; std::variant<T, double, std::string> var;
REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), 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); CHECK_NOT_VARIANT(var, double);
REQUIRE_VARIANT(var, "2.2.2", std::string); REQUIRE_VARIANT(var, "2.2.2", std::string);
} }
{ {
std::variant<double, std::string, int> var; std::variant<double, std::string, T> var;
REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), 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); CHECK_NOT_VARIANT(var, double);
REQUIRE_VARIANT(var, "2.2.2", std::string); REQUIRE_VARIANT(var, "2.2.2", std::string);
} }
{ {
std::variant<std::string, double, int> var; std::variant<std::string, double, T> var;
REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), 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); CHECK_NOT_VARIANT(var, double);
REQUIRE_VARIANT(var, "2.2.2", std::string); REQUIRE_VARIANT(var, "2.2.2", std::string);
} }
{ {
std::variant<int, double> var; std::variant<T, double> var;
REQUIRE_FALSE(ss::extract(s.c_str(), s.c_str() + s.size(), 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); CHECK_NOT_VARIANT(var, double);
} }
{ {
std::variant<double, int> var; std::variant<double, T> var;
REQUIRE_FALSE(ss::extract(s.c_str(), s.c_str() + s.size(), var)); REQUIRE_FALSE(ss::extract(s.c_str(), s.c_str() + s.size(), var));
REQUIRE_VARIANT(var, double{}, double); REQUIRE_VARIANT(var, double{}, double);
CHECK_NOT_VARIANT(var, int); CHECK_NOT_VARIANT(var, T);
} }
{ {
std::variant<int> var; std::variant<T> var;
REQUIRE_FALSE(ss::extract(s.c_str(), s.c_str() + s.size(), var)); REQUIRE_FALSE(ss::extract(s.c_str(), s.c_str() + s.size(), var));
REQUIRE_VARIANT(var, int{}, int); REQUIRE_VARIANT(var, T{}, T);
} }
} }
} }

View File

@ -62,12 +62,12 @@ struct buffer {
[[maybe_unused]] inline buffer buff; [[maybe_unused]] inline buffer buff;
[[maybe_unused]] std::string time_now_rand() { [[maybe_unused]] std::string time_now_rand() {
srand(time(nullptr)); std::srand(std::time(nullptr));
std::stringstream ss; std::stringstream ss;
auto t = std::time(nullptr); auto t = std::time(nullptr);
auto tm = *std::localtime(&t); auto tm = *std::localtime(&t);
ss << std::put_time(&tm, "%d%m%Y%H%M%S"); ss << std::put_time(&tm, "%d%m%Y%H%M%S");
srand(time(nullptr)); std::srand(std::time(nullptr));
return ss.str() + std::to_string(rand()); return ss.str() + std::to_string(rand());
} }
@ -78,8 +78,8 @@ struct unique_file_name {
unique_file_name(const std::string& test) { unique_file_name(const std::string& test) {
do { do {
name = "ssp_test_" + test + "_" + std::to_string(i++) + name = "ssp_test_" + test + "_" + std::to_string(i++) + "_" +
"_" + time_now_rand() + "_file.csv"; time_now_rand() + "_file.csv";
} while (std::filesystem::exists(name)); } while (std::filesystem::exists(name));
} }

View File

@ -77,9 +77,9 @@ TEST_CASE_TEMPLATE("test position method", T, ParserOptionCombinations) {
if (!buff.empty()) { if (!buff.empty()) {
return buff[n]; return buff[n];
} else { } else {
auto file = fopen(f.name.c_str(), "r"); auto file = std::fopen(f.name.c_str(), "r");
fseek(file, n, SEEK_SET); std::fseek(file, n, SEEK_SET);
return static_cast<char>(fgetc(file)); return static_cast<char>(std::fgetc(file));
} }
}; };