BLT/src/blt/parse/argparse.cpp

147 lines
4.0 KiB
C++
Raw Normal View History

/*
* 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"
namespace blt::parser {
2023-07-29 13:38:19 -04:00
arg_vector::arg_vector(const std::vector<std::string>& args) {
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
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;
}
// 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)
2023-07-31 13:53:10 -04:00
user_args.nameAssociations.emplace_back(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());
2023-07-31 13:53:10 -04:00
size_t lastPositional;
while (asToken.hasNext()) {
if (!asToken.isFlag()){
loaded_args.positionalArgs[user_args.nameAssociations[lastPositional].first] = asToken.next();
continue;
}
}
return loaded_args;
2023-07-29 13:38:19 -04:00
}
2023-07-29 14:04:46 -04:00
}