From 59fddc997e405249708b9d6c9a611eaa8da8e983 Mon Sep 17 00:00:00 2001 From: badaix Date: Tue, 19 Jan 2016 23:24:12 +0100 Subject: [PATCH] options can be set multiple times --- PoplTest.cpp | 87 ++++++------------------------------------------ include/popl.hpp | 76 +++++++++++++++++++++++++++++++----------- 2 files changed, 67 insertions(+), 96 deletions(-) diff --git a/PoplTest.cpp b/PoplTest.cpp index 4f85962..f947759 100644 --- a/PoplTest.cpp +++ b/PoplTest.cpp @@ -22,88 +22,21 @@ using namespace std; using namespace popl; -void test(int argc, char **argv) -{ - OptionParser op("Allowed options"); - std::string s; - int i, m; - bool version; - - Switch helpSwitchOption("h", "help", "produce help message"); - Switch versionSwitchOption("v", "version", "show version number", &version); - - Value longOption("", "1234567890123456789012345678901234567890", "test of a long option name"); - - Value floatOption("f", "float", "test for float values"); - Value floatOptionDefault("", "floatDefault", "test for float values with default", 0.1); - Value intOption("i", "int", "test for int values"); - Value intOptionDefault("", "intDefault", "test for int values with default", 42); - Value intOptionDefaultAssign("", "intDefaultAssign", "test for int values with default\nAssign result to variable i", 42, &i); - Value stringOption("s", "string", "test for string values"); - Value stringOptionAssign("", "stringAssign", "test for string values\nAssign result to variable s", "", &s); - - Implicit implicitIntOption("m", "implicit", "implicit test", 5, &m); - - op.add(helpSwitchOption) - .add(versionSwitchOption) - .add(longOption) - .add(floatOption) - .add(floatOptionDefault) - .add(intOption) - .add(intOptionDefault) - .add(intOptionDefaultAssign) - .add(stringOption) - .add(stringOptionAssign) - .add(implicitIntOption); - - op.parse(argc, argv); - - if (helpSwitchOption.isSet()) - { - cout << op << "\n"; - return; - } - - if (version) - { - cout << POPL_VERSION << "\n"; - return; - } - - cout - << "floatOption isSet: " << floatOption.isSet() << ", value: " << floatOption.getValue() << "\n" - << "floatOptionDefault isSet: " << floatOptionDefault.isSet() << ", value: " << floatOptionDefault.getValue() << "\n" - << "intOption isSet: " << intOption.isSet() << ", value: " << intOption.getValue() << "\n" - << "intOptionDefault isSet: " << intOptionDefault.isSet() << ", value: " << intOptionDefault.getValue() << "\n" - << "intOptionDefaultA isSet: " << intOptionDefaultAssign.isSet() << ", value: " << intOptionDefaultAssign.getValue() << ", var: " << i << "\n" - << "stringOption isSet: " << stringOption.isSet() << ", value: " << stringOption.getValue() << "\n" - << "stringOptionAssign isSet: " << stringOptionAssign.isSet() << ", value: " << stringOptionAssign.getValue() << ", var: " << s << "\n" - << "implicitIntOption isSet: " << implicitIntOption.isSet() << ", value: " << implicitIntOption.getValue() << ", var: " << m << "\n"; - - for (size_t n=0; n floatOption("f", "float", "test for float values", 1.23, &f); + Value floatOption("f", "float", "test for float values", 1.23f, &f); + Value doubleOption("d", "double", "test for double values", 3.14159265359); Value stringOption("s", "string", "test for string values"); Implicit implicitIntOption("m", "implicit", "implicit test", 42, &m); OptionParser op("Allowed options"); op.add(helpOption) - .add(testOption) .add(floatOption) + .add(doubleOption) .add(stringOption) .add(implicitIntOption); @@ -122,13 +55,15 @@ int main(int argc, char **argv) cout << "UnknownOptions: " << op.unknownOptions()[n] << "\n"; // print all the configured values - cout << "testOption - value: " << testOption.getValue() << ", isSet: " << testOption.isSet() << ", count: " << testOption.count() << ", reference: " << t << "\n"; - cout << "floatOption - value: " << floatOption.getValue() << ", reference: " << f << "\n"; - cout << "stringOption - value: " << stringOption.getValue() << "\n"; + cout << "floatOption - isSet: " << floatOption.isSet() << ", value: " << floatOption.getValue() << ", reference: " << f << "\n"; + cout << "doubleOption - isSet: " << doubleOption.isSet() << ", value: " << doubleOption.getValue() << "\n"; + if (stringOption.isSet()) + { + for (size_t n=0; n& assignTo(T* var); Value& setDefault(const T& value); - T getValue() const; + T getValue(size_t idx = 0) const; protected: virtual void parse(const std::string& whatOption, const char* value); virtual std::string optionToString() const; virtual int hasArg() const; + virtual void addValue(const T& value); virtual void updateReference(); T* assignTo_; - T value_; + std::vector values_; T default_; bool hasDefault_; }; @@ -202,7 +203,7 @@ unsigned int Option::count() const bool Option::isSet() const { - return (count_ > 0); + return (count() > 0); } @@ -248,7 +249,6 @@ Value::Value(const std::string& shortOption, const std::string& longOption, c assignTo_(NULL), hasDefault_(false) { - updateReference(); } @@ -256,7 +256,6 @@ template Value::Value(const std::string& shortOption, const std::string& longOption, const std::string& description, const T& defaultVal, T* assignTo) : Option(shortOption, longOption, description), assignTo_(assignTo), - value_(defaultVal), default_(defaultVal), hasDefault_(true) { @@ -275,7 +274,6 @@ Value& Value::assignTo(T* var) template Value& Value::setDefault(const T& value) { - value_ = value; default_ = value; hasDefault_ = true; return *this; @@ -286,14 +284,54 @@ template void Value::updateReference() { if (assignTo_ != NULL) - *assignTo_ = value_; + { + if (isSet() || hasDefault_) + *assignTo_ = getValue(); + } } template -T Value::getValue() const +void Value::addValue(const T& value) { - return value_; + values_.push_back(value); + ++count_; + updateReference(); +} + + +template +T Value::getValue(size_t idx) const +{ + if (!isSet()) + { + if (hasDefault_) + return default_; + else + { + std::stringstream optionStr; + if (getShortOption() != 0) + optionStr << "-" << getShortOption(); + else + optionStr << "--" << getLongOption(); + + throw std::out_of_range("option not set: \"" + optionStr.str() + "\""); + } + } + + if (idx >= count_) + { + std::stringstream optionStr; + optionStr << "index out of range (" << idx << ") for \""; + if (getShortOption() != 0) + optionStr << "-" << getShortOption(); + else + optionStr << "--" << getLongOption(); + optionStr << "\""; + throw std::out_of_range(optionStr.str()); + } + + return values_[idx]; } @@ -307,14 +345,14 @@ int Value::hasArg() const template<> void Value::parse(const std::string& whatOption, const char* value) { - value_ = value; - updateReference(); + addValue(value); } template void Value::parse(const std::string& whatOption, const char* value) { + T parsedValue; std::string strValue; if (value != NULL) strValue = value; @@ -324,7 +362,7 @@ void Value::parse(const std::string& whatOption, const char* value) while (is.good()) { if (is.peek() != EOF) - is >> value_; + is >> parsedValue; else break; @@ -340,7 +378,7 @@ void Value::parse(const std::string& whatOption, const char* value) if (strValue.empty()) throw std::invalid_argument("missing argument for " + whatOption); - updateReference(); + addValue(parsedValue); } @@ -392,7 +430,7 @@ void Implicit::parse(const std::string& whatOption, const char* value) if (value != NULL) Value::parse(whatOption, value); else - this->updateReference(); + this->addValue(this->default_); } @@ -424,8 +462,7 @@ Switch::Switch(const std::string& shortOption, const std::string& longOption, co void Switch::parse(const std::string& whatOption, const char* value) { - value_ = true; - updateReference(); + addValue(true); } @@ -538,7 +575,6 @@ void OptionParser::parse(int argc, char **argv) for (size_t opt = 0; opt < options_.size(); ++opt) { Option* option(options_[opt]); - option->updateReference(); if (!option->getLongOption().empty()) { ::option o; @@ -595,7 +631,8 @@ void OptionParser::parse(int argc, char **argv) else if (c == '?') { // std::cout << "unknown(?): " << c << ", " << (char)c << ", " << optopt << ", " << (char)optopt << ", " << argv[curind] << "\n"; - unknownOptions_.push_back(argv[curind]); + if (std::find(unknownOptions_.begin(), unknownOptions_.end(), argv[curind]) == unknownOptions_.end()) + unknownOptions_.push_back(argv[curind]); } /// missing argument else if (c == ':') @@ -605,7 +642,6 @@ void OptionParser::parse(int argc, char **argv) if (option != NULL) { - ++option->count_; option->parse(argv[curind], optarg); } }