| @@ -6,10 +6,6 @@ | |||||
| namespace cppargs | namespace cppargs | ||||
| { | { | ||||
| template<typename T_value, typename T_enable = void> | |||||
| struct argument_props | |||||
| { | |||||
| static std::string type(bool optional = false) = delete; | |||||
| }; | |||||
| } | } | ||||
| @@ -9,49 +9,6 @@ | |||||
| namespace cppargs | namespace cppargs | ||||
| { | { | ||||
| inline std::string enwrap_type(const std::string& type, bool optional) | |||||
| { | |||||
| auto opn = optional ? "(" : "<"; | |||||
| auto cls = optional ? ")" : ">"; | |||||
| return std::string(opn) + type + cls; | |||||
| } | |||||
| template<> | |||||
| struct argument_props<std::string, void> | |||||
| { | |||||
| static std::string type(bool optional = false) | |||||
| { return enwrap_type("string", false); } | |||||
| }; | |||||
| template<typename T_value> | |||||
| struct argument_props<T_value, utl::mp::enable_if_c<!std::is_class<T_value>::value>> | |||||
| { | |||||
| static std::string type(bool optional = false) | |||||
| { return enwrap_type(utl::type_helper<T_value>::name(), false); } | |||||
| }; | |||||
| template<typename T_value> | |||||
| struct argument_props<std::list<T_value>, void> | |||||
| { | |||||
| static std::string type(bool optional = false) | |||||
| { | |||||
| return | |||||
| argument_props<T_value>::type(false) + ' ' + | |||||
| argument_props<T_value>::type(true) + ' ' + | |||||
| enwrap_type("...", true); | |||||
| } | |||||
| }; | |||||
| template<typename T_value> | |||||
| struct argument_props<std::vector<T_value>, void> | |||||
| { | |||||
| static std::string type(bool optional = false) | |||||
| { | |||||
| return | |||||
| argument_props<T_value>::type(false) + ' ' + | |||||
| argument_props<T_value>::type(true) + ' ' + | |||||
| enwrap_type("...", true); | |||||
| } | |||||
| }; | |||||
| } | } | ||||
| @@ -5,13 +5,12 @@ | |||||
| namespace cppargs | namespace cppargs | ||||
| { | { | ||||
| template<typename T_instance, typename T_value, typename T_predicate> | |||||
| template<typename T_instance, typename T_predicate> | |||||
| struct member_predicate_option | struct member_predicate_option | ||||
| : public member_option<T_instance> | : public member_option<T_instance> | ||||
| { | { | ||||
| public: | public: | ||||
| using instance_type = T_instance; | using instance_type = T_instance; | ||||
| using value_type = T_value; | |||||
| using predicate_type = T_predicate; | using predicate_type = T_predicate; | ||||
| using base_type = member_option<instance_type>; | using base_type = member_option<instance_type>; | ||||
| @@ -5,17 +5,17 @@ | |||||
| namespace cppargs | namespace cppargs | ||||
| { | { | ||||
| template<typename T_instance, typename T_value, typename T_predicate> | |||||
| template<typename T_instance, typename T_predicate> | |||||
| template<typename... T_args> | template<typename... T_args> | ||||
| member_predicate_option<T_instance, T_value, T_predicate>::member_predicate_option( | |||||
| member_predicate_option<T_instance, T_predicate>::member_predicate_option( | |||||
| const option_meta& p_meta, | const option_meta& p_meta, | ||||
| T_args&&... args) | T_args&&... args) | ||||
| : base_type (p_meta) | : base_type (p_meta) | ||||
| , _predicate(std::forward<T_args>(args)...) | , _predicate(std::forward<T_args>(args)...) | ||||
| { } | { } | ||||
| template<typename T_instance, typename T_value, typename T_predicate> | |||||
| void member_predicate_option<T_instance, T_value, T_predicate>::parse(context& c) const | |||||
| template<typename T_instance, typename T_predicate> | |||||
| void member_predicate_option<T_instance, T_predicate>::parse(context& c) const | |||||
| { _predicate(this->instance(), c); } | { _predicate(this->instance(), c); } | ||||
| } | } | ||||
| @@ -22,11 +22,12 @@ namespace cppargs | |||||
| inline option_meta& set_long_name (const std::string& value); | inline option_meta& set_long_name (const std::string& value); | ||||
| inline option_meta& set_description (const std::string& value); | inline option_meta& set_description (const std::string& value); | ||||
| inline option_meta& set_arguments (const std::string& value); | inline option_meta& set_arguments (const std::string& value); | ||||
| inline option_meta& set_default_value (const std::string& value); | |||||
| template <typename T_value> | |||||
| inline option_meta& set_default_value (const T_value& value); | |||||
| inline option_meta& set_mandatory (bool value = true); | inline option_meta& set_mandatory (bool value = true); | ||||
| template<typename T_value> | template<typename T_value> | ||||
| static option_meta prepare_arguments(const option_meta& meta); | |||||
| static option_meta prepare(const option_meta& meta, T_value&& value); | |||||
| }; | }; | ||||
| /** | /** | ||||
| @@ -1,5 +1,6 @@ | |||||
| #pragma once | #pragma once | ||||
| #include <cpputils/misc/string.h> | |||||
| #include <cppargs/misc/misc.inl> | #include <cppargs/misc/misc.inl> | ||||
| #include "option.h" | #include "option.h" | ||||
| @@ -7,6 +8,95 @@ | |||||
| namespace cppargs | namespace cppargs | ||||
| { | { | ||||
| /* argument_props */ | |||||
| inline std::string enwrap_type(const std::string& type, bool optional) | |||||
| { | |||||
| auto opn = optional ? "(" : "<"; | |||||
| auto cls = optional ? ")" : ">"; | |||||
| return std::string(opn) + type + cls; | |||||
| } | |||||
| template<typename T_value, typename T_enable = void> | |||||
| struct argument_props | |||||
| { | |||||
| static std::string type(bool optional = false) | |||||
| { return "unknown"; }; | |||||
| }; | |||||
| template<> | |||||
| struct argument_props<std::string, void> | |||||
| { | |||||
| static std::string type(bool optional = false) | |||||
| { return enwrap_type("string", false); } | |||||
| }; | |||||
| template<typename T_value> | |||||
| struct argument_props<T_value, utl::mp::enable_if_c<!std::is_class<T_value>::value>> | |||||
| { | |||||
| static std::string type(bool optional = false) | |||||
| { return enwrap_type(utl::type_helper<T_value>::name(), false); } | |||||
| }; | |||||
| template<typename T_value> | |||||
| struct argument_props<std::list<T_value>, void> | |||||
| { | |||||
| static std::string type(bool optional = false) | |||||
| { | |||||
| return | |||||
| argument_props<T_value>::type(false) + ' ' + | |||||
| argument_props<T_value>::type(true) + ' ' + | |||||
| enwrap_type("...", true); | |||||
| } | |||||
| }; | |||||
| template<typename T_value> | |||||
| struct argument_props<std::vector<T_value>, void> | |||||
| { | |||||
| static std::string type(bool optional = false) | |||||
| { | |||||
| return | |||||
| argument_props<T_value>::type(false) + ' ' + | |||||
| argument_props<T_value>::type(true) + ' ' + | |||||
| enwrap_type("...", true); | |||||
| } | |||||
| }; | |||||
| /* prepare_impl */ | |||||
| template<typename T_value, typename T_enable = void> | |||||
| struct prepare_impl | |||||
| { | |||||
| static inline option_meta prepare(const option_meta& meta, T_value&& value) | |||||
| { | |||||
| option_meta m = meta; | |||||
| if (m.arguments.empty()) | |||||
| m.arguments = argument_props<T_value>::type(std::is_same<T_value, bool>::value); | |||||
| if (m.default_value.empty()) | |||||
| m.set_default_value(std::forward<T_value>(value)); | |||||
| return m; | |||||
| } | |||||
| }; | |||||
| template<typename T_value, typename T_object> | |||||
| struct prepare_impl< | |||||
| T_value T_object::*, | |||||
| utl::mp::enable_if_c< | |||||
| std::is_default_constructible<T_object>::value>> | |||||
| { | |||||
| static inline option_meta prepare(const option_meta& meta, T_value T_object::*member) | |||||
| { | |||||
| option_meta m = meta; | |||||
| if (m.arguments.empty()) | |||||
| m.arguments = argument_props<T_value>::type(std::is_same<T_value, bool>::value); | |||||
| if (m.default_value.empty()) | |||||
| m.set_default_value<T_value>(T_object().*member); | |||||
| return m; | |||||
| } | |||||
| }; | |||||
| /* option_meta */ | |||||
| option_meta& option_meta::set_short_name(char value) | option_meta& option_meta::set_short_name(char value) | ||||
| { | { | ||||
| short_name = value; | short_name = value; | ||||
| @@ -31,9 +121,10 @@ namespace cppargs | |||||
| return *this; | return *this; | ||||
| } | } | ||||
| option_meta& option_meta::set_default_value(const std::string& value) | |||||
| template <typename T_value> | |||||
| option_meta& option_meta::set_default_value(const T_value& value) | |||||
| { | { | ||||
| default_value = value; | |||||
| default_value = utl::to_string(value); | |||||
| return *this; | return *this; | ||||
| } | } | ||||
| @@ -44,13 +135,8 @@ namespace cppargs | |||||
| } | } | ||||
| template<typename T_value> | template<typename T_value> | ||||
| option_meta option_meta::prepare_arguments(const option_meta& meta) | |||||
| { | |||||
| option_meta m = meta; | |||||
| if (m.arguments.empty()) | |||||
| m.arguments = argument_props<T_value>::type(); | |||||
| return m; | |||||
| } | |||||
| option_meta option_meta::prepare(const option_meta& meta, T_value&& value) | |||||
| { return prepare_impl<utl::mp::decay_t<T_value>>::prepare(meta, std::forward<T_value>(value)); } | |||||
| option::option(const option_meta& p_meta) | option::option(const option_meta& p_meta) | ||||
| : meta(p_meta) | : meta(p_meta) | ||||
| @@ -13,6 +13,17 @@ namespace cppargs | |||||
| using parser::parser; | using parser::parser; | ||||
| public: | public: | ||||
| /** | |||||
| * @brief Create new member predicate option. | |||||
| * | |||||
| * @param[in] meta Meta data of the new option. | |||||
| * @param[in] predicate Predicate to execute for this option. | |||||
| * | |||||
| * @return Created option. | |||||
| */ | |||||
| template<typename T_instance, typename T_predicate> | |||||
| static constexpr decltype(auto) make_option(const option_meta& meta, T_predicate&& predicate); | |||||
| /** | /** | ||||
| * @brief Create new member option. | * @brief Create new member option. | ||||
| * | * | ||||
| @@ -22,7 +33,7 @@ namespace cppargs | |||||
| * @return Created option. | * @return Created option. | ||||
| */ | */ | ||||
| template<typename T_instance, typename T_object, typename T_value> | template<typename T_instance, typename T_object, typename T_value> | ||||
| static constexpr decltype(auto) make_member_option(const option_meta& meta, T_value T_object::*member); | |||||
| static constexpr decltype(auto) make_option(const option_meta& meta, T_value T_object::*member); | |||||
| /** | /** | ||||
| * @brief Create new group. | * @brief Create new group. | ||||
| @@ -45,7 +56,7 @@ namespace cppargs | |||||
| * @return Created group. | * @return Created group. | ||||
| */ | */ | ||||
| template<typename T_instance, typename T_object, typename T_value, typename... T_args> | template<typename T_instance, typename T_object, typename T_value, typename... T_args> | ||||
| static constexpr decltype(auto) make_member_group(const group_meta& meta, T_value T_object::*member, T_args&&... args); | |||||
| static constexpr decltype(auto) make_group(const group_meta& meta, T_value T_object::*member, T_args&&... args); | |||||
| }; | }; | ||||
| /** | /** | ||||
| @@ -11,8 +11,17 @@ | |||||
| namespace cppargs | namespace cppargs | ||||
| { | { | ||||
| template<typename T_instance, typename T_predicate> | |||||
| constexpr decltype(auto) member_parser_base::make_option(const option_meta& meta, T_predicate&& predicate) | |||||
| { | |||||
| using instance_type = T_instance; | |||||
| using predicate_type = T_predicate; | |||||
| using member_predicate_option_type = member_predicate_option<instance_type, predicate_type>; | |||||
| return std::make_unique<member_predicate_option_type>(meta, std::forward<T_predicate>(predicate)); | |||||
| } | |||||
| template<typename T_instance, typename T_object, typename T_value> | template<typename T_instance, typename T_object, typename T_value> | ||||
| constexpr decltype(auto) member_parser_base::make_member_option(const option_meta& meta, T_value T_object::*member) | |||||
| constexpr decltype(auto) member_parser_base::make_option(const option_meta& meta, T_value T_object::*member) | |||||
| { | { | ||||
| static_assert(std::is_base_of<T_object, T_instance>::value, "Member pointer must be in the instance type."); | static_assert(std::is_base_of<T_object, T_instance>::value, "Member pointer must be in the instance type."); | ||||
| @@ -26,9 +35,9 @@ namespace cppargs | |||||
| }; | }; | ||||
| using predicate_type = decltype(predicate); | using predicate_type = decltype(predicate); | ||||
| using member_predicate_option_type = member_predicate_option<instance_type, value_type, predicate_type>; | |||||
| using member_predicate_option_type = member_predicate_option<instance_type, predicate_type>; | |||||
| return std::make_unique<member_predicate_option_type>( | return std::make_unique<member_predicate_option_type>( | ||||
| option_meta::prepare_arguments<T_value>(meta), | |||||
| option_meta::prepare(meta, member), | |||||
| std::move(predicate)); | std::move(predicate)); | ||||
| } | } | ||||
| @@ -47,7 +56,7 @@ namespace cppargs | |||||
| } | } | ||||
| template<typename T_instance, typename T_object, typename T_value, typename... T_args> | template<typename T_instance, typename T_object, typename T_value, typename... T_args> | ||||
| constexpr decltype(auto) member_parser_base::make_member_group(const group_meta& meta, T_value T_object::*member, T_args&&... args) | |||||
| constexpr decltype(auto) member_parser_base::make_group(const group_meta& meta, T_value T_object::*member, T_args&&... args) | |||||
| { | { | ||||
| using owner_instance_type = T_instance; | using owner_instance_type = T_instance; | ||||
| using my_instance_type = T_value; | using my_instance_type = T_value; | ||||
| @@ -46,7 +46,7 @@ namespace cppargs | |||||
| using predicate_type = decltype(predicate); | using predicate_type = decltype(predicate); | ||||
| using simple_predicate_option_type = simple_predicate_option<predicate_type>; | using simple_predicate_option_type = simple_predicate_option<predicate_type>; | ||||
| return std::make_unique<simple_predicate_option_type>( | return std::make_unique<simple_predicate_option_type>( | ||||
| option_meta::prepare_arguments<T_value>(meta), | |||||
| option_meta::prepare(meta, value), | |||||
| std::move(predicate)); | std::move(predicate)); | ||||
| } | } | ||||
| @@ -18,9 +18,9 @@ TEST(member_parser, simple_object) | |||||
| simple s; | simple s; | ||||
| parser p( | parser p( | ||||
| nullptr, | nullptr, | ||||
| parser::make_member_option<simple>({ 'i', "int" }, &simple::i), | |||||
| parser::make_member_option<simple>({ 's', "string" }, &simple::s), | |||||
| parser::make_member_option<simple>({ 'd', "double" }, &simple::d) | |||||
| parser::make_option<simple>({ 'i', "int" }, &simple::i), | |||||
| parser::make_option<simple>({ 's', "string" }, &simple::s), | |||||
| parser::make_option<simple>({ 'd', "double" }, &simple::d) | |||||
| ); | ); | ||||
| std::vector<const char*> args({ | std::vector<const char*> args({ | ||||
| @@ -55,12 +55,12 @@ TEST(member_parser, grouped_object) | |||||
| grouped g; | grouped g; | ||||
| parser p( | parser p( | ||||
| nullptr, | nullptr, | ||||
| parser::make_member_option<grouped>({ 'i', "int" }, &grouped::i), | |||||
| parser::make_member_option<grouped>({ 's', "string" }, &grouped::s), | |||||
| parser::make_member_option<grouped>({ 'd', "double" }, &grouped::d), | |||||
| parser::make_member_group<grouped> ({ }, &grouped::g1, | |||||
| parser::make_member_option<grouped::group1>({ 'l', "list" }, &grouped::group1::list), | |||||
| parser::make_member_option<grouped::group1>({ 'v', "vector" }, &grouped::group1::vec)) | |||||
| parser::make_option<grouped>({ 'i', "int" }, &grouped::i), | |||||
| parser::make_option<grouped>({ 's', "string" }, &grouped::s), | |||||
| parser::make_option<grouped>({ 'd', "double" }, &grouped::d), | |||||
| parser::make_group<grouped> ({ }, &grouped::g1, | |||||
| parser::make_option<grouped::group1>({ 'l', "list" }, &grouped::group1::list), | |||||
| parser::make_option<grouped::group1>({ 'v', "vector" }, &grouped::group1::vec)) | |||||
| ); | ); | ||||
| std::vector<const char*> args({ | std::vector<const char*> args({ | ||||
| @@ -31,7 +31,7 @@ TEST(misc, print_help) | |||||
| parser p( | parser p( | ||||
| nullptr, | nullptr, | ||||
| parser::make_member_option<config>( | |||||
| parser::make_option<config>( | |||||
| ::cppargs::option_meta() | ::cppargs::option_meta() | ||||
| .set_short_name ('c') | .set_short_name ('c') | ||||
| .set_long_name ("config") | .set_long_name ("config") | ||||
| @@ -40,47 +40,45 @@ TEST(misc, print_help) | |||||
| .set_mandatory (true), | .set_mandatory (true), | ||||
| &config::config), | &config::config), | ||||
| // parser::make_group<std::string>({ }), | |||||
| /* database */ | /* database */ | ||||
| parser::make_member_group<config>( | |||||
| parser::make_group<config>( | |||||
| ::cppargs::group_meta() | ::cppargs::group_meta() | ||||
| .set_name("Database") | .set_name("Database") | ||||
| .set_description("The following parameters are database related."), | .set_description("The following parameters are database related."), | ||||
| &config::database, | &config::database, | ||||
| parser::make_member_option<struct config::database>( | |||||
| parser::make_option<struct config::database>( | |||||
| ::cppargs::option_meta() | ::cppargs::option_meta() | ||||
| .set_long_name ("database:host") | .set_long_name ("database:host") | ||||
| .set_description("Database host to connect to."), | .set_description("Database host to connect to."), | ||||
| &config::database::host), | &config::database::host), | ||||
| parser::make_member_option<struct config::database>( | |||||
| parser::make_option<struct config::database>( | |||||
| ::cppargs::option_meta() | ::cppargs::option_meta() | ||||
| .set_long_name ("database:port") | .set_long_name ("database:port") | ||||
| .set_description("Database port to connect to."), | .set_description("Database port to connect to."), | ||||
| &config::database::port), | &config::database::port), | ||||
| parser::make_member_option<struct config::database>( | |||||
| parser::make_option<struct config::database>( | |||||
| ::cppargs::option_meta() | ::cppargs::option_meta() | ||||
| .set_long_name ("database:password") | .set_long_name ("database:password") | ||||
| .set_description("Password to use for authenticatiom"), | .set_description("Password to use for authenticatiom"), | ||||
| &config::database::password)), | &config::database::password)), | ||||
| /* logging */ | /* logging */ | ||||
| parser::make_member_group<config>( | |||||
| parser::make_group<config>( | |||||
| ::cppargs::group_meta() | ::cppargs::group_meta() | ||||
| .set_name("Logging"), | .set_name("Logging"), | ||||
| &config::logging, | &config::logging, | ||||
| parser::make_member_option<struct config::logging>( | |||||
| parser::make_option<struct config::logging>( | |||||
| ::cppargs::option_meta() | ::cppargs::option_meta() | ||||
| .set_long_name ("logging:file") | .set_long_name ("logging:file") | ||||
| .set_arguments (::cppargs::enwrap_type("filename", false)) | .set_arguments (::cppargs::enwrap_type("filename", false)) | ||||
| .set_description("File to write log output to."), | .set_description("File to write log output to."), | ||||
| &config::logging::file), | &config::logging::file), | ||||
| parser::make_member_option<struct config::logging>( | |||||
| parser::make_option<struct config::logging>( | |||||
| ::cppargs::option_meta() | ::cppargs::option_meta() | ||||
| .set_long_name ("logging:level") | .set_long_name ("logging:level") | ||||
| .set_description("Log Level."), | .set_description("Log Level."), | ||||
| &config::logging::level), | &config::logging::level), | ||||
| parser::make_member_option<struct config::logging>( | |||||
| parser::make_option<struct config::logging>( | |||||
| ::cppargs::option_meta() | ::cppargs::option_meta() | ||||
| .set_long_name ("logging:name") | .set_long_name ("logging:name") | ||||
| .set_description("Default name of the logger."), | .set_description("Default name of the logger."), | ||||
| @@ -88,6 +86,5 @@ TEST(misc, print_help) | |||||
| std::ostringstream ss; | std::ostringstream ss; | ||||
| p.print_help(ss); | p.print_help(ss); | ||||
| std::cout << ss.str(); | |||||
| EXPECT_FALSE(ss.str().empty()); | |||||
| } | } | ||||