From f8f5b4eafc2c83880a89b62b6ef6a25ae7e59f4a Mon Sep 17 00:00:00 2001 From: Cameron Reed Date: Mon, 8 Jul 2024 14:21:09 -0600 Subject: [PATCH] v2 --- Inc/argparser.h | 213 ++++++++++++------- Makefile | 35 ++-- Src/argparser.cpp | 525 ++++++++++++++++++++++++++-------------------- test.cpp | 53 ++--- 4 files changed, 476 insertions(+), 350 deletions(-) diff --git a/Inc/argparser.h b/Inc/argparser.h index 499dc2d..a445450 100644 --- a/Inc/argparser.h +++ b/Inc/argparser.h @@ -2,88 +2,161 @@ #include #include -namespace Cam -{ namespace Arguments { enum ERROR { NO_ERROR = 0, - ERROR_UNKNOWN_OPTION, - ERROR_INCORRECT_TYPE, - ERROR_MISSING_ARGUMENT, + ERROR_UNKNOWN_ARGUMENT, + ERROR_UNKNOWN_POSITIONAL_ARGUMENT, + ERROR_MISSING_VALUE, ERROR_MISSING_POSITIONAL_ARGUMENT, - SPECIAL_CASE_HELP -}; - -enum OPTTYPE { - FLAG = 0, - STRING, - INT -}; - -class Option -{ -public: - Option(const char* name, const char* description, OPTTYPE type); - Option(const char* name, const char short_name, const char* description, OPTTYPE type); - Option(const char short_name, const char* description, OPTTYPE type); - bool found(); - void* data; -private: - const char* m_name; - const char m_short_name; - const char* m_description; - OPTTYPE m_type; - bool m_found; - - friend class Parser; -}; - -class PositionalArgument -{ -public: - PositionalArgument(const char* name, bool required, OPTTYPE type = STRING); - bool found(); - void* data; -private: - const char* m_name; - OPTTYPE m_type; - bool m_req; - bool m_found; - - friend class Parser; + ERROR_INVALID_INT, + SPECIAL_CASE_HELP, }; class Parser { public: - Parser(const char* program_name); - void set_description(const char* description); - void add_option(Option* opt); - void add_positional_argument(PositionalArgument* arg); - ERROR parse(int argc, char** argv); + Parser(int argc, char** argv); + + bool hasNext(); + void next(); + const char* value(); + private: - ERROR print_help_message(); - ERROR handle_long_option(const char* option, const char* next_value); - ERROR handle_short_option(const char option, const char* next_value); - ERROR handle_positional_argument(const char* arg); - ERROR get_option_data(Option* opt, const char* option_name, const char* data_str); - ERROR get_option_data(Option* opt, const char option_name, const char* data_str); - ERROR unknown_option(const char* option); - ERROR unknown_option(const char option); - ERROR incorrect_type(const char* option, const char* got); - ERROR missing_argument(const char* option); - ERROR missing_argument(const char option); - ERROR missing_positional_argument(const char* arg); -private: - const char* m_program_name; - const char* m_description; - uint16_t m_opt_index; - uint16_t m_pos_index; - std::vector m_options; - std::vector m_positional_args; + int m_ArgCount; + char** m_ArgValues; + + int m_Index; }; + +class Argument +{ +public: + Argument(const char* name); + Argument(char name); + + Argument& description(const char* desc); + + Argument& alias(const char* alias); + Argument& alias(char alias); + + bool matches(const char*); + bool matchesShort(char); + + virtual ERROR noValue() = 0; + virtual ERROR parseValue(Parser& state) = 0; + +public: + bool found; + +protected: + const char* m_Name; + char m_ShortName; + + const char* m_Description; + +private: + std::vector m_Aliases; + std::vector m_ShortAliases; +}; + + +class Int: public Argument +{ +public: + Int(const char* name, int64_t defaultValue); + Int(char name, int64_t defaultValue); + + ERROR noValue() override; + ERROR parseValue(Parser& state) override; + +public: + int64_t value; + +private: + void printMissingValueError(); +}; + +class String: public Argument +{ +public: + String(const char* name, const char* defaultValue); + String(char name, const char* defaultValue); + + ERROR noValue() override; + ERROR parseValue(Parser& state) override; + +public: + const char* value; + +private: + void printMissingValueError(); +}; + +class Bool: public Argument +{ +public: + Bool(const char* name); + Bool(char name); + + ERROR noValue() override; + ERROR parseValue(Parser& state) override; +}; + + +class PositionalArgument +{ +public: + PositionalArgument(bool required); + + void description(const char* desc); + + virtual ERROR parseValue(Parser& state) = 0; + +public: + bool found; + bool required; + +private: + const char* m_Description; +}; + + +class PositionalInt: public PositionalArgument +{ +public: + PositionalInt(int64_t defaultValue, bool required); + + ERROR parseValue(Parser& state) override; + +public: + int64_t value; +}; + +class PositionalString: public PositionalArgument +{ +public: + PositionalString(const char* defaultValue, bool required); + + ERROR parseValue(Parser& state) override; + +public: + const char* value; +}; + + +ERROR parse(int argc, char** argv); +ERROR findMatch(Parser& parser, const char* name); +ERROR findShortMatch(Parser& parser, char name, bool last); +ERROR matchPositional(Parser& parser); + +void printInvalidIntError(const char* value); +void printUnknownArgError(const char* argument); +void printUnknownArgError(char argument); +void printUnknownPosArgError(const char* value); + } // namespace Arguments -} // namespace Cam + diff --git a/Makefile b/Makefile index 132d43e..ff73497 100644 --- a/Makefile +++ b/Makefile @@ -2,9 +2,10 @@ TYPE = STATIC SHARED_TYPE = SHARED STATIC_TYPE = STATIC -BUILD_DIR = bin SOURCE_DIR = Src HEADER_DIR = Inc +BUILD_DIR = bin + HEADER_INSTALL_DIR = /usr/local/include INSTALL_DIR = /usr/local/lib @@ -17,8 +18,7 @@ endif OPT = -O2 -INCS = \ --IInc +INCS = -IInc C_SOURCES = $(wildcard $(SOURCE_DIR)/*.c) CXX_SOURCES = $(wildcard $(SOURCE_DIR)/*.cpp) @@ -38,25 +38,20 @@ endif HEADERS = $(wildcard $(HEADER_DIR)/*.h) -CP = cp -MKDIR = mkdir -p ARFLAGS = rvc -SED = sed -i -e -CHMOD = chmod -LDCONFIG = ldconfig all: $(BUILD_DIR)/$(LIB_FILE_NAME) ifneq ($(TYPE), $(SHARED_TYPE)) shared: clean - @$(SED) "s/^TYPE = .*$$/TYPE = $(SHARED_TYPE)/" Makefile + @sed -i -e "s/^TYPE = .*$$/TYPE = $(SHARED_TYPE)/" Makefile .PHONY: shared endif ifneq ($(TYPE), $(STATIC_TYPE)) static: clean - @$(SED) "s/^TYPE = .*$$/TYPE = $(STATIC_TYPE)/" Makefile + @sed -i -e "s/^TYPE = .*$$/TYPE = $(STATIC_TYPE)/" Makefile .PHONY: static endif @@ -75,29 +70,29 @@ $(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.cpp | $(BUILD_DIR) $(CXX) -c $< $(CXXFLAGS) -o $@ $(BUILD_DIR): - $(MKDIR) $@ + mkdir -p $@ -test: all - $(CXX) test.cpp $(CXXFLAGS) -l$(LIB_NAME) -L$(BUILD_DIR) $(TESTFLAGS) -o $(BUILD_DIR)/test +test: test.cpp all | $(BUILD_DIR) + $(CXX) $< $(CXXFLAGS) -l$(LIB_NAME) -L$(BUILD_DIR) $(TESTFLAGS) -o $(BUILD_DIR)/test -$(BUILD_DIR)/test -test_installed: - $(CXX) test.cpp $(CXXFLAGS) -l$(LIB_NAME) -o $(BUILD_DIR)/test +test_installed: test.cpp | $(BUILD_DIR) + $(CXX) $< $(CXXFLAGS) -l$(LIB_NAME) -o $(BUILD_DIR)/test -$(BUILD_DIR)/test install: all - $(CP) $(BUILD_DIR)/$(LIB_FILE_NAME) $(INSTALL_DIR) - $(CP) $(HEADERS) $(HEADER_INSTALL_DIR) - @$(CHMOD) 0755 $(INSTALL_DIR)/$(LIB_FILE_NAME) + cp $(BUILD_DIR)/$(LIB_FILE_NAME) $(INSTALL_DIR) + cp $(HEADERS) $(HEADER_INSTALL_DIR) + @chmod 0755 $(INSTALL_DIR)/$(LIB_FILE_NAME) ifeq ($(TYPE), $(SHARED_TYPE)) - @$(LDCONFIG) + @ldconfig endif uninstall: $(RM) $(INSTALL_DIR)/$(LIB_FILE_NAME) $(RM) $(addprefix $(HEADER_INSTALL_DIR)/, $(notdir $(HEADERS))) ifeq ($(TYPE), $(SHARED_TYPE)) - @$(LDCONFIG) + @ldconfig endif clean: diff --git a/Src/argparser.cpp b/Src/argparser.cpp index e7d99e8..cf77301 100644 --- a/Src/argparser.cpp +++ b/Src/argparser.cpp @@ -1,315 +1,384 @@ -#include "argparser.h" -#include -#include #include +#include +#include +#include +#include +#include +#include -int stringToInt(const char* input) -{ - int value = 0; - for (int i = 0; input[i] != 0; i++) - { - if (input[i] < '0' || input[i] > '9') - return -1; - value = (value * 10) + input[i] - '0'; - } +#include "argparser.h" - return value; -} -namespace Cam -{ namespace Arguments { +static std::vector arguments; +static std::vector positionalArguments; +static size_t posArgIdx = 0; -Option::Option(const char* name, const char* description, OPTTYPE type) - : m_name(name), m_short_name(0), m_description(description), m_type(type), m_found(false) {} -Option::Option(const char* name, const char short_name, const char* description, OPTTYPE type) - : m_name(name), m_short_name(short_name), m_description(description), m_type(type), m_found(false) {} +Parser::Parser(int argc, char** argv) + : m_ArgCount(argc), m_ArgValues(argv), m_Index(0) { }; -Option::Option(const char short_name, const char* description, OPTTYPE type) - : m_name(nullptr), m_short_name(short_name), m_description(description), m_type(type), m_found(false) {} - -bool Option::found() +const char* Parser::value() { - return m_found; + if (m_Index >= m_ArgCount) { + return nullptr; + } else { + return m_ArgValues[m_Index]; + } } -PositionalArgument::PositionalArgument(const char* name, bool required, OPTTYPE type /* = STRING */) - : m_name(name), m_type(type), m_req(required), m_found(false) +bool Parser::hasNext() { - if (type == FLAG) { - std::cout << "Warning OPTTYPE 'FLAG' is not meant to be used with positional arguments" << std::endl; - std::cout << "Assuming type 'STRING' instead" << std::endl; - m_type = STRING; - } + return m_Index + 1 < m_ArgCount; } -bool PositionalArgument::found() +void Parser::next() { - return m_found; + m_Index++; } -Parser::Parser(const char* program_name) - : m_program_name(program_name), m_description(nullptr), m_options(), m_positional_args() {} -void Parser::set_description(const char* description) +Argument::Argument(const char* name) + : found(false), m_Name(name), m_ShortName(0) { - m_description = description; + arguments.push_back(this); +}; + +Argument::Argument(char name) + : m_Name(nullptr), m_ShortName(name) +{ + arguments.push_back(this); +}; + +Argument& Argument::description(const char* desc) +{ + m_Description = desc; + return *this; } -void Parser::add_option(Option* opt) +Argument& Argument::alias(const char* alias) { - m_options.push_back(opt); + m_Aliases.push_back(alias); + return *this; } -void Parser::add_positional_argument(PositionalArgument* arg) +Argument& Argument::alias(char alias) { - m_positional_args.push_back(arg); + m_ShortAliases.push_back(alias); + return *this; } -ERROR Parser::parse(int argc, char** argv) +bool Argument::matches(const char* arg) { - m_pos_index = 0; - for (m_opt_index = 1; m_opt_index < argc; m_opt_index++) - { - if (argv[m_opt_index][0] == '-' && argv[m_opt_index][1] == '-') { + if (m_Name != nullptr) { + if (std::strlen(arg) == std::strlen(m_Name)) { + if (std::strcmp(arg, m_Name) == 0) { + return true; + } + } + } - ERROR ret = handle_long_option(argv[m_opt_index] + 2, m_opt_index + 1 < argc ? argv[m_opt_index + 1] : nullptr); - if (ret) - return ret; + for (const char* alias: m_Aliases) { + if (std::strlen(arg) == std::strlen(alias)) { + if (std::strcmp(arg, alias) == 0) { + return true; + } + } + } - } else if (argv[m_opt_index][0] == '-' && argv[m_opt_index][1] != '-') { - - for (uint8_t i = 1; argv[m_opt_index][i] != 0; i++) { - bool last = argv[m_opt_index][i + 1] == 0; - ERROR ret = handle_short_option(argv[m_opt_index][i], m_opt_index + 1 < argc && last ? argv[m_opt_index + 1] : nullptr); - if (ret) - return ret; - if (last) - break; - } - - } else { - - ERROR ret = handle_positional_argument(argv[m_opt_index]); - if (ret) - return ret; - - } - } - - if (m_pos_index < m_positional_args.size()) { - for (; m_pos_index < m_positional_args.size(); m_pos_index++) { - if (m_positional_args[m_pos_index]->m_req) - return missing_positional_argument(m_positional_args[m_pos_index]->m_name); - } - } - - return NO_ERROR; + return false; } -ERROR Parser::handle_long_option(const char* option, const char* next_value) +bool Argument::matchesShort(char arg) { - Option* matched_option = nullptr; + if (arg == 0) { + return false; + } - for (Option* opt: m_options) { - if (opt->m_name == nullptr) - continue; - if (strcmp(opt->m_name, option) == 0) { - matched_option = opt; - break; - } - } + if (arg == m_ShortName) { + return true; + } - if (matched_option == nullptr) { + for (char alias: m_ShortAliases) { + if (arg == alias) { + return true; + } + } - if (strcmp("help", option) == 0) - return print_help_message(); - - return unknown_option(option); - - } - - - matched_option->m_found = true; - return get_option_data(matched_option, option, next_value); + return false; } -ERROR Parser::handle_short_option(const char option, const char* next_value) + +Int::Int(const char* name, int64_t defaultValue) + : Argument(name), value(defaultValue) { } + +Int::Int(char name, int64_t defaultValue) + : Argument(name), value(defaultValue) { } + +ERROR Int::noValue() { - Option* matched_option = nullptr; - - for (Option* opt: m_options) { - if (opt->m_short_name == option) { - matched_option = opt; - break; - } - } - - if (matched_option == nullptr) { - - if ('h' == option) - return print_help_message(); - - return unknown_option(option); - - } - - - matched_option->m_found = true; - return get_option_data(matched_option, option, next_value); + printMissingValueError(); + return ERROR_MISSING_VALUE; } -ERROR Parser::handle_positional_argument(const char* arg) +ERROR Int::parseValue(Parser& state) { - if (m_pos_index >= m_positional_args.size()) - return unknown_option(arg); + if (!state.hasNext()) { + printMissingValueError(); + return ERROR_MISSING_VALUE; + } - PositionalArgument* pos_arg = m_positional_args[m_pos_index]; + state.next(); - if (pos_arg->m_type == INT) { - int* val = new int; - if ((*val = stringToInt(arg)) == -1) - return incorrect_type(pos_arg->m_name, arg); + const char* val = state.value(); + if (*val == '-' || *val == '+') { + val++; + } - pos_arg->data = val; - } else { - pos_arg->data = (void*) arg; - } + while (*val != '\0') { + if (*val < '0' || *val > '9') { + printInvalidIntError(state.value()); + return ERROR_INVALID_INT; + } + val++; + } - pos_arg->m_found = true; - m_pos_index++; - return NO_ERROR; + found = true; + value = std::atoi(state.value()); + + return NO_ERROR; } -ERROR Parser::get_option_data(Option* opt, const char* option_name, const char* data_str) +void Int::printMissingValueError() { - if (opt->m_type == FLAG) - return NO_ERROR; - - if (data_str == nullptr || data_str[0] == '-') - return missing_argument(option_name); - - if (opt->m_type == INT) { - int* val = new int; - if ((*val = stringToInt(data_str)) == -1) - return incorrect_type(opt->m_name, data_str); - opt->data = val; - } else { - opt->data = (void*) data_str; - } - - m_opt_index++; - return NO_ERROR; + std::cerr << "Missing integer value for argument "; + if (m_Name != nullptr) { + std::cerr << "--" << m_Name << std::endl; + } else { + std::cerr << "-" << m_ShortName << std::endl; + } } -ERROR Parser::get_option_data(Option* opt, const char option_name, const char* data_str) + +String::String(const char* name, const char* defaultValue) + : Argument(name), value(defaultValue) { } + +String::String(char name, const char* defaultValue) + : Argument(name), value(defaultValue) { } + +ERROR String::noValue() { - if (opt->m_type == FLAG) - return NO_ERROR; - - if (data_str == nullptr || data_str[0] == '-') - return missing_argument(option_name); - - if (opt->m_type == INT) { - int* val = new int; - if ((*val = stringToInt(data_str)) == -1) - return incorrect_type(opt->m_name, data_str); - opt->data = val; - } else { - opt->data = (void*) data_str; - } - - m_opt_index++; - return NO_ERROR; + printMissingValueError(); + return ERROR_MISSING_VALUE; } -ERROR Parser::unknown_option(const char* option) +ERROR String::parseValue(Parser& state) { - std::cout << m_program_name << ": invalid option '" << option << '\'' << std::endl << std::endl; - std::cout << "See " << m_program_name << " --help" << std::endl; + if (!state.hasNext()) { + printMissingValueError(); + return ERROR_MISSING_VALUE; + } - return ERROR_UNKNOWN_OPTION; + found = true; + + state.next(); + value = state.value(); + + return NO_ERROR; } -ERROR Parser::unknown_option(const char option) +void String::printMissingValueError() { - std::cout << m_program_name << ": invalid option: " << option << std::endl << std::endl; - std::cout << "See " << m_program_name << " --help" << std::endl; - - return ERROR_UNKNOWN_OPTION; + std::cerr << "Missing value for argument "; + if (m_Name != nullptr) { + std::cerr << "--" << m_Name << std::endl; + } else { + std::cerr << "-" << m_ShortName << std::endl; + } } -ERROR Parser::incorrect_type(const char* option, const char* got) -{ - std::cout << m_program_name << ": argument '" << option << "' expects an integer as an argument, got " << got << " instead" << std::endl; - return ERROR_INCORRECT_TYPE; +Bool::Bool(const char* name) + : Argument(name) { } + +Bool::Bool(char name) + : Argument(name) { } + +ERROR Bool::noValue() +{ + found = true; + + return NO_ERROR; } -ERROR Parser::missing_argument(const char* option) +ERROR Bool::parseValue(Parser& state) { - std::cout << m_program_name << ": Missing argument for option '" << option << '\'' << std::endl; + (void) state; - return ERROR_MISSING_ARGUMENT; + found = true; + + return NO_ERROR; } -ERROR Parser::missing_argument(const char option) -{ - std::cout << m_program_name << ": Missing argument for option '" << option << '\'' << std::endl; - return ERROR_MISSING_ARGUMENT; +PositionalArgument::PositionalArgument(bool required) + : found(false), required(required), m_Description(nullptr) +{ + if (required) { + for (PositionalArgument* arg: positionalArguments) { + if (!arg->required) { + std::cerr << "All required positional arguments must be registered before any optional positional arguments" << std::endl; + exit(-1); + } + } + } + + positionalArguments.push_back(this); } -ERROR Parser::missing_positional_argument(const char* arg) +void PositionalArgument::description(const char* desc) { - std::cout << m_program_name << ": Missing required positional argument '" << arg << "'" << std::endl << std::endl; - std::cout << "See " << m_program_name << " --help" << std::endl; - - return ERROR_MISSING_POSITIONAL_ARGUMENT; + m_Description = desc; } -ERROR Parser::print_help_message() + +PositionalInt::PositionalInt(int64_t defaultValue, bool required) + : PositionalArgument(required), value(defaultValue) { } + +ERROR PositionalInt::parseValue(Parser& state) { - std::cout << "Usage: " << m_program_name << (m_options.size() > 0 ? " [OPTIONS]" : ""); - for (PositionalArgument* arg: m_positional_args) - { - std::cout << " " << arg->m_name; - } - std::cout << std::endl; + const char* val = state.value(); + if (*val == '-' || *val == '+') { + val++; + } + + while (*val != '\0') { + if (*val < '0' || *val > '9') { + printInvalidIntError(state.value()); + return ERROR_INVALID_INT; + } + val++; + } + + found = true; + value = std::atoi(state.value()); + + return NO_ERROR; +} - if (m_options.size() > 0) - std::cout << std::endl << std::endl << "Options:" << std::endl; - for (Option* opt: m_options) - { - std::cout << " "; - if (opt->m_short_name != 0) - std::cout << '-' << opt->m_short_name; +PositionalString::PositionalString(const char* defaultValue, bool required) + : PositionalArgument(required), value(defaultValue) { } - if (opt->m_short_name != 0 && opt->m_name != nullptr) - std::cout << ", "; +ERROR PositionalString::parseValue(Parser& state) +{ + found = true; + value = state.value(); - if (opt->m_name != nullptr) - std::cout << "--" << opt->m_name; + return NO_ERROR; +} - if (opt->m_name != nullptr) { - for (uint8_t i = 0; i < 20 - strlen(opt->m_name) - ((opt->m_short_name != 0) * 4); i++) - std::cout << ' '; - } else { - for (uint8_t i = 0; i < 24 - ((opt->m_short_name != 0) * 4); i++) - std::cout << ' '; - } - std::cout << opt->m_description << std::endl; - } +ERROR parse(int argc, char** argv) +{ + Parser parser(argc, argv); - if (m_description) - std::cout << std::endl << std::endl << m_description << std::endl; + while (parser.hasNext()) { + parser.next(); // This is OK on the first iteration because it skips the executable name - return SPECIAL_CASE_HELP; + const char* value = parser.value(); + bool firstDash = value[0] == '-'; + bool secondDash = value[1] == '-'; + + if (firstDash && secondDash) { + ERROR err = findMatch(parser, value + 2); + if (err != NO_ERROR) { + return err; + } + } else if (firstDash) { + size_t len = std::strlen(value); + for (size_t i = 1; i < len; i++) { + ERROR err = findShortMatch(parser, value[i], i == len - 1); + if (err != NO_ERROR) { + return err; + } + } + } else { + ERROR err = matchPositional(parser); + if (err != NO_ERROR) { + return err; + } + } + } + + if (posArgIdx < positionalArguments.size()) { + if (positionalArguments[posArgIdx]->required) { + std::cerr << "Missing required positional argument" << std::endl; + return ERROR_MISSING_POSITIONAL_ARGUMENT; + } + } + + return NO_ERROR; +} + +ERROR findMatch(Parser& parser, const char* name) +{ + for (Argument* arg: arguments) { + if (arg->matches(name)) { + return arg->parseValue(parser); + } + } + + printUnknownArgError(name); + return ERROR_UNKNOWN_ARGUMENT; +} + +ERROR findShortMatch(Parser &parser, char name, bool last) +{ + for (Argument* arg: arguments) { + if (arg->matchesShort(name)) { + if (last) { + return arg->parseValue(parser); + } + + return arg->noValue(); + } + } + + printUnknownArgError(name); + return ERROR_UNKNOWN_ARGUMENT; +} + +ERROR matchPositional(Parser &parser) +{ + if (posArgIdx >= positionalArguments.size()) { + printUnknownPosArgError(parser.value()); + return ERROR_UNKNOWN_POSITIONAL_ARGUMENT; + } + + return positionalArguments[posArgIdx++]->parseValue(parser); +} + +void printInvalidIntError(const char* value) +{ + std::cerr << value << " is not an integer" << std::endl; +} + +void printUnknownArgError(const char* argument) +{ + std::cerr << "Unknown argument --" << argument << std::endl; +} + +void printUnknownArgError(char argument) +{ + std::cerr << "Unknown argument -" << argument << std::endl; +} + +void printUnknownPosArgError(const char* value) +{ + std::cerr << "Extra positional argument " << value << std::endl; } } // namespace Arguments -} // namespace Cam + diff --git a/test.cpp b/test.cpp index 385dabb..7770b49 100644 --- a/test.cpp +++ b/test.cpp @@ -1,48 +1,37 @@ #include + #include "argparser.h" -using namespace Cam; -int main(int argc, char **argv) { - Arguments::Parser parser = Arguments::Parser("test"); +int main(int argc, char** argv) { + Arguments::String first('f', "none"); + first.description("First arg"); - parser.set_description("A test of argument parsing :)"); + Arguments::Int second("second", 0); + second.description("Second arg").alias('s'); - Arguments::Option first('f', "First arg", Arguments::STRING); - Arguments::Option second("second", 's', "Second arg", Arguments::INT); - Arguments::Option third("third", "Third arg", Arguments::FLAG); + Arguments::Bool third("third"); + third.description("Third arg").alias("abc").alias('t'); - Arguments::PositionalArgument name("name", true, Arguments::STRING); - Arguments::PositionalArgument age("age", false, Arguments::INT); + Arguments::PositionalString name("", true); + Arguments::PositionalInt age(0, false); - parser.add_option(&first); - parser.add_option(&second); - parser.add_option(&third); - - parser.add_positional_argument(&name); - parser.add_positional_argument(&age); - - if (parser.parse(argc, argv) != 0) { + if (Arguments::parse(argc, argv) != Arguments::NO_ERROR) { return 0; } std::cout << "Found:" << std::endl; - std::cout << "\tFirst: " << first.found() << std::endl; - std::cout << "\tSecond: " << second.found() << std::endl; - std::cout << "\tThird: " << third.found() << std::endl; - std::cout << "\tName: " << name.found() << std::endl; - std::cout << "\tAge: " << age.found() << std::endl; + std::cout << "\tFirst: " << first.found << std::endl; + std::cout << "\tSecond: " << second.found << std::endl; + std::cout << "\tThird: " << third.found << std::endl; + std::cout << "\tName: " << name.found << std::endl; + std::cout << "\tAge: " << age.found << std::endl; - if (first.found() || second.found() || name.found() || age.found()) - std::cout << std::endl << "Values:" << std::endl; - if (first.found()) - std::cout << "\tFirst: " << (char*) first.data << std::endl; - if (second.found()) - std::cout << "\tSecond: " << *((int*) second.data) << std::endl; - if (name.found()) - std::cout << "\tName: " << (char*) name.data << std::endl; - if (age.found()) - std::cout << "\tAge: " << *((int*) age.data) << std::endl; + std::cout << std::endl << "Values:" << std::endl; + std::cout << "\tFirst: " << first.value << std::endl; + std::cout << "\tSecond: " << second.value << std::endl; + std::cout << "\tName: " << name.value << std::endl; + std::cout << "\tAge: " << age.value << std::endl; return 0; }