| @@ -6,10 +6,6 @@ | |||
| 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 | |||
| { | |||
| 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 | |||
| { | |||
| template<typename T_instance, typename T_value, typename T_predicate> | |||
| template<typename T_instance, typename T_predicate> | |||
| struct member_predicate_option | |||
| : public member_option<T_instance> | |||
| { | |||
| public: | |||
| using instance_type = T_instance; | |||
| using value_type = T_value; | |||
| using predicate_type = T_predicate; | |||
| using base_type = member_option<instance_type>; | |||
| @@ -5,17 +5,17 @@ | |||
| namespace cppargs | |||
| { | |||
| template<typename T_instance, typename T_value, typename T_predicate> | |||
| template<typename T_instance, typename T_predicate> | |||
| 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, | |||
| T_args&&... args) | |||
| : base_type (p_meta) | |||
| , _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); } | |||
| } | |||
| @@ -22,11 +22,12 @@ namespace cppargs | |||
| inline option_meta& set_long_name (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_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); | |||
| 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 | |||
| #include <cpputils/misc/string.h> | |||
| #include <cppargs/misc/misc.inl> | |||
| #include "option.h" | |||
| @@ -7,6 +8,95 @@ | |||
| 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) | |||
| { | |||
| short_name = value; | |||
| @@ -31,9 +121,10 @@ namespace cppargs | |||
| 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; | |||
| } | |||
| @@ -44,13 +135,8 @@ namespace cppargs | |||
| } | |||
| 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) | |||
| : meta(p_meta) | |||
| @@ -13,6 +13,17 @@ namespace cppargs | |||
| using parser::parser; | |||
| 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. | |||
| * | |||
| @@ -22,7 +33,7 @@ namespace cppargs | |||
| * @return Created option. | |||
| */ | |||
| 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. | |||
| @@ -45,7 +56,7 @@ namespace cppargs | |||
| * @return Created group. | |||
| */ | |||
| 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 | |||
| { | |||
| 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> | |||
| 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."); | |||
| @@ -26,9 +35,9 @@ namespace cppargs | |||
| }; | |||
| 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>( | |||
| option_meta::prepare_arguments<T_value>(meta), | |||
| option_meta::prepare(meta, member), | |||
| std::move(predicate)); | |||
| } | |||
| @@ -47,7 +56,7 @@ namespace cppargs | |||
| } | |||
| 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 my_instance_type = T_value; | |||
| @@ -46,7 +46,7 @@ namespace cppargs | |||
| using predicate_type = decltype(predicate); | |||
| using simple_predicate_option_type = simple_predicate_option<predicate_type>; | |||
| return std::make_unique<simple_predicate_option_type>( | |||
| option_meta::prepare_arguments<T_value>(meta), | |||
| option_meta::prepare(meta, value), | |||
| std::move(predicate)); | |||
| } | |||
| @@ -18,9 +18,9 @@ TEST(member_parser, simple_object) | |||
| simple s; | |||
| parser p( | |||
| 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({ | |||
| @@ -55,12 +55,12 @@ TEST(member_parser, grouped_object) | |||
| grouped g; | |||
| parser p( | |||
| 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({ | |||
| @@ -31,7 +31,7 @@ TEST(misc, print_help) | |||
| parser p( | |||
| nullptr, | |||
| parser::make_member_option<config>( | |||
| parser::make_option<config>( | |||
| ::cppargs::option_meta() | |||
| .set_short_name ('c') | |||
| .set_long_name ("config") | |||
| @@ -40,47 +40,45 @@ TEST(misc, print_help) | |||
| .set_mandatory (true), | |||
| &config::config), | |||
| // parser::make_group<std::string>({ }), | |||
| /* database */ | |||
| parser::make_member_group<config>( | |||
| parser::make_group<config>( | |||
| ::cppargs::group_meta() | |||
| .set_name("Database") | |||
| .set_description("The following parameters are database related."), | |||
| &config::database, | |||
| parser::make_member_option<struct config::database>( | |||
| parser::make_option<struct config::database>( | |||
| ::cppargs::option_meta() | |||
| .set_long_name ("database:host") | |||
| .set_description("Database host to connect to."), | |||
| &config::database::host), | |||
| parser::make_member_option<struct config::database>( | |||
| parser::make_option<struct config::database>( | |||
| ::cppargs::option_meta() | |||
| .set_long_name ("database:port") | |||
| .set_description("Database port to connect to."), | |||
| &config::database::port), | |||
| parser::make_member_option<struct config::database>( | |||
| parser::make_option<struct config::database>( | |||
| ::cppargs::option_meta() | |||
| .set_long_name ("database:password") | |||
| .set_description("Password to use for authenticatiom"), | |||
| &config::database::password)), | |||
| /* logging */ | |||
| parser::make_member_group<config>( | |||
| parser::make_group<config>( | |||
| ::cppargs::group_meta() | |||
| .set_name("Logging"), | |||
| &config::logging, | |||
| parser::make_member_option<struct config::logging>( | |||
| parser::make_option<struct config::logging>( | |||
| ::cppargs::option_meta() | |||
| .set_long_name ("logging:file") | |||
| .set_arguments (::cppargs::enwrap_type("filename", false)) | |||
| .set_description("File to write log output to."), | |||
| &config::logging::file), | |||
| parser::make_member_option<struct config::logging>( | |||
| parser::make_option<struct config::logging>( | |||
| ::cppargs::option_meta() | |||
| .set_long_name ("logging:level") | |||
| .set_description("Log Level."), | |||
| &config::logging::level), | |||
| parser::make_member_option<struct config::logging>( | |||
| parser::make_option<struct config::logging>( | |||
| ::cppargs::option_meta() | |||
| .set_long_name ("logging:name") | |||
| .set_description("Default name of the logger."), | |||
| @@ -88,6 +86,5 @@ TEST(misc, print_help) | |||
| std::ostringstream ss; | |||
| p.print_help(ss); | |||
| std::cout << ss.str(); | |||
| EXPECT_FALSE(ss.str().empty()); | |||
| } | |||