summaryrefslogtreecommitdiff
path: root/src/cam/options.cpp
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2019-01-31 23:36:04 +0200
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2019-02-01 11:42:02 +0200
commitc8c546fe99a343c13c7c0b8f2e5e180c19831b43 (patch)
tree631d116f09aa60d39fe4205507c9ac5ab667ef20 /src/cam/options.cpp
parent6f3503981a4f20ef3e939a9b91c29ef12d95efd2 (diff)
cam: options: Add option type handling to options parser
Extend the options parser with support for option types. All options must now specify the type of their argument, and the parser automatically parses the argument and handles errors internally. Available types are none, integer or string. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
Diffstat (limited to 'src/cam/options.cpp')
-rw-r--r--src/cam/options.cpp133
1 files changed, 128 insertions, 5 deletions
diff --git a/src/cam/options.cpp b/src/cam/options.cpp
index c13022ce..204081f3 100644
--- a/src/cam/options.cpp
+++ b/src/cam/options.cpp
@@ -12,6 +12,30 @@
#include "options.h"
+/* -----------------------------------------------------------------------------
+ * Option
+ */
+
+const char *Option::typeName() const
+{
+ switch (type) {
+ case OptionNone:
+ return "none";
+
+ case OptionInteger:
+ return "integer";
+
+ case OptionString:
+ return "string";
+ }
+
+ return "unknown";
+}
+
+/* -----------------------------------------------------------------------------
+ * OptionBase<T>
+ */
+
template <typename T>
bool OptionsBase<T>::valid() const
{
@@ -25,12 +49,46 @@ bool OptionsBase<T>::isSet(const T &opt) const
}
template <typename T>
-const std::string &OptionsBase<T>::operator[](const T &opt) const
+const OptionValue &OptionsBase<T>::operator[](const T &opt) const
{
return values_.find(opt)->second;
}
template <typename T>
+bool OptionsBase<T>::parseValue(const T &opt, const Option &option,
+ const char *optarg)
+{
+ OptionValue value;
+
+ switch (option.type) {
+ case OptionNone:
+ break;
+
+ case OptionInteger:
+ unsigned int integer;
+
+ if (optarg) {
+ char *endptr;
+ integer = strtoul(optarg, &endptr, 10);
+ if (*endptr != '\0')
+ return false;
+ } else {
+ integer = 0;
+ }
+
+ value = OptionValue(integer);
+ break;
+
+ case OptionString:
+ value = OptionValue(optarg ? optarg : "");
+ break;
+ }
+
+ values_[opt] = value;
+ return true;
+}
+
+template <typename T>
void OptionsBase<T>::clear()
{
values_.clear();
@@ -38,8 +96,53 @@ void OptionsBase<T>::clear()
template class OptionsBase<int>;
-bool OptionsParser::addOption(int opt, const char *help, const char *name,
- OptionArgument argument, const char *argumentName)
+/* -----------------------------------------------------------------------------
+ * OptionValue
+ */
+
+OptionValue::OptionValue()
+ : type_(OptionNone)
+{
+}
+
+OptionValue::OptionValue(int value)
+ : type_(OptionInteger), integer_(value)
+{
+}
+
+OptionValue::OptionValue(const char *value)
+ : type_(OptionString), string_(value)
+{
+}
+
+OptionValue::OptionValue(const std::string &value)
+ : type_(OptionString), string_(value)
+{
+}
+
+OptionValue::operator int() const
+{
+ if (type_ != OptionInteger)
+ return 0;
+
+ return integer_;
+}
+
+OptionValue::operator std::string() const
+{
+ if (type_ != OptionString)
+ return std::string();
+
+ return string_;
+}
+
+/* -----------------------------------------------------------------------------
+ * OptionsParser
+ */
+
+bool OptionsParser::addOption(int opt, OptionType type, const char *help,
+ const char *name, OptionArgument argument,
+ const char *argumentName)
{
/*
* Options must have at least a short or long name, and a text message.
@@ -56,7 +159,8 @@ bool OptionsParser::addOption(int opt, const char *help, const char *name,
if (optionsMap_.find(opt) != optionsMap_.end())
return false;
- options_.push_back(Option({ opt, name, argument, argumentName, help }));
+ options_.push_back(Option({ opt, type, name, argument, argumentName,
+ help }));
optionsMap_[opt] = &options_.back();
return true;
}
@@ -126,7 +230,13 @@ OptionsParser::Options OptionsParser::parse(int argc, char **argv)
break;
}
- options.values_[c] = optarg ? optarg : "";
+ const Option &option = *optionsMap_[c];
+ if (!options.parseValue(c, option, optarg)) {
+ parseValueError(option);
+ usage();
+ options.clear();
+ break;
+ }
}
return options;
@@ -193,3 +303,16 @@ void OptionsParser::usage()
}
}
}
+
+void OptionsParser::parseValueError(const Option &option)
+{
+ std::string optionName;
+
+ if (option.name)
+ optionName = "--" + std::string(option.name);
+ else
+ optionName = "-" + static_cast<char>(option.opt);
+
+ std::cerr << "Can't parse " << option.typeName()
+ << " argument for option " << optionName << std::endl;
+}