From 16e3f58ce9b7ce60e1f4c428688337a18c617274 Mon Sep 17 00:00:00 2001 From: Pranav Srinivas Kumar Date: Sat, 30 Mar 2019 12:58:28 -0400 Subject: [PATCH] Added support for list of arguments per parameter. Added nargs method --- src/argparse.hpp | 76 ++++++++++++++++++++++++++++++++++++++---------- tests/main.cpp | 13 +++++++-- 2 files changed, 71 insertions(+), 18 deletions(-) diff --git a/src/argparse.hpp b/src/argparse.hpp index 05ed881..d11a032 100644 --- a/src/argparse.hpp +++ b/src/argparse.hpp @@ -29,8 +29,8 @@ struct Argument { std::string mHelp; std::function mDefaultValue; std::function mAction; - std::any mValue; - std::string mRawValue; + std::vector mValues; + std::vector mRawValues; size_t mNumArgs; Argument() : @@ -38,8 +38,8 @@ struct Argument { mHelp(""), mDefaultValue(nullptr), mAction([](const std::string& aValue) { return aValue; }), - mValue(nullptr), - mRawValue(""), + mValues({}), + mRawValues({}), mNumArgs(1) {} Argument& help(const std::string& aHelp) { @@ -64,7 +64,7 @@ struct Argument { template T get() { - if (!mValue.has_value()) { + if (mValues.size() == 0) { if (mDefaultValue != nullptr) { return std::any_cast(mDefaultValue()); } @@ -72,8 +72,8 @@ struct Argument { return T(); } else { - if (mRawValue != "") - return std::any_cast(mValue); + if (mRawValues.size() > 0) + return std::any_cast(mValues[0]); else { if (mDefaultValue != nullptr) return std::any_cast(mDefaultValue()); @@ -83,6 +83,43 @@ struct Argument { } } + template + std::vector get_list() { + std::vector tResult; + if (mValues.size() == 0) { + if (mDefaultValue != nullptr) { + std::any tDefaultValueLambdaResult = mDefaultValue(); + std::vector tDefaultValues = std::any_cast>(tDefaultValueLambdaResult); + for (size_t i = 0; i < tDefaultValues.size(); i++) { + tResult.push_back(std::any_cast(tDefaultValues[i])); + } + return tResult; + } + else + return std::vector(); + } + else { + if (mRawValues.size() > 0) { + for (size_t i = 0; i < mValues.size(); i++) { + tResult.push_back(std::any_cast(mValues[i])); + } + return tResult; + } + else { + if (mDefaultValue != nullptr) { + std::any tDefaultValueLambdaResult = mDefaultValue(); + std::vector tDefaultValues = std::any_cast>(tDefaultValueLambdaResult); + for (size_t i = 0; i < tDefaultValues.size(); i++) { + tResult.push_back(std::any_cast(tDefaultValues[i])); + } + return tResult; + } + else + return std::vector(); + } + } + } + }; class ArgumentParser { @@ -112,14 +149,14 @@ class ArgumentParser { while (tCount > 0) { i = i + 1; if (i < argc) { - tArgument->mRawValue = argv[i]; + tArgument->mRawValues.push_back(argv[i]); if (tArgument->mAction != nullptr) - tArgument->mValue = tArgument->mAction(argv[i]); + tArgument->mValues.push_back(tArgument->mAction(argv[i])); else { if (tArgument->mDefaultValue != nullptr) - tArgument->mValue = tArgument->mDefaultValue(); + tArgument->mValues.push_back(tArgument->mDefaultValue()); else - tArgument->mValue = std::string(argv[i]); + tArgument->mValues.push_back(std::string(argv[i])); } } tCount -= 1; @@ -139,15 +176,22 @@ class ArgumentParser { template T get(const char * aArgumentName) { - for (auto& tArgument : mArguments) { - auto tIndex = std::find(tArgument->mNames.begin(), tArgument->mNames.end(), aArgumentName); - if (tIndex != tArgument->mNames.end()) { - return tArgument->get(); - } + std::map>::iterator tIterator = mArgumentMap.find(aArgumentName); + if (tIterator != mArgumentMap.end()) { + return tIterator->second->get(); } return T(); } + template + std::vector get_list(const char * aArgumentName) { + std::map>::iterator tIterator = mArgumentMap.find(aArgumentName); + if (tIterator != mArgumentMap.end()) { + return tIterator->second->get_list(); + } + return std::vector(); + } + private: Argument& add_argument_internal(std::shared_ptr aArgument) { return *aArgument; diff --git a/tests/main.cpp b/tests/main.cpp index 35c54cd..1d783c7 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -11,20 +11,29 @@ int main(int argc, char * argv[]) { program.add_argument("-n", "--num_iterations") .help("Number of iterations") - .nargs(2) .action([](const std::string& value) { return std::stoi(value); }); program.add_argument("-v", "--verbose", "VERBOSE") - .default_value([]() { return true; }); + .nargs(0) + .default_value([]() { return false; }); + + program.add_argument("--test_inputs") + .nargs(3) + .default_value([]() { return std::vector{ 1, 2, 3 }; }) + .action([](const std::string& value) { return std::stoi(value); }); program.parse_args(argc, argv); auto config_file = program.get("--config"); auto num_iters = program.get("-n"); auto verbose = program.get("-v"); + auto test_inputs = program.get_list("--test_inputs"); std::cout << config_file << std::endl; std::cout << num_iters << std::endl; std::cout << verbose << std::endl; + for (auto& input : test_inputs) + std::cout << input << std::endl; + return 0; } \ No newline at end of file