diff options
Diffstat (limited to 'subprojects/argspp')
| -rw-r--r-- | subprojects/argspp/args.cpp | 477 | ||||
| -rw-r--r-- | subprojects/argspp/args.h | 119 | ||||
| -rw-r--r-- | subprojects/argspp/meson.build | 5 |
3 files changed, 0 insertions, 601 deletions
diff --git a/subprojects/argspp/args.cpp b/subprojects/argspp/args.cpp deleted file mode 100644 index 21f483e..0000000 --- a/subprojects/argspp/args.cpp +++ /dev/null @@ -1,477 +0,0 @@ -// ----------------------------------------------------------------------------- -// Args++: an argument-parsing library in portable C++11. -// ----------------------------------------------------------------------------- - -#include "args.h" - -#include <algorithm> -#include <cctype> -#include <iostream> -#include <sstream> -#include <deque> -#include <set> - -using namespace std; -using namespace args; - - -// ----------------------------------------------------------------------------- -// Flags and Options. -// ----------------------------------------------------------------------------- - - -struct args::Flag { - int count = 0; -}; - - -struct args::Option { - vector<string> values; - string fallback; -}; - - -// ----------------------------------------------------------------------------- -// ArgStream. -// ----------------------------------------------------------------------------- - - -struct args::ArgStream { - deque<string> args; - void append(string const& arg); - string next(); - bool hasNext(); -}; - - -void ArgStream::append(string const& arg) { - args.push_back(arg); -} - - -string ArgStream::next() { - string arg = args.front(); - args.pop_front(); - return arg; -} - - -bool ArgStream::hasNext() { - return args.size() > 0; -} - - -// ----------------------------------------------------------------------------- -// ArgParser: setup. -// ----------------------------------------------------------------------------- - - -void ArgParser::flag(string const& name) { - Flag* flag = new Flag(); - stringstream stream(name); - string alias; - while (stream >> alias) { - flags[alias] = flag; - } -} - - -void ArgParser::option(string const& name, string const& fallback) { - Option* option = new Option(); - option->fallback = fallback; - stringstream stream(name); - string alias; - while (stream >> alias) { - options[alias] = option; - } -} - - -// ----------------------------------------------------------------------------- -// ArgParser: retrieve values. -// ----------------------------------------------------------------------------- - - -bool ArgParser::found(string const& name) const { - if (flags.count(name) > 0) { - return flags.at(name)->count > 0; - } - if (options.count(name) > 0) { - return options.at(name)->values.size() > 0; - } - return false; -} - - -int ArgParser::count(string const& name) const { - if (flags.count(name) > 0) { - return flags.at(name)->count; - } - if (options.count(name) > 0) { - return options.at(name)->values.size(); - } - return 0; -} - - -string ArgParser::value(string const& name) const { - if (options.count(name) > 0) { - if (options.at(name)->values.size() > 0) { - return options.at(name)->values.back(); - } - return options.at(name)->fallback; - } - return string(); -} - - -vector<string> ArgParser::values(string const& name) const { - if (options.count(name) > 0) { - return options.at(name)->values; - } - return vector<string>(); -} - - -// ----------------------------------------------------------------------------- -// ArgParser: commands. -// ----------------------------------------------------------------------------- - - -ArgParser& ArgParser::command( - string const& name, - string const& helptext, - void (*callback)(string cmd_name, ArgParser& cmd_parser)) { - - ArgParser *parser = new ArgParser(); - parser->helptext = helptext; - parser->callback = callback; - - stringstream stream(name); - string alias; - - while (stream >> alias) { - commands[alias] = parser; - } - - return *parser; -} - - -bool ArgParser::commandFound() { - return command_name != ""; -} - - -string ArgParser::commandName() { - return command_name; -} - - -ArgParser& ArgParser::commandParser() { - return *commands[command_name]; -} - - -// ----------------------------------------------------------------------------- -// ArgParser: parse arguments. -// ----------------------------------------------------------------------------- - - -// Parse an option of the form --name=value or -n=value. -void ArgParser::parseEqualsOption(string prefix, string name, string value) { - if (options.count(name) > 0) { - if (value.size() > 0) { - options[name]->values.push_back(value); - } else { - cerr << "Error: missing value for " << prefix << name << ".\n"; - exit(1); - } - } else { - cerr << "Error: " << prefix << name << " is not a recognised option.\n"; - exit(1); - } -} - - -// Parse a long-form option, i.e. an option beginning with a double dash. -void ArgParser::parseLongOption(string arg, ArgStream& stream) { - size_t pos = arg.find("="); - if (pos != string::npos) { - parseEqualsOption("--", arg.substr(0, pos), arg.substr(pos + 1)); - return; - } - - if (flags.count(arg) > 0) { - flags[arg]->count++; - return; - } - - if (options.count(arg) > 0) { - if (stream.hasNext()) { - options[arg]->values.push_back(stream.next()); - return; - } else { - cerr << "Error: missing argument for --" << arg << ".\n"; - exit(1); - } - } - - if (arg == "help" && this->helptext != "") { - exitHelp(); - } - - if (arg == "version" && this->version != "") { - exitVersion(); - } - - cerr << "Error: --" << arg << " is not a recognised flag or option.\n"; - exit(1); -} - - -// Parse a short-form option, i.e. an option beginning with a single dash. -void ArgParser::parseShortOption(string arg, ArgStream& stream) { - size_t pos = arg.find("="); - if (pos != string::npos) { - parseEqualsOption("-", arg.substr(0, pos), arg.substr(pos + 1)); - return; - } - - for (char& c: arg) { - string name = string(1, c); - - if (flags.count(name) > 0) { - flags[name]->count++; - continue; - } - - if (options.count(name) > 0) { - if (stream.hasNext()) { - options[name]->values.push_back(stream.next()); - continue; - } else { - if (arg.size() > 1) { - cerr << "Error: missing argument for '" << c << "' in -" << arg << ".\n"; - } else { - cerr << "Error: missing argument for -" << c << ".\n"; - } - exit(1); - } - } - - if (c == 'h' && this->helptext != "") { - exitHelp(); - } - - if (c == 'v' && this->version != "") { - exitVersion(); - } - - if (arg.size() > 1) { - cerr << "Error: '" << c << "' in -" << arg << " is not a recognised flag or option.\n"; - } else { - cerr << "Error: -" << c << " is not a recognised flag or option.\n"; - } - exit(1); - } -} - - -// Parse a stream of string arguments. -void ArgParser::parse(ArgStream& stream) { - bool is_first_arg = true; - - while (stream.hasNext()) { - string arg = stream.next(); - - // If we enounter a '--', turn off option parsing. - if (arg == "--") { - while (stream.hasNext()) { - args.push_back(stream.next()); - } - continue; - } - - // Is the argument a long-form option or flag? - if (arg.compare(0, 2, "--") == 0) { - parseLongOption(arg.substr(2), stream); - continue; - } - - // Is the argument a short-form option or flag? If the argument - // consists of a single dash or a dash followed by a digit, we treat - // it as a positional argument. - if (arg[0] == '-') { - if (arg.size() == 1 || isdigit(arg[1])) { - args.push_back(arg); - } else { - parseShortOption(arg.substr(1), stream); - } - continue; - } - - // Is the argument a registered command? - if (is_first_arg && commands.count(arg) > 0) { - ArgParser* command_parser = commands[arg]; - command_name = arg; - command_parser->parse(stream); - if (command_parser->callback != nullptr) { - command_parser->callback(arg, *command_parser); - } - continue; - } - - // Is the argument the automatic 'help' command? - if (is_first_arg && arg == "help" && commands.size() > 0) { - if (stream.hasNext()) { - string name = stream.next(); - if (commands.find(name) == commands.end()) { - cerr << "Error: '" << name << "' is not a recognised command.\n"; - exit(1); - } else { - commands[name]->exitHelp(); - } - } else { - cerr << "Error: the help command requires an argument.\n"; - exit(1); - } - } - - // Otherwise add the argument to our list of positional arguments. - args.push_back(arg); - is_first_arg = false; - } -} - - -// Parse an array of string arguments. We assume that [argc] and [argv] are the -// original parameters passed to main() and skip the first element. In some -// situations [argv] can be empty, i.e. [argc == 0]. This can lead to security -// vulnerabilities if not handled explicitly. -void ArgParser::parse(int argc, char **argv) { - if (argc > 1) { - ArgStream stream; - for (int i = 1; i < argc; i++) { - stream.append(argv[i]); - } - parse(stream); - } -} - - -// Parse a vector of string arguments. -void ArgParser::parse(vector<string> args) { - ArgStream stream; - for (string& arg: args) { - stream.append(arg); - } - parse(stream); -} - - -// ----------------------------------------------------------------------------- -// ArgParser: utilities. -// ----------------------------------------------------------------------------- - - -// Override the << stream insertion operator to support vectors. This will -// allow us to cout our lists of option values in the print() method. -template<typename T> -static ostream& operator<<(ostream& stream, const vector<T>& vec) { - stream << "["; - for(size_t i = 0; i < vec.size(); ++i) { - if (i) cout << ", "; - stream << vec[i]; - } - stream << "]"; - return stream; -} - - -// Dump the parser's state to stdout. -void ArgParser::print() { - cout << "Options:\n"; - if (options.size() > 0) { - for (auto element: options) { - cout << " " << element.first << ": "; - Option *option = element.second; - cout << "(" << option->fallback << ") "; - cout << option->values; - cout << "\n"; - } - } else { - cout << " [none]\n"; - } - - cout << "\nFlags:\n"; - if (flags.size() > 0) { - for (auto element: flags) { - cout << " " << element.first << ": " << element.second->count << "\n"; - } - } else { - cout << " [none]\n"; - } - - cout << "\nArguments:\n"; - if (args.size() > 0) { - for (auto arg: args) { - cout << " " << arg << "\n"; - } - } else { - cout << " [none]\n"; - } - - cout << "\nCommand:\n"; - if (commandFound()) { - cout << " " << command_name << "\n"; - } else { - cout << " [none]\n"; - } -} - - -// Print the parser's help text and exit. -void ArgParser::exitHelp() { - cout << helptext << endl; - exit(0); -} - - -// Print the parser's version string and exit. -void ArgParser::exitVersion() { - cout << version << endl; - exit(0); -} - - -// ----------------------------------------------------------------------------- -// ArgParser: cleanup. -// ----------------------------------------------------------------------------- - - -ArgParser::~ArgParser() { - set<Option*> unique_options; - for (auto element: options) { - unique_options.insert(element.second); - } - for (auto pointer: unique_options) { - delete pointer; - } - - set<Flag*> unique_flags; - for (auto element: flags) { - unique_flags.insert(element.second); - } - for (auto pointer: unique_flags) { - delete pointer; - } - - set<ArgParser*> unique_cmd_parsers; - for (auto element: commands) { - unique_cmd_parsers.insert(element.second); - } - for (auto pointer: unique_cmd_parsers) { - delete pointer; - } -} diff --git a/subprojects/argspp/args.h b/subprojects/argspp/args.h deleted file mode 100644 index a120f4e..0000000 --- a/subprojects/argspp/args.h +++ /dev/null @@ -1,119 +0,0 @@ -// ----------------------------------------------------------------------------- -// Args++: an argument-parsing library in portable C++11. -// -// Author: Darren Mulholland <dmulholl@tcd.ie> -// License: Public Domain -// Version: 2.1.0 -// ----------------------------------------------------------------------------- - -#ifndef args_h -#define args_h - -#include <map> -#include <string> -#include <vector> -#include <sstream> - -namespace args { - - struct ArgStream; - struct Option; - struct Flag; - - class ArgParser { - public: - ArgParser( - std::string const& helptext = "", - std::string const& version = "" - ) : helptext(helptext), version(version) {} - - ~ArgParser(); - - // Stores positional arguments. - std::vector<std::string> args; - - // Application/command help text and version strings. - std::string helptext; - std::string version; - - // Callback function for command parsers. - void (*callback)(std::string cmd_name, ArgParser& cmd_parser); - - // Register flags and options. - void flag(std::string const& name); - void option(std::string const& name, std::string const& fallback = ""); - - // Parse the application's command line arguments. - void parse(int argc, char **argv); - void parse(std::vector<std::string> args); - - // Retrieve flag and option values. - bool found(std::string const& name) const; - int count(std::string const& name) const; - std::string value(std::string const& name) const; - std::vector<std::string> values(std::string const& name) const; - - template<typename T> - T value(std::string const& name) const - { - std::string str = value(name); - T ret = scan<T>(str); - return ret; - } - - template<typename T> - std::vector<T> values(std::string const& name) const - { - std::vector<std::string> vec = values(name); - std::vector<T> ret; - ret.reserve(vec.size()); - for (size_t i = 0; i < vec.size(); ++i) { - T value = vec[i]; - ret.push_back(value); - } - return ret; - } - - // Register a command. Returns the command's ArgParser instance. - ArgParser& command( - std::string const& name, - std::string const& helptext = "", - void (*callback)(std::string cmd_name, ArgParser& cmd_parser) = nullptr - ); - - // Utilities for handling commands manually. - bool commandFound(); - std::string commandName(); - ArgParser& commandParser(); - - // Print a parser instance to stdout. - void print(); - - private: - std::map<std::string, Option*> options; - std::map<std::string, Flag*> flags; - std::map<std::string, ArgParser*> commands; - std::string command_name; - - void parse(ArgStream& args); - void registerOption(std::string const& name, Option* option); - void parseLongOption(std::string arg, ArgStream& stream); - void parseShortOption(std::string arg, ArgStream& stream); - void parseEqualsOption(std::string prefix, std::string name, std::string value); - void exitHelp(); - void exitVersion(); - - template<typename T> - T scan(const std::string &input) const - { - std::stringstream stream(input); - T ret; - if ((stream >> ret).fail()) { - return T{0}; - } - return ret; - } - }; -} - -#endif diff --git a/subprojects/argspp/meson.build b/subprojects/argspp/meson.build deleted file mode 100644 index 50aec98..0000000 --- a/subprojects/argspp/meson.build +++ /dev/null @@ -1,5 +0,0 @@ -project('argspp', 'cpp', version: '2.1.0') - -argspp_inc = include_directories('.') -argspp_lib = static_library('argspp', 'args.cpp', include_directories: argspp_inc) -argspp = declare_dependency(link_with: argspp_lib, include_directories: argspp_inc) |