This commit is contained in:
Cameron Reed 2024-07-08 14:21:09 -06:00
parent 9cc2348ded
commit f8f5b4eafc
4 changed files with 476 additions and 350 deletions

View File

@ -2,88 +2,161 @@
#include <vector>
#include <stdint.h>
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<Option*> m_options;
std::vector<PositionalArgument*> 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<const char*> m_Aliases;
std::vector<char> 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

View File

@ -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:

View File

@ -1,315 +1,384 @@
#include "argparser.h"
#include <stdint.h>
#include <string.h>
#include <iostream>
#include <cctype>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <vector>
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<Argument*> arguments;
static std::vector<PositionalArgument*> 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

View File

@ -1,48 +1,37 @@
#include <iostream>
#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;
}