diff options
-rw-r--r-- | diargs.cpp | 30 | ||||
-rw-r--r-- | diargs.hpp | 68 |
2 files changed, 87 insertions, 11 deletions
@@ -1,3 +1,25 @@ +/** + * diargs.cpp + * Copyright (c) 2022 Jon Santmyer <jon@jonsantmyer.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ #include "diargs.hpp" #include <string_view> #include <list> @@ -10,14 +32,16 @@ ArgumentParser::ArgumentParser( ArgumentList &arguments, ArgsPair argcv) { + /*Raw c strings passed to string_view for safety*/ std::vector<std::string_view> argv(argcv.argc); for(int arg = 0; arg < argcv.argc; arg++) { argv[arg] = std::string_view(argcv.argv[arg]); } + /*Skip the first argument because it will always be the path to the program*/ for(auto it = argv.begin() + 1; it != argv.end(); it++) { - if(it->at(0) == '-') { - if(it->at(1) == '-') { + if(it->at(0) == '-') { /*Argument could be shortform*/ + if(it->at(1) == '-') { /*Argument is longform*/ std::string_view parsing = std::string_view(it->data() + 2); if(parsing.size() == 0) continue; for(auto &argdef : arguments.arguments) { @@ -45,7 +69,7 @@ ArgumentParser::ArgumentParser( } } continue; - } + } /*When argument is unmarked, it's an ordered type*/ for(auto argit = arguments.arguments.begin(); argit != arguments.arguments.end(); argit++) { @@ -1,3 +1,49 @@ +/** + * diargs.hpp + * Copyright (c) 2022 Jon Santmyer <jon@jonsantmyer.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * diargs - An alternative to GNU getopt for modern C++ + * Provides tools to parse command line arguments for C++17 programs + * + * Usage: Instantiate an ArgumentParser class, passing in a fallback + * error function, an ArgumentList struct, and an argc,argv pair. + * + * Example: + * + * void printusage(int err) { + * std::cout << "-h --help : Print this message" << std::endl; + * std::exit(err); + * } + * + * int main(int argc, char **argv) { + * bool helpflag; + * + * ArgsPair args{argc, argv}; + * ArgumentList argslist( + * ToggleArgument("help", 'h', helpflag, true) + * ); + * ArgumentParser parser(printusage, argslist, args); + * return 0; + * } + */ #ifndef DIARGS_HPP #define DIARGS_HPP 1 @@ -10,15 +56,17 @@ namespace diargs { + /*Passed to ArgumentParser*/ struct ArgsPair { int argc {}; char **argv {}; }; + /*Interface for argument types. Makes the whole system tick*/ struct IArgument { - std::string longform {}; - char shortform {}; + std::string longform {}; /*Name parsed when passed through with '--'*/ + char shortform {}; /*Character parsed when passed through with '-'*/ IArgument() = default; IArgument(const std::string &Longform, char Shortform) : @@ -33,7 +81,8 @@ namespace diargs { template<typename T> struct MultiArgument : public IArgument { - T *flag; + T *flag; /*Value set when encountered. Taken from next argument + i.e. --arg [VALUE]*/ MultiArgument(T &Flag) : flag(&Flag) {} MultiArgument(const std::string &Longform, T &Flag) : @@ -45,7 +94,8 @@ namespace diargs { std::optional<std::vector<std::string_view>::iterator> parse( std::vector<std::string_view> &argv, std::vector<std::string_view>::iterator arg) { - if(++arg == argv.end()) return std::nullopt; + if(++arg == argv.end()) return std::nullopt; /*Not having the + value is an error case*/ std::stringstream ss((*arg).data()); ss >> std::noskipws >> *flag; return arg; @@ -55,8 +105,8 @@ namespace diargs { template<typename T> struct ToggleArgument : public IArgument { - T *flag; - T set; + T *flag; /*Value set to [set] when encountered*/ + T set; /*Value that [flag] is set to when parsed*/ ToggleArgument(T &Flag, const T Set) : flag(&Flag), set(Set) {} @@ -75,10 +125,11 @@ namespace diargs { } }; + /*Type for values not denoted with '-' or '--'*/ template<typename T> struct OrderedArgument : public IArgument { - T *flag; + T *flag; /*Value set when passed arg is not any other type*/ std::optional<T> dflt; OrderedArgument(T &Flag) : flag(&Flag), dflt(std::nullopt) {} @@ -94,6 +145,7 @@ namespace diargs { } }; + /*Container for argument checking*/ struct ArgumentList { std::vector<std::unique_ptr<IArgument>> arguments; @@ -111,9 +163,9 @@ namespace diargs { } }; + /*Instantiation results in parsed arguments*/ class ArgumentParser { - void (*m_abortfunc)(int); public: ArgumentParser( void (*failfunc)(int), |