From b0554a3dd0ea14d2d84f3d0e9fa7f22ff1c04175 Mon Sep 17 00:00:00 2001 From: Claudius 'keldu' Holeksa Date: Wed, 31 Jul 2024 15:53:21 +0200 Subject: Basic Arg parsing support --- modules/codec/c++/args.hpp | 65 ++++++++++++++++++++++++++++++++++++++------ modules/codec/tests/args.cpp | 2 +- modules/core/c++/error.cpp | 6 ++++ modules/core/c++/error.hpp | 27 ++++++++++++++++++ 4 files changed, 91 insertions(+), 9 deletions(-) diff --git a/modules/codec/c++/args.hpp b/modules/codec/c++/args.hpp index a2b338b..e3e651d 100644 --- a/modules/codec/c++/args.hpp +++ b/modules/codec/c++/args.hpp @@ -4,6 +4,7 @@ #include "data.hpp" #include +#include namespace saw { namespace encode { @@ -59,6 +60,42 @@ struct args_decode { static_assert(always_false, "Not supported"); }; +template +struct args_decode, ToDec> { + using Schema = schema::Primitive; + + static error_or decode(data& to, std::string_view view){ + if(view.empty()){ + return make_error("Can't decode empty data."); + } + typename native_data_type::type val{}; + auto fc_res = std::from_chars(view.data(), view.data()+view.size(), val); + if(fc_res.ec != std::errc{}){ + auto err_bld = error_builder{[&](){ + return std::string{"Parsing of failed: "} + std::string{view}; + }}; + return err_bld.template make_error("Parsing failed. "); + } + to.set(val); + + return make_void(); + } +}; + +template +struct args_decode { + using Schema = schema::String; + + static error_or decode(data& to, std::string_view view){ + try{ + to.set(std::string{view}); + }catch(const std::exception&){ + return make_error(); + } + return make_void(); + } +}; + template struct args_decode...>,schema::Tuple>,ToDec> { using Schema = schema::Args< @@ -73,11 +110,12 @@ struct args_decode...>,sche static error_or decode_struct_member(data& to, std::string_view name, std::string_view value){ if constexpr ( i < sizeof...(Str) ) { static constexpr string_literal Literal = parameter_key_pack_type::literal; + using StrT = typename parameter_pack_type::type; if(Literal.view() == name){ auto& target = to.template get(); - /// @TODO - return void_t{}; + auto eov = args_decode::decode(target, value); + return eov; } return decode_struct_member(to, name, value); @@ -86,9 +124,17 @@ struct args_decode...>,sche } template - static error_or decode_tuple_member(data& to, std::string_view value){ - - return make_error(); + static error_or decode_tuple_member(data& to, uint64_t ptr_i, std::string_view value){ + if constexpr ( i < sizeof...(Tup) ){ + if ( i == ptr_i ){ + using TupT = typename parameter_pack_type::type; + auto& target = to.template get(); + + return args_decode::decode(target, value); + } + return decode_tuple_member(to, ptr_i, value); + } + return make_error("Too many positional arguments."); } static error_or decode(data& from, data& to){ @@ -97,7 +143,8 @@ struct args_decode...>,sche } to.template get<"program">().set(std::string{from.arg_view(0)}); - std::size_t tuple_pos = 0; + uint64_t tuple_pos = 0; + for(size_t i = 1; i < from.size(); ++i){ auto view = from.arg_view(i); if(view.starts_with("--")){ @@ -116,7 +163,7 @@ struct args_decode...>,sche return eov; } } else { - auto eov = decode_tuple_member<0>(to.template get<"positionals">(), view); + auto eov = decode_tuple_member<0>(to.template get<"positionals">(), tuple_pos, view); if(eov.is_error()){ return eov; } @@ -125,7 +172,7 @@ struct args_decode...>,sche } if(tuple_pos != sizeof...(Tup)){ - return make_error(); + return make_error("Didn't parse the whole set of positionals."); } return void_t{}; @@ -138,6 +185,7 @@ class codec { public: template error_or decode(data& from, data& to){ + /* struct name_and_value { std::string name; std::string value; @@ -145,6 +193,7 @@ public: std::string program; std::vector navs; std::vector positionals; + */ auto eov = impl::args_decode::decode(from,to); return eov; diff --git a/modules/codec/tests/args.cpp b/modules/codec/tests/args.cpp index ed6d918..f53b80e 100644 --- a/modules/codec/tests/args.cpp +++ b/modules/codec/tests/args.cpp @@ -40,7 +40,7 @@ SAW_TEST("Codec Args Decode"){ codec, encode::Args> args_codec; auto eov = args_codec.decode(dat_args, dat_nat); - SAW_EXPECT(eov.is_value(), "Couldn't decode data"); + SAW_EXPECT(eov.is_value(), std::string{"Couldn't decode data. "} + std::string{eov.get_error().get_category()} + std::string{" - "} + std::string{eov.get_error().get_message()}); auto& prog = dat_nat.template get<"program">(); auto& str = dat_nat.template get<"args">(); diff --git a/modules/core/c++/error.cpp b/modules/core/c++/error.cpp index 192cab6..d5132ac 100644 --- a/modules/core/c++/error.cpp +++ b/modules/core/c++/error.cpp @@ -9,6 +9,12 @@ error::error(error::code code_, bool is_critical__, const std::string_view &msg) error_code_{static_cast(code_)} , is_critical_{is_critical__}, error_message_{msg}{} + error::error(error::code code_, bool is_critical__, std::string&& msg): + error_code_{static_cast(code_)}, + is_critical_{is_critical__}, + error_message_{std::move(msg)} + {} + error::error(error &&error) : error_code_{std::move(error.error_code_)} diff --git a/modules/core/c++/error.hpp b/modules/core/c++/error.hpp index 8439f85..7a5dd8a 100644 --- a/modules/core/c++/error.hpp +++ b/modules/core/c++/error.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -40,6 +41,7 @@ private: public: error(error::code id, bool is_critical); error(error::code id, bool is_critical, const std::string_view &msg); + error(error::code id, bool is_critical, std::string&& msg); error(error &&error); SAW_FORBID_COPY(error); @@ -158,6 +160,31 @@ template error make_error(){ error make_error(error::code code, const std::string_view &generic); +struct error_builder { +private: + std::function func_; +public: + template + error_builder(Func&& func__): + func_{std::move(func__)} + {} + + template + error make_error(const std::string& generic){ + try{ + std::string err_str = func_(); + error::code id = impl::get_template_id(); + func_ = [](){return "";}; + return error{id, T::is_critical, std::move(err_str)}; + }catch(const std::exception&){} + return make_error(generic); + } +}; + +template +error_builder build_error(Func&& func){ + return error_builder{std::move(func)}; +} namespace err { struct no_error { -- cgit v1.2.3