diff --git a/include/Parser.hpp b/include/Parser.hpp index 89eddfa..dd7b0c7 100644 --- a/include/Parser.hpp +++ b/include/Parser.hpp @@ -3,26 +3,89 @@ #include "Arg.hpp" #include "utils.hpp" +#include +#include +#include +#include +#include +#include #include #include #include #include +template +struct Parse { + static std::optional parse(std::string_view s) { + if constexpr (std::is_integral_v) { + T value; + auto [ptr, ec] = std::from_chars(s.data(), s.data() + s.size(), value); + if (ec == std::errc()) return value; + return std::nullopt; + } + else if constexpr (std::is_same_v) { + char* end = nullptr; + float value = std::strtof(s.data(), &end); + if (end == s.data() + s.size()) return value; + return std::nullopt; + } + else if constexpr (std::is_same_v) { + char* end = nullptr; + double value = std::strtod(s.data(), &end); + if (end == s.data() + s.size()) return value; + return std::nullopt; + } + else if constexpr (std::is_same_v) { + char* end = nullptr; + long double value = std::strtold(s.data(), &end); + if (end == s.data() + s.size()) return value; + return std::nullopt; + } + else { + static_assert(sizeof(T) == 0, "No Parse specialization defined for this type"); + } + } +}; + +template<> +struct Parse { + static std::optional parse(std::string_view s) { + return std::string(s); + } +}; + +template<> +struct Parse { + static std::optional parse(std::string_view s) { + auto as_int = Parse::parse(s).value(); + return as_int; + } +}; + +template +concept Parseable = requires(std::string_view s) { + { Parse::parse(s) } -> std::convertible_to>; +}; + class ClapParser { public: void add_arg(const Arg& arg); void parse(const int& argc, char* argv[]); void print_help() const; - template inline std::optional get_one_as(const std::string& name) { + template + requires Parseable + inline std::optional get_one_as(const std::string& name) { Arg* arg = ok_or(ClapParser::find_arg(*this, "--" + name), []{ return std::nullopt; }); - if (auto arg_value = arg->get__value(); arg_value) { - T value; - std::istringstream(*arg_value) >> value; - return value; - } - return std::nullopt; + // if (auto arg_value = arg->get__value(); arg_value) { + // T value; + // std::istringstream(*arg_value) >> value; + // return value; + // } + // return std::nullopt; + + return Parse::parse(arg->get__value().value()); } static void print_parser(std::ostream& os, const ClapParser& parser, int indent);