Skip to content

Commit

Permalink
options: Add all type support for vector parsing (#1597)
Browse files Browse the repository at this point in the history
options: Add int and string vector parsing support
  • Loading branch information
mwestphal authored Aug 31, 2024
1 parent 368233b commit 6ef173d
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 28 deletions.
60 changes: 36 additions & 24 deletions library/private/options_tools.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,45 @@ namespace f3d
{
namespace options_tools
{
// TODO expose parse methods in options API ?

//----------------------------------------------------------------------------
/**
* Not implemented generic templated parse method
* A std::string_view trim function
*/
std::string trim(std::string_view strv)
{
constexpr std::string_view spaces = " \t\r\v\n";
strv.remove_prefix(std::min(strv.find_first_not_of(spaces), strv.size()));
strv.remove_suffix(std::min(strv.size() - strv.find_last_not_of(spaces) - 1, strv.size()));
return std::string(strv);
}

//----------------------------------------------------------------------------
/**
* Vector specific templated parse method
*/
template<typename T>
struct is_vector : std::false_type
{
};
template<typename... Args>
struct is_vector<std::vector<Args...>> : std::true_type
{
};
template<typename T>
T parse(const std::string& str) = delete;
T parse(const std::string& str)
{
static_assert(is_vector<T>::value, "non-vector types parsing must be specialized");

// TODO implement more parsing possibilities, eg different types of tokens
T vec;
std::istringstream split(str);
for (std::string each; std::getline(split, each, ',');)
{
vec.emplace_back(options_tools::parse<typename T::value_type>(each));
}
return vec;
}

//----------------------------------------------------------------------------
/**
Expand Down Expand Up @@ -100,31 +131,12 @@ ratio_t parse(const std::string& str)

//----------------------------------------------------------------------------
/**
* Return provided string
* Return provided string stripped of leading and trailing spaces.
*/
template<>
std::string parse(const std::string& str)
{
return str;
}

//----------------------------------------------------------------------------
/**
* Parse provided string into a double vector
* Split the string using ',', then rely on double version for parsing each token
* Can throw options::parsing_exception in case of failure to parse
*/
template<>
std::vector<double> parse(const std::string& str)
{
// TODO implement more parsing possibilities, eg different types of tokens
std::vector<double> vec;
std::istringstream split(str);
for (std::string each; std::getline(split, each, ',');)
{
vec.emplace_back(options_tools::parse<double>(each));
}
return vec;
return options_tools::trim(str);
}

// TODO Improve string generation
Expand Down
4 changes: 3 additions & 1 deletion library/public/options.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,9 @@ public:

/**
* Templated parsing method used internally to parse strings.
* Implemented only for: bool, int, double, ratio_t, string and double vector.
* Implemented only for types: bool, int, double, ratio_t,
* as well as vector for each of these types.
* See parsing documentation for more info. TODO.
* Throw an options::parsing_exception if parsing failed.
*/
template<typename T>
Expand Down
7 changes: 5 additions & 2 deletions library/src/options.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,16 @@ T options::parse(const std::string& str)
}

//----------------------------------------------------------------------------
#define F3D_DECL_TYPE(TYPE) template F3D_EXPORT TYPE options::parse<TYPE>(const std::string& str)
#define F3D_DECL_TYPE_INTERNAL(TYPE) \
template F3D_EXPORT TYPE options::parse<TYPE>(const std::string& str)
#define F3D_DECL_TYPE(TYPE) \
F3D_DECL_TYPE_INTERNAL(TYPE); \
F3D_DECL_TYPE_INTERNAL(std::vector<TYPE>)
F3D_DECL_TYPE(bool);
F3D_DECL_TYPE(int);
F3D_DECL_TYPE(double);
F3D_DECL_TYPE(f3d::ratio_t);
F3D_DECL_TYPE(std::string);
F3D_DECL_TYPE(std::vector<double>);

//----------------------------------------------------------------------------
options::parsing_exception::parsing_exception(const std::string& what)
Expand Down
14 changes: 13 additions & 1 deletion library/testing/TestSDKOptions.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -312,17 +312,29 @@ int TestSDKOptions(int argc, char* argv[])
std::cerr << "Options parse method not behaving as expected with ratio_t." << std::endl;
return EXIT_FAILURE;
}
if (f3d::options::parse<std::string>(std::string("foobar")) != "foobar")
if (f3d::options::parse<std::string>(std::string(" foobar ")) != "foobar")
{
std::cerr << "Options parse method not behaving as expected with string." << std::endl;
return EXIT_FAILURE;
}
if (f3d::options::parse<std::vector<int>>(std::string("1, 2, 3")) !=
std::vector<int>({ 1, 2, 3 }))
{
std::cerr << "Options parse method not behaving as expected with int vector." << std::endl;
return EXIT_FAILURE;
}
if (f3d::options::parse<std::vector<double>>(std::string("0.1, 0.2, 0.3")) !=
std::vector<double>({ 0.1, 0.2, 0.3 }))
{
std::cerr << "Options parse method not behaving as expected with double vector." << std::endl;
return EXIT_FAILURE;
}
if (f3d::options::parse<std::vector<std::string>>(std::string("foo, bar, baz")) !=
std::vector<std::string>({ "foo", "bar", "baz" }))
{
std::cerr << "Options parse method not behaving as expected with string vector." << std::endl;
return EXIT_FAILURE;
}

return EXIT_SUCCESS;
}

0 comments on commit 6ef173d

Please sign in to comment.