From f8386836dfda04c626e63ba9d64c1a4f63867dfa Mon Sep 17 00:00:00 2001
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Date: Sat, 23 Mar 2019 06:05:46 +0200
Subject: cam: Separate options valid() and empty()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

An empty option list is not necessarily an error. Add a new empty()
function to test the option list for emptiness, and modify the valid()
function to only notify parsing errors. As a side effect this allows
accessing partially parsed options, which may be useful in the future.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Jacopo Mondi <jacopo@jmondi.org>
Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
---
 src/cam/main.cpp    |  7 +++++--
 src/cam/options.cpp | 34 +++++++++++++++-------------------
 src/cam/options.h   |  5 ++++-
 3 files changed, 24 insertions(+), 22 deletions(-)

(limited to 'src/cam')

diff --git a/src/cam/main.cpp b/src/cam/main.cpp
index 1ca7862b..e7490c32 100644
--- a/src/cam/main.cpp
+++ b/src/cam/main.cpp
@@ -67,9 +67,12 @@ static int parseOptions(int argc, char *argv[])
 	parser.addOption(OptList, OptionNone, "List all cameras", "list");
 
 	options = parser.parse(argc, argv);
-	if (!options.valid() || options.isSet(OptHelp)) {
+	if (!options.valid())
+		return -EINVAL;
+
+	if (options.empty() || options.isSet(OptHelp)) {
 		parser.usage();
-		return !options.valid() ? -EINVAL : -EINTR;
+		return options.empty() ? -EINVAL : -EINTR;
 	}
 
 	return 0;
diff --git a/src/cam/options.cpp b/src/cam/options.cpp
index 92b6b8ef..172d40f7 100644
--- a/src/cam/options.cpp
+++ b/src/cam/options.cpp
@@ -40,10 +40,16 @@ const char *Option::typeName() const
  * OptionBase<T>
  */
 
+template<typename T>
+bool OptionsBase<T>::empty() const
+{
+	return values_.empty();
+}
+
 template<typename T>
 bool OptionsBase<T>::valid() const
 {
-	return !values_.empty();
+	return valid_;
 }
 
 template<typename T>
@@ -105,12 +111,6 @@ bool OptionsBase<T>::parseValue(const T &opt, const Option &option,
 	return true;
 }
 
-template<typename T>
-void OptionsBase<T>::clear()
-{
-	values_.clear();
-}
-
 template class OptionsBase<int>;
 template class OptionsBase<std::string>;
 
@@ -170,21 +170,18 @@ KeyValueParser::Options KeyValueParser::parse(const char *arguments)
 
 		if (optionsMap_.find(key) == optionsMap_.end()) {
 			std::cerr << "Invalid option " << key << std::endl;
-			options.clear();
-			break;
+			return options;
 		}
 
 		OptionArgument arg = optionsMap_[key].argument;
 		if (value.empty() && arg == ArgumentRequired) {
 			std::cerr << "Option " << key << " requires an argument"
 				  << std::endl;
-			options.clear();
-			break;
+			return options;
 		} else if (!value.empty() && arg == ArgumentNone) {
 			std::cerr << "Option " << key << " takes no argument"
 				  << std::endl;
-			options.clear();
-			break;
+			return options;
 		}
 
 		const Option &option = optionsMap_[key];
@@ -192,11 +189,11 @@ KeyValueParser::Options KeyValueParser::parse(const char *arguments)
 			std::cerr << "Failed to parse '" << value << "' as "
 				  << option.typeName() << " for option " << key
 				  << std::endl;
-			options.clear();
-			break;
+			return options;
 		}
 	}
 
+	options.valid_ = true;
 	return options;
 }
 
@@ -438,19 +435,18 @@ OptionsParser::Options OptionsParser::parse(int argc, char **argv)
 			std::cerr << argv[optind - 1] << std::endl;
 
 			usage();
-			options.clear();
-			break;
+			return options;
 		}
 
 		const Option &option = *optionsMap_[c];
 		if (!options.parseValue(c, option, optarg)) {
 			parseValueError(option);
 			usage();
-			options.clear();
-			break;
+			return options;
 		}
 	}
 
+	options.valid_ = true;
 	return options;
 }
 
diff --git a/src/cam/options.h b/src/cam/options.h
index 6e3ef62e..5e346b47 100644
--- a/src/cam/options.h
+++ b/src/cam/options.h
@@ -47,6 +47,9 @@ template<typename T>
 class OptionsBase
 {
 public:
+	OptionsBase() : valid_(false) {}
+
+	bool empty() const;
 	bool valid() const;
 	bool isSet(const T &opt) const;
 	const OptionValue &operator[](const T &opt) const;
@@ -56,9 +59,9 @@ private:
 	friend class OptionsParser;
 
 	bool parseValue(const T &opt, const Option &option, const char *value);
-	void clear();
 
 	std::map<T, OptionValue> values_;
+	bool valid_;
 };
 
 class KeyValueParser
-- 
cgit v1.2.1