diff --git a/include/argparse/parameter.h b/include/argparse/parameter.h index 95036c3..9f9e278 100644 --- a/include/argparse/parameter.h +++ b/include/argparse/parameter.h @@ -7,7 +7,7 @@ namespace argparse { enum parameter_type { - NONE, INTEGER, STRING, FLOAT + NONE, INTEGER, STRING, FLOAT, BOOL }; class parameter diff --git a/include/argparse/parameter_bool.h b/include/argparse/parameter_bool.h new file mode 100644 index 0000000..1dc13ba --- /dev/null +++ b/include/argparse/parameter_bool.h @@ -0,0 +1,18 @@ +#ifndef ARGPARSE_PARAMETER_BOOL_H +#define ARGPARSE_PARAMETER_BOOL_H + +#include "argparse/parameter.h" +#include + +namespace argparse { + class parameter_bool : public parameter { + public: + parameter_bool(std::string short_name, std::string name, std::string description); + void set(std::string value) override; + void get_value_to(void* p_value) override; + private: + bool value; + }; +} + +#endif // ARGPARSE_PARAMETER_BOOL_H diff --git a/include/argparse/parser.h b/include/argparse/parser.h index 56a1b15..356f618 100644 --- a/include/argparse/parser.h +++ b/include/argparse/parser.h @@ -1,12 +1,12 @@ -#ifndef ARGPARSE_PARSER_H -#define ARGPARSE_PARSER_H - -#include "argparse/defs.h" -#include "argparse/util.h" - -namespace argparse -{ - +#ifndef ARGPARSE_PARSER_H +#define ARGPARSE_PARSER_H + +#include "argparse/defs.h" +#include "argparse/util.h" + +namespace argparse +{ + class parser { public: @@ -14,6 +14,7 @@ namespace argparse virtual ~parser(); void add_parameter(std::string short_name, std::string name, std::string description, parameter_type type=NONE, bool required=false, std::string default_value=std::string("")); + void add_bool(std::string short_name, std::string name, std::string description, bool required = false, bool default_value = false); std::string get_help_message(); @@ -38,7 +39,7 @@ namespace argparse bool is_help_requested(); void print_help_and_exit(); - }; -} - + }; +} + #endif \ No newline at end of file diff --git a/include/argparse/util.h b/include/argparse/util.h index d57565a..97192d3 100644 --- a/include/argparse/util.h +++ b/include/argparse/util.h @@ -9,6 +9,7 @@ #include "argparse/parameter_integer.h" #include "argparse/parameter_string.h" #include "argparse/parameter_float.h" +#include "argparse/parameter_bool.h" namespace argparse { diff --git a/src/argparse/parameter_bool.cc b/src/argparse/parameter_bool.cc new file mode 100644 index 0000000..06ea31b --- /dev/null +++ b/src/argparse/parameter_bool.cc @@ -0,0 +1,23 @@ +#include "argparse/parameter_bool.h" +#include + +using namespace argparse; + +parameter_bool::parameter_bool(std::string short_name, std::string name, std::string description) + : parameter(short_name, name, description, BOOL), value(false) {} + +void parameter_bool::set(std::string value_str) { + std::string lower = value_str; + std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower); + if (lower == "1" || lower == "true" || lower == "yes" || lower == "on") { + value = true; + } else { + value = false; + } +} + +void parameter_bool::get_value_to(void* p_value) { + if (p_value) { + *static_cast(p_value) = value; + } +} diff --git a/src/argparse/parser.cc b/src/argparse/parser.cc index 28195de..25f1767 100644 --- a/src/argparse/parser.cc +++ b/src/argparse/parser.cc @@ -2,70 +2,86 @@ #include #include -using namespace argparse; - +using namespace argparse; + parser::parser() { auto_help_enabled = true; // Enable auto-help by default -} - -parser::~parser() -{ - // Delete all parameters - for (auto p_parameter : this->parameters) - { - delete p_parameter.second; - } -} - -void argparse::parser::add_parameter(std::string short_name, std::string name, std::string description, parameter_type type, bool required, std::string default_value) -{ - parameter* p_parameter = nullptr; - p_parameter = util::create_parameter(short_name, name, description, type); - if (p_parameter != nullptr) - { - if (type != NONE) - p_parameter->set(default_value); - p_parameter->set_required(required); - std::string key = short_name + '\n' + name; - parameters[key] = p_parameter; - if (short_name != "") - { - short_name_query[short_name] = key; - } - if (name != "") - { - name_query[name] = key; - } - } -} - -std::string argparse::parser::get_help_message() -{ - std::string help_message = ""; - help_message += std::string("Usage: ") + program_name + " [options]"; - for (auto p_parameter : this->parameters) - { - help_message += std::string("\n"); - if (p_parameter.second->get_short_name() != "") - { - help_message += std::string("-") + p_parameter.second->get_short_name(); - help_message += std::string(", "); - } - if (p_parameter.second->get_name() != "") - { - help_message += std::string("--") + p_parameter.second->get_name(); - } - help_message += std::string("\t") + p_parameter.second->get_description(); - if (p_parameter.second->get_short_name() == "" && p_parameter.second->get_name() == "") - { - help_message = "error: parameter has no name or short name"; - return help_message; - } - } - return help_message; -} - +} + +parser::~parser() +{ + // Delete all parameters + for (auto p_parameter : this->parameters) + { + delete p_parameter.second; + } +} + +void argparse::parser::add_parameter(std::string short_name, std::string name, std::string description, parameter_type type, bool required, std::string default_value) +{ + parameter* p_parameter = nullptr; + p_parameter = util::create_parameter(short_name, name, description, type); + if (p_parameter != nullptr) + { + if (type != NONE) + p_parameter->set(default_value); + p_parameter->set_required(required); + std::string key = short_name + '\n' + name; + parameters[key] = p_parameter; + if (short_name != "") + { + short_name_query[short_name] = key; + } + if (name != "") + { + name_query[name] = key; + } + } +} + +void parser::add_bool(std::string short_name, std::string name, std::string description, bool required, bool default_value) { + parameter* p_parameter = util::create_parameter(short_name, name, description, parameter_type::BOOL); + if (p_parameter != nullptr) { + p_parameter->set(default_value ? "true" : "false"); + p_parameter->set_required(required); + std::string key = short_name + "::" + name; + parameters[key] = p_parameter; + if (short_name != "") { + short_name_query[short_name] = key; + } + if (name != "") { + name_query[name] = key; + } + } +} + +std::string argparse::parser::get_help_message() +{ + std::string help_message = ""; + help_message += std::string("Usage: ") + program_name + " [options]"; + for (auto p_parameter : this->parameters) + { + help_message += std::string("\n"); + if (p_parameter.second->get_short_name() != "") + { + help_message += std::string("-") + p_parameter.second->get_short_name(); + help_message += std::string(", "); + } + if (p_parameter.second->get_name() != "") + { + help_message += std::string("--") + p_parameter.second->get_name(); + } + help_message += std::string("\t") + p_parameter.second->get_description(); + if (p_parameter.second->get_short_name() == "" && p_parameter.second->get_name() == "") + { + help_message = "error: parameter has no name or short name"; + return help_message; + } + } + return help_message; +} + bool parser::parse(std::vector args) { //get program name by removing path @@ -145,18 +161,18 @@ bool parser::parse(std::vector args) } return true; -} - -bool parser::parse(int argc, char** argv) -{ - std::vector args; - for (int i = 0; i < argc; i++) - { - args.push_back(argv[i]); - } - return parse(args); -} - +} + +bool parser::parse(int argc, char** argv) +{ + std::vector args; + for (int i = 0; i < argc; i++) + { + args.push_back(argv[i]); + } + return parse(args); +} + bool parser::get_parameter_value_to(std::string flag, void* value_buf) { std::string key = ""; diff --git a/src/argparse/util.cc b/src/argparse/util.cc index a722f65..98329c3 100644 --- a/src/argparse/util.cc +++ b/src/argparse/util.cc @@ -1,4 +1,5 @@ #include "argparse/util.h" +#include "argparse/parameter_bool.h" using namespace argparse; @@ -14,6 +15,8 @@ parameter* util::create_parameter(std::string short_name, std::string name, std: return new parameter_string(short_name, name, description); case parameter_type::FLOAT: return new parameter_float(short_name, name, description); + case parameter_type::BOOL: + return new parameter_bool(short_name, name, description); default: std::cerr << "Unknown parameter type: " << type << std::endl; return nullptr; diff --git a/tests/test_parameter_bool.cc b/tests/test_parameter_bool.cc new file mode 100644 index 0000000..5e1d855 --- /dev/null +++ b/tests/test_parameter_bool.cc @@ -0,0 +1,42 @@ +#include "argparse/parser.h" +#include +#include + +using namespace argparse; + +void test_bool_parameter() { + parser p; + p.add_bool("v", "verbose", "Enable verbose mode", false, false); + const char* argv[] = {"prog", "--verbose", "true"}; + bool result = p.parse(3, const_cast(argv)); + assert(result); + bool verbose = false; + bool found = p.get_parameter_value_to("verbose", &verbose); + assert(found); + assert(verbose == true); + + // Test false value + const char* argv2[] = {"prog", "--verbose", "false"}; + p.parse(3, const_cast(argv2)); + verbose = true; + found = p.get_parameter_value_to("verbose", &verbose); + assert(found); + assert(verbose == false); + + // Test default value + parser p2; + p2.add_bool("d", "debug", "Enable debug", false, true); + const char* argv3[] = {"prog"}; + p2.parse(1, const_cast(argv3)); + bool debug = false; + found = p2.get_parameter_value_to("debug", &debug); + assert(found); + assert(debug == true); + + std::cout << "Bool parameter tests passed!\n"; +} + +int main() { + test_bool_parameter(); + return 0; +}