Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • mpim-sw/cdo
1 result
Show changes
Commits on Source (3)
......@@ -328,7 +328,7 @@ setup_options()
CLIOptions::option("set_missval", "m")
->describe_argument("missval")
->add_effect([&](const std::string &argument) {
auto [success, mv] = string_to_number<double>(argument);
auto [success, mv] = string_to_floating<double>(argument);
if (success)
{
Debug("set missval of cdi to: %f", mv);
......
......@@ -63,19 +63,50 @@ string_contains(const std::string &s, unsigned char ch)
}
template <typename Precission>
std::tuple<bool, Precission>
Precission
string_to_number(const std::string &str)
{
static_assert(std::is_arithmetic<Precission>::value, "Only arithmetic types allowed");
std::stringstream ss(str);
if (str.empty()) { throw std::invalid_argument("Error, conversion of " + str + " not possible, string empty"); }
std::stringstream ss(str);
Precission number = 0.0;
ss >> number;
if (!ss.eof()) { return { false, std::numeric_limits<Precission>::quiet_NaN() }; }
if (!ss.eof()) { throw std::invalid_argument("Error, conversion of " + str + " not possible"); }
return number;
}
template <typename Precission>
std::tuple<bool, Precission>
string_to_integral(const std::string &str)
{
static_assert(std::is_integral<Precission>::value, "Only integral number types allowed");
Precission number;
/* clang-format off */
try
{ number = string_to_number<Precission>(str); }
catch (std::invalid_argument &e)
{ return { false, std::numeric_limits<Precission>::max() }; }
/* clang-format on */
return { true, number };
}
template <typename Precission>
std::tuple<bool, Precission>
string_to_floating(const std::string &str)
{
static_assert(std::is_floating_point<Precission>::value, "Only floating point number types allowed");
Precission number;
/* clang-format off */
try
{ number = string_to_number<Precission>(str); }
catch (std::invalid_argument &e)
{ return { false, std::numeric_limits<Precission>::quiet_NaN() }; }
/* clang-format on */
return { true, number };
}
namespace Util
{
namespace String
......
......@@ -36,7 +36,7 @@ test_string_to_number_unsigned()
bandit::it(msg, [&]() {
bool success;
T result;
std::tie(success, result) = string_to_number<T>(to_be_tested[i]);
std::tie(success, result) = string_to_integral<T>(to_be_tested[i]);
AssertThat(success, Equals(true));
AssertThat(result, Equals(expected[i]));
});
......@@ -58,7 +58,7 @@ test_string_to_number()
std::vector<std::string> to_be_tested;
std::vector<T> expected;
to_be_tested = { "1", "0", str_num_max.str(), "-1", str_num_min.str() };
to_be_tested = { "1", "0", str_num_max.str(), "-1", str_num_min.str() };
expected = { 1, 0, std::numeric_limits<T>::max(), -1, std::numeric_limits<T>::min() };
for (std::size_t i = 0; i < to_be_tested.size(); i++)
......@@ -67,7 +67,7 @@ test_string_to_number()
bandit::it(msg, [&]() {
bool success;
T result;
std::tie(success, result) = string_to_number<T>(to_be_tested[i]);
std::tie(success, result) = string_to_integral<T>(to_be_tested[i]);
AssertThat(success, Equals(true));
AssertThat(result, Equals(expected[i]));
});
......@@ -86,8 +86,7 @@ test_string_to_number_fl()
std::stringstream str_num_min;
str_num_min << std::setprecision(std::numeric_limits<T>::max_digits10) << num_min;
std::vector<std::string> to_be_tested
= { "0.0", "0", "0.0e1", "2.e3", "2.0e3", "2.0625", str_num_max.str(), str_num_min.str() };
std::vector<std::string> to_be_tested = { "0.0", "0", "0.0e1", "2.e3", "2.0e3", "2.0625", str_num_max.str(), str_num_min.str() };
std::vector<T> expected = { 0, 0, 0, 2000, 2000, 2.0625, num_max, num_min };
for (std::size_t i = 0; i < to_be_tested.size(); i++)
{
......@@ -95,14 +94,14 @@ test_string_to_number_fl()
bandit::it(msg, [&]() {
bool success;
T result;
std::tie(success, result) = string_to_number<T>(to_be_tested[i]);
std::tie(success, result) = string_to_floating<T>(to_be_tested[i]);
AssertThat(success, Equals(true));
AssertThat(result, Equals(expected[i]));
});
}
}
template <typename T>
template <auto func>
void
test_string_to_number_failures()
{
......@@ -111,13 +110,29 @@ test_string_to_number_failures()
{
auto msg = "correctly throws error on " + to_be_tested[i];
bandit::it(msg, [&]() {
auto [success, result] = string_to_number<T>(to_be_tested[i]);
auto [success, result] = func(to_be_tested[i]);
AssertThat(success, Equals(false));
AssertThat(std::isnan(result), Equals(true));
});
}
}
template <auto func>
void
test_string_to_integral_failures()
{
std::vector<std::string> to_be_tested = { "1.0", "a2", "2a", "2e" };
for (std::size_t i = 0; i < to_be_tested.size(); i++)
{
auto msg = "correctly throws error on " + to_be_tested[i];
bandit::it(msg, [&]() {
auto [success, result] = func(to_be_tested[i]);
AssertThat(success, Equals(false));
AssertThat(std::numeric_limits<decltype(result)>::max(), Equals(result));
});
}
}
go_bandit([]() {
//==============================================================================
//
......@@ -143,9 +158,50 @@ go_bandit([]() {
});
bandit::describe("Testing string_to_number negatives", []() {
bandit::describe("Testing errors for float", []() { test_string_to_number_failures<float>(); });
bandit::describe("Testing errors for double", []() { test_string_to_number_failures<double>(); });
bandit::describe("Testing errors for long double", []() { test_string_to_number_failures<long double>(); });
bandit::describe("Testing errors for float", []() {
test_string_to_number_failures<string_to_floating<float>>();
bandit::it("correctly throws error on empty string with float", [&]() {
auto [success_f, result_f] = string_to_floating<float>("");
AssertThat(success_f, Equals(false));
AssertThat(std::isnan(result_f), Equals(true));
});
});
bandit::describe("Testing errors for double", []() { test_string_to_number_failures<string_to_floating<double>>();
bandit::it("correctly throws error on empty string with double", [&]() {
auto [success_d, result_d] = string_to_floating<double>("");
AssertThat(success_d, Equals(false));
AssertThat(std::isnan(result_d), Equals(true));
});
});
bandit::describe("Testing errors for long double", []() {
test_string_to_number_failures<string_to_floating<long double>>();
bandit::it("correctly throws error on empty string with long double", [&]() {
auto [success_d, result_d] = string_to_floating<long double>("");
AssertThat(success_d, Equals(false));
AssertThat(std::isnan(result_d), Equals(true));
});
});
bandit::describe("Testing errors for int", []() {
test_string_to_integral_failures<string_to_integral<int>>();
bandit::it("correctly throws error on empty string with int", [&]() {
auto [success_i, result_i] = string_to_integral<int>("");
AssertThat(success_i, Equals(false));
AssertThat(std::numeric_limits<int>::max(), Equals(result_i));
});
});
bandit::describe("Testing errors for int", []() {
test_string_to_integral_failures<string_to_integral<unsigned int>>();
bandit::it("correctly throws error on empty string with unsigned int", [&]() {
auto [success_ui, result_ui] = string_to_integral<unsigned int>("");
AssertThat(success_ui, Equals(false));
AssertThat(std::numeric_limits<unsigned int>::max(), Equals(result_ui));
});
});
});
});
......