[libcamera-devel,4/6] cam: options: remove OptionsParser::options_

Message ID 20190128004109.25860-5-niklas.soderlund@ragnatech.se
State Superseded
Headers show
Series
  • cam: add --format option to configure a stream
Related show

Commit Message

Niklas Söderlund Jan. 28, 2019, 12:41 a.m. UTC
It's unsafe to keep a pointer to an object inside a vector if one keeps
adding and modifying the vectors content. There are also little need to
keep the two data structures around when one map can solve the problem.
Remove the vector and update all loops to iterate over the map instead
of the vector.

Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
---
 src/cam/options.cpp | 18 +++++++++++-------
 src/cam/options.h   |  3 +--
 2 files changed, 12 insertions(+), 9 deletions(-)

Comments

Laurent Pinchart Jan. 31, 2019, 10:13 a.m. UTC | #1
Hi Niklas,

Thank you for the patch.

On Mon, Jan 28, 2019 at 01:41:07AM +0100, Niklas Söderlund wrote:
> It's unsafe to keep a pointer to an object inside a vector if one keeps
> adding and modifying the vectors content.

Very good point.

> There are also little need to keep the two data structures around when
> one map can solve the problem. Remove the vector and update all loops
> to iterate over the map instead of the vector.
> 
> Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
> ---
>  src/cam/options.cpp | 18 +++++++++++-------
>  src/cam/options.h   |  3 +--
>  2 files changed, 12 insertions(+), 9 deletions(-)
> 
> diff --git a/src/cam/options.cpp b/src/cam/options.cpp
> index c9ca017b4cf3fa3d..d3bff1cd897a5cfb 100644
> --- a/src/cam/options.cpp
> +++ b/src/cam/options.cpp
> @@ -30,8 +30,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 }));
> -	optionsMap_[opt] = &options_.back();
> +	optionsMap_[opt] = Option({ opt, name, argument, argumentName, help });
> +
>  	return true;
>  }
>  
> @@ -43,14 +43,16 @@ OptionsParser::Options OptionsParser::parse(int argc, char **argv)
>  	 * Allocate short and long options arrays large enough to contain all
>  	 * options.
>  	 */
> -	char shortOptions[options_.size() * 3 + 2] = {};
> -	struct option longOptions[options_.size() + 1] = {};
> +	char shortOptions[optionsMap_.size() * 3 + 2] = {};
> +	struct option longOptions[optionsMap_.size() + 1] = {};
>  	unsigned int ids = 0;
>  	unsigned int idl = 0;
>  
>  	shortOptions[ids++] = ':';
>  
> -	for (const Option &option : options_) {
> +	for (auto const &iter : optionsMap_) {
> +		const Option &option = iter.second;
> +
>  		if (option.hasShortOption()) {
>  			shortOptions[ids++] = option.opt;
>  			if (option.argument != ArgumentNone)
> @@ -112,7 +114,8 @@ void OptionsParser::usage()
>  
>  	unsigned int indent = 0;
>  
> -	for (const Option &option : options_) {
> +	for (auto const &iter : optionsMap_) {
> +		const Option &option = iter.second;

This will result in options being sorted base on their value. Do we
really want this ?

An alternative would be to replace the std::vector options_ with an
std::list that will not invalidate iterators and references when
inserting an element at the end.

>  		unsigned int length = 14;
>  		if (option.hasLongOption())
>  			length += 2 + strlen(option.name);
> @@ -127,7 +130,8 @@ void OptionsParser::usage()
>  
>  	indent = (indent + 7) / 8 * 8;
>  
> -	for (const Option &option : options_) {
> +	for (auto const &iter : optionsMap_) {
> +		const Option &option = iter.second;
>  		std::string argument;
>  		if (option.hasShortOption())
>  			argument = std::string("  -")
> diff --git a/src/cam/options.h b/src/cam/options.h
> index dfb7fcc9f6fa3324..cb7286a0a8005579 100644
> --- a/src/cam/options.h
> +++ b/src/cam/options.h
> @@ -57,8 +57,7 @@ private:
>  		bool hasLongOption() const { return name != nullptr; }
>  	};
>  
> -	std::vector<Option> options_;
> -	std::map<unsigned int, Option *> optionsMap_;
> +	std::map<unsigned int, Option> optionsMap_;

You can rename optionsMap_ to options_, it will simplify the patch a
bit.

>  };
>  
>  #endif /* __CAM_OPTIONS_H__ */

Patch

diff --git a/src/cam/options.cpp b/src/cam/options.cpp
index c9ca017b4cf3fa3d..d3bff1cd897a5cfb 100644
--- a/src/cam/options.cpp
+++ b/src/cam/options.cpp
@@ -30,8 +30,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 }));
-	optionsMap_[opt] = &options_.back();
+	optionsMap_[opt] = Option({ opt, name, argument, argumentName, help });
+
 	return true;
 }
 
@@ -43,14 +43,16 @@  OptionsParser::Options OptionsParser::parse(int argc, char **argv)
 	 * Allocate short and long options arrays large enough to contain all
 	 * options.
 	 */
-	char shortOptions[options_.size() * 3 + 2] = {};
-	struct option longOptions[options_.size() + 1] = {};
+	char shortOptions[optionsMap_.size() * 3 + 2] = {};
+	struct option longOptions[optionsMap_.size() + 1] = {};
 	unsigned int ids = 0;
 	unsigned int idl = 0;
 
 	shortOptions[ids++] = ':';
 
-	for (const Option &option : options_) {
+	for (auto const &iter : optionsMap_) {
+		const Option &option = iter.second;
+
 		if (option.hasShortOption()) {
 			shortOptions[ids++] = option.opt;
 			if (option.argument != ArgumentNone)
@@ -112,7 +114,8 @@  void OptionsParser::usage()
 
 	unsigned int indent = 0;
 
-	for (const Option &option : options_) {
+	for (auto const &iter : optionsMap_) {
+		const Option &option = iter.second;
 		unsigned int length = 14;
 		if (option.hasLongOption())
 			length += 2 + strlen(option.name);
@@ -127,7 +130,8 @@  void OptionsParser::usage()
 
 	indent = (indent + 7) / 8 * 8;
 
-	for (const Option &option : options_) {
+	for (auto const &iter : optionsMap_) {
+		const Option &option = iter.second;
 		std::string argument;
 		if (option.hasShortOption())
 			argument = std::string("  -")
diff --git a/src/cam/options.h b/src/cam/options.h
index dfb7fcc9f6fa3324..cb7286a0a8005579 100644
--- a/src/cam/options.h
+++ b/src/cam/options.h
@@ -57,8 +57,7 @@  private:
 		bool hasLongOption() const { return name != nullptr; }
 	};
 
-	std::vector<Option> options_;
-	std::map<unsigned int, Option *> optionsMap_;
+	std::map<unsigned int, Option> optionsMap_;
 };
 
 #endif /* __CAM_OPTIONS_H__ */