From: Rafał Długołęcki Date: Sun, 3 May 2015 09:27:26 +0000 (+0200) Subject: Added mechanism to understand passed Option value. X-Git-Tag: v0.2~26 X-Git-Url: https://git.dlugolecki.net.pl/?p=command.git;a=commitdiff_plain;h=2900a7396aa582dcf622b968c286059b28d9c0a8 Added mechanism to understand passed Option value. --- diff --git a/include/argument.h b/include/argument.h index 159f5eb..82954eb 100644 --- a/include/argument.h +++ b/include/argument.h @@ -51,16 +51,17 @@ namespace command { /** * Method used for checking if Argument understands user value. - * If so current Argument is flagged as used, and no more checks against + * If so current Argument is flagged as used and no more checks against * it will be done in future. * - * If conversion from passed value to ArgumentType is impossible, it is - * ignored. + * \attention If conversion from passed value to ArgumentType is + * impossible, it is ignored. It means that it is not understanded by + * Argument. * * @param argv command line value against which test will be made. * * @return If passed argv is succesfully converted to ArgumentType, - * returns true, and Argument is set as used one. If there was an error + * returns true and Argument is set as used one. If there was an error * during conversion, method returns false and can be used to check * against next value. */ diff --git a/include/option.h b/include/option.h index 270bb76..dba1c16 100644 --- a/include/option.h +++ b/include/option.h @@ -2,6 +2,8 @@ #define __COMMAND_OPTION_H #include +#include +#include #include "parameter.h" @@ -11,16 +13,26 @@ namespace command { * Options are non-required, named parameters of program. * * Example: - * ./myprog OptionName OptionValue + * ./myprog OptionName=OptionValue */ template class Option : public Parameter, public Callable { + public: + typedef std::string OptionName; protected: /** - * Option name + * Current Option name + */ + OptionName name; + + /** + * Current Option value */ - std::string name; + OptionType value; + + /** Variable indicating if current Option was already used or not */ + bool used = false; public: /** @@ -33,17 +45,66 @@ namespace command { Option(std::string name, const std::string & description, void (*function)(OptionType)) : Parameter(description), Callable(function), name(name) { } + + /** + * + */ virtual ~Option() { } + /** + * + */ virtual void handle() { - this->call(std::string("O")); + this->call(value); } - virtual bool understand(const std::string & argVal) { - if (argVal.find(name) != std::string::npos) { + /** + * Method used for checking if Option understands given user value. + * If so current Option is flagged as used and no more checks against + * it will be done in future. + * + * Passed value should be in form of: + * OptionName=OptionValue + * + * If no equal sign is after OptionName part, + * std::invalid_argument exception with appropriate message is thrown + * + * If conversion of OptionValue part to OptionType failed, + * std::invalid_argument exception with appropriate message is thrown + * + * @param argv command line value against which test will be made. + * User value should be in format: OptionName=OptionValue. + * + * @return If passed argv succesfully detected OptionName part as a + * current option and its OptionValue part has been succesfully + * converted to OptionType, returns true and Option is set as used one. + * Otherwise returns false and can be used to check against next value. + * + * @throw std::invalid_argument when OptionName part has no equal sign + * after itself + * @throw std::invalid_argument when OptionValue part failed conversion + * to OptionType + */ + virtual bool understand(const std::string & argv) { + if ((!used) && + (argv.find(name) == 0)) { + std::size_t pos = argv.find("="); + if (pos != name.size()) { + throw std::invalid_argument("Option: " + name + " requires value but no one has been provided"); + } + + std::stringstream ss; + + ss << argv.substr(pos + 1); + ss >> value; + + if (ss.fail()) { + throw std::invalid_argument("Value for option: " + name + " failed conversion to the required type"); + } + + used = true; return true; } - return false; } }; diff --git a/src/main.cpp b/src/main.cpp index 813491a..0174345 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,11 +9,15 @@ void some_function(bool a) { std::cout << "Some function " << a << std::endl; } +void help_function(std::string a) { + std::cout << "Some function " << a << std::endl; +} + int main(int argc, char *argv[]) { command::Command command(argc, argv, { // new command::Argument("File path", [](std::string value)->void { std::cout << "Hello from lambda " << value << std::endl; }), - new command::Argument("File path", some_function)/*, - new command::Option("h", "Help", some_function)*/ + new command::Argument("File path", some_function), + new command::Option("h", "Help", help_function) }); return 0;