2023-07-29 02:03:28 -04:00
|
|
|
/*
|
|
|
|
* Created by Brett on 28/07/23.
|
|
|
|
* Licensed under GNU General Public License V3.0
|
|
|
|
* See LICENSE file for license detail
|
|
|
|
*/
|
|
|
|
#include <blt/parse/argparse.h>
|
2023-07-29 14:04:46 -04:00
|
|
|
#include "blt/std/logging.h"
|
2023-07-29 02:03:28 -04:00
|
|
|
|
|
|
|
namespace blt::parser {
|
|
|
|
|
2023-07-29 13:38:19 -04:00
|
|
|
arg_vector::arg_vector(const std::vector<std::string>& args) {
|
2023-07-29 02:03:28 -04:00
|
|
|
for (auto& arg : args)
|
|
|
|
insertAndSort(arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
arg_vector::arg_vector(std::initializer_list<std::string> args) {
|
|
|
|
for (auto& arg : args)
|
|
|
|
insertAndSort(arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
arg_vector::arg_vector(const std::string& arg) {
|
|
|
|
insertAndSort(arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
arg_vector::arg_vector(const char* arg) {
|
|
|
|
insertAndSort(arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
arg_vector& arg_vector::operator=(const std::string& arg) {
|
|
|
|
insertAndSort(arg);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
arg_vector& arg_vector::operator=(const char* arg) {
|
|
|
|
insertAndSort(arg);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
arg_vector& arg_vector::operator=(std::initializer_list<std::string>& args) {
|
|
|
|
for (auto& arg : args)
|
|
|
|
insertAndSort(arg);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
arg_vector& arg_vector::operator=(std::vector<std::string>& args) {
|
|
|
|
for (auto& arg : args)
|
|
|
|
insertAndSort(arg);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void arg_vector::insertAndSort(const std::string& str) {
|
|
|
|
if (str.starts_with('-'))
|
|
|
|
flags.push_back(str);
|
|
|
|
else
|
|
|
|
names.push_back(str);
|
|
|
|
}
|
|
|
|
|
|
|
|
arg_nargs::arg_nargs(char c) {
|
|
|
|
decode(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
arg_nargs::arg_nargs(std::string s) {
|
|
|
|
decode(s[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
arg_nargs::arg_nargs(const char* s) {
|
|
|
|
decode(*s);
|
|
|
|
}
|
|
|
|
|
|
|
|
arg_nargs& arg_nargs::operator=(const std::string& s) {
|
|
|
|
decode(s[0]);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
arg_nargs& arg_nargs::operator=(char c) {
|
|
|
|
decode(c);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
arg_nargs& arg_nargs::operator=(int a) {
|
|
|
|
args = a;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
arg_nargs& arg_nargs::operator=(const char* s) {
|
|
|
|
decode(*s);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void arg_nargs::decode(char c) {
|
|
|
|
if (c == '?')
|
|
|
|
flags |= UNKNOWN;
|
|
|
|
if (c == '+')
|
|
|
|
flags |= ALL_REQUIRED;
|
|
|
|
if (c == '*')
|
|
|
|
flags |= ALL;
|
|
|
|
}
|
2023-07-29 13:38:19 -04:00
|
|
|
|
2023-07-30 14:04:59 -04:00
|
|
|
arg_tokenizer::arg_tokenizer(size_t argc, const char** argv) {
|
2023-07-29 13:38:19 -04:00
|
|
|
for (size_t i = 0; i < argc; i++)
|
|
|
|
args.emplace_back(argv[i]);
|
|
|
|
}
|
|
|
|
|
2023-07-29 14:04:46 -04:00
|
|
|
bool argparse::validateArgument(const arg_properties& args) {
|
|
|
|
return !args.a_flags.getFlags().empty() ^ !args.a_flags.getNames().empty();
|
|
|
|
}
|
2023-07-29 13:38:19 -04:00
|
|
|
|
2023-07-29 14:04:46 -04:00
|
|
|
void argparse::addArgument(const arg_properties& args) {
|
|
|
|
if (!validateArgument(args)) {
|
|
|
|
BLT_WARN("Argument contains both flags and positional names, this is not allowed!");
|
|
|
|
BLT_WARN("(Discarding argument)");
|
|
|
|
return;
|
|
|
|
}
|
2023-07-30 14:04:59 -04:00
|
|
|
// store one copy of the properties (arg properties could in theory be very large!)
|
|
|
|
auto pos = user_args.argStorage.size();
|
|
|
|
user_args.argStorage.push_back(args);
|
|
|
|
auto& arg = user_args.argStorage[pos];
|
|
|
|
// associate the arg properties per name and flag to allow for quick access when parsing
|
|
|
|
auto& names = args.a_flags.getNames();
|
|
|
|
for (const auto& name : names)
|
|
|
|
user_args.nameAssociations[name] = &arg;
|
|
|
|
|
|
|
|
auto& flags = args.a_flags.getFlags();
|
|
|
|
for (const auto& flag : flags)
|
|
|
|
user_args.flagAssociations[flag] = &arg;
|
|
|
|
}
|
|
|
|
|
|
|
|
const argparse::arg_results& argparse::parse_args(int argc, const char** argv) {
|
|
|
|
loaded_args = {};
|
|
|
|
arg_tokenizer asToken(argc, argv);
|
|
|
|
loaded_args.programName = asToken.next();
|
|
|
|
BLT_TRACE("Loading args for %s", loaded_args.programName.c_str());
|
|
|
|
|
|
|
|
return loaded_args;
|
2023-07-29 13:38:19 -04:00
|
|
|
}
|
2023-07-29 14:04:46 -04:00
|
|
|
|
|
|
|
|
2023-07-29 02:03:28 -04:00
|
|
|
}
|