diff --git a/include/parser/argument_parser.hpp b/include/parser/argument_parser.hpp index ca60c74..f1abab0 100644 --- a/include/parser/argument_parser.hpp +++ b/include/parser/argument_parser.hpp @@ -1,4 +1,6 @@ #pragma once +#include +#include #ifndef ARGUMENT_PARSER_HPP #define ARGUMENT_PARSER_HPP @@ -14,6 +16,7 @@ #include #include #include +#include namespace argument_parser { class action_base { @@ -129,6 +132,17 @@ namespace argument_parser { std::string help_text; }; + namespace helpers { + template + static parametered_action make_parametered_action(std::function const& function) { + return parametered_action(function); + } + + static non_parametered_action make_non_parametered_action(std::function const& function) { + return non_parametered_action(function); + } + } + class base_parser { public: template @@ -140,6 +154,22 @@ namespace argument_parser { base_add_argument(short_arg, long_arg, help_text, action, required); } + void add_argument(std::string const& short_arg, std::string const& long_arg, std::string const& help_text, bool required) { + base_add_argument(short_arg, long_arg, help_text, required); + } + + template + void add_argument(std::string const& short_arg, std::string const& long_arg, std::string const& help_text, bool required) { + base_add_argument(short_arg, long_arg, help_text, required); + } + + template + std::optional get_optional(std::string const& arg) { + auto id = find_argument_id(arg); + if (id.has_value()) return std::any_cast(stored_arguments[id.value()]); + return std::nullopt; + } + std::string build_help_text(std::initializer_list convention_types) { std::stringstream ss; ss << "Usage: " << program_name << " [OPTIONS]...\n"; @@ -164,6 +194,15 @@ namespace argument_parser { } throw std::runtime_error("Unknown argument: " + arg.second); } + + std::optional find_argument_id(std::string const& arg) { + auto long_pos = long_arguments.find(arg); + auto short_post = short_arguments.find(arg); + + if (long_pos != long_arguments.end()) return long_pos->second; + if (short_post != short_arguments.end()) return short_post->second; + return std::nullopt; + } void handle_arguments(std::initializer_list convention_types) { for (auto it = parsed_arguments.begin(); it != parsed_arguments.end(); ++it) { @@ -217,24 +256,50 @@ namespace argument_parser { std::vector parsed_arguments; private: - template - void base_add_argument(std::string const& short_arg, std::string const& long_arg, std::string const& help_text, ActionType const& action, bool required) { + void assert_argument_not_exist(std::string const& short_arg, std::string const& long_arg) { if (short_arguments.count(short_arg) || long_arguments.count(long_arg)) { throw std::runtime_error("The key already exists!"); } + } - int id = id_counter.fetch_add(1); - - argument arg(id, short_arg + "|" + long_arg, action); - arg.set_required(required); + void set_argument_status(bool is_required, std::string const& help_text, argument& arg) { + arg.set_required(is_required); arg.set_help_text(help_text); - + } + + void place_argument(int id, argument const& arg, std::string const& short_arg, std::string const& long_arg) { argument_map[id] = arg; short_arguments[short_arg] = id; reverse_short_arguments[id] = short_arg; long_arguments[long_arg] = id; reverse_long_arguments[id] = long_arg; } + + template + void base_add_argument(std::string const& short_arg, std::string const& long_arg, std::string const& help_text, ActionType const& action, bool required) { + assert_argument_not_exist(short_arg, long_arg); + int id = id_counter.fetch_add(1); + argument arg(id, short_arg + "|" + long_arg, action); + set_argument_status(required, help_text, arg); + place_argument(id, arg, short_arg, long_arg); + } + + template + void base_add_argument(std::string const& short_arg, std::string const& long_arg, std::string const& help_text, bool required) { + assert_argument_not_exist(short_arg, long_arg); + int id = id_counter.fetch_add(1); + if constexpr (std::is_same_v) { + auto action = helpers::make_non_parametered_action([id, this] { stored_arguments[id] = std::any{ true }; }); + argument arg(id, short_arg + "|" + long_arg, action); + set_argument_status(required, help_text, arg); + place_argument(id, arg, short_arg, long_arg); + } else { + auto action = helpers::make_parametered_action([id, this](StoreType const& value) { stored_arguments[id] = std::any{ value }; }); + argument arg(id, short_arg + "|" + long_arg, action); + set_argument_status(required, help_text, arg); + place_argument(id, arg, short_arg, long_arg); + } + } void check_for_required_arguments(std::initializer_list convention_types) { std::vector> required_args; @@ -259,6 +324,7 @@ namespace argument_parser { inline static std::atomic_int id_counter = 0; + std::unordered_map stored_arguments; std::unordered_map argument_map; std::unordered_map short_arguments; std::unordered_map reverse_short_arguments; @@ -271,16 +337,7 @@ namespace argument_parser { friend class fake_parser; }; - namespace helpers { - template - static parametered_action make_parametered_action(std::function const& function) { - return parametered_action(function); - } - - static non_parametered_action make_non_parametered_action(std::function const& function) { - return non_parametered_action(function); - } - } + } #endif // ARGUMENT_PARSER_HPP \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index d6582b9..b9e2b90 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -118,7 +118,16 @@ int main() { parser.display_help(conventions); }), false); + parser.add_argument("t", "test_store", "Test store", false); + parser.handle_arguments(conventions); + auto store = parser.get_optional("test_store"); + if (store.has_value()) { + std::cout << "Stored value: " << store.value() << std::endl; + } else { + std::cout << "No stored value." << std::endl; + } + return 0; } \ No newline at end of file