[libcamera-devel] [PATCH] libcamera: utils: Add map_keys() function

Laurent Pinchart laurent.pinchart at ideasonboard.com
Thu Jun 25 16:17:34 CEST 2020


Hi Jacopo,

On Thu, Jun 25, 2020 at 09:47:21AM +0200, Jacopo Mondi wrote:
> Hi Laurent,
>    I still wonder why we don't have this in STL...

If you ever find an answer, I'll be interested to know :-)

> On Thu, Jun 25, 2020 at 04:23:35AM +0300, Laurent Pinchart wrote:
> > Add a map_keys() function to the utils namespace to extract keys from a
> > map.
> >
> > Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> > ---
> >  include/libcamera/internal/utils.h | 10 ++++++++++
> >  src/libcamera/utils.cpp            |  7 +++++++
> >  test/utils.cpp                     | 21 +++++++++++++++++++++
> >  3 files changed, 38 insertions(+)
> >
> > diff --git a/include/libcamera/internal/utils.h b/include/libcamera/internal/utils.h
> > index 0953423ee8d0..4fe4843922a9 100644
> > --- a/include/libcamera/internal/utils.h
> > +++ b/include/libcamera/internal/utils.h
> > @@ -11,6 +11,7 @@
> >  #include <chrono>
> >  #include <memory>
> >  #include <ostream>
> > +#include <set>
> >  #include <sstream>
> >  #include <string>
> >  #include <string.h>
> > @@ -36,6 +37,15 @@ const char *basename(const char *path);
> >  char *secure_getenv(const char *name);
> >  std::string dirname(const std::string &path);
> >
> > +template<typename T>
> > +std::set<typename T::key_type> map_keys(const T &map)
> 
> Keys are unique and sorted in maps, can't we return a vector ? Is this
> meant to support multimaps too ? If that's not desired, can we use
> std::map<class Key, T> as the template parameter ?
> 
> (To be honest, calling this on a multimap opens one question: do we
> want the -unique- keys, or all the keys ? The number of keys, if
> unique, would be less than the number of actual entries in the map...
> This makes me feel we want this for maps only)

I'd rather make this specific to std::map for now. Returning a vector
would make sense, and I think that's what I'd prefer. Maybe this is why
STL doesn't have a std::map::keys() method, they couldn't decide what
container it should return ;-)

> > +{
> > +	std::set<typename T::key_type> keys;
> > +	std::transform(map.begin(), map.end(), std::inserter(keys, keys.end()),
> > +		       [](const auto &value) { return value.first; });
> > +	return keys;
> > +}
> > +
> >  template<class InputIt1, class InputIt2>
> >  unsigned int set_overlap(InputIt1 first1, InputIt1 last1,
> >  			 InputIt2 first2, InputIt2 last2)
> > diff --git a/src/libcamera/utils.cpp b/src/libcamera/utils.cpp
> > index d55338fe681a..1eb8970a5bbc 100644
> > --- a/src/libcamera/utils.cpp
> > +++ b/src/libcamera/utils.cpp
> > @@ -127,6 +127,13 @@ std::string dirname(const std::string &path)
> >  	return path.substr(0, pos + 1);
> >  }
> >
> > +/**
> > + * \fn std::set<typename T::key_type> map_keys(const T &map)
> > + * \brief Retrieve the keys of a std::map<>
> > + * \param[in] map The map whose keys to retrieve
> > + * \return A std::set<> containing the keys of \a map
> > + */
> > +
> >  /**
> >   * \fn libcamera::utils::set_overlap(InputIt1 first1, InputIt1 last1,
> >   *				     InputIt2 first2, InputIt2 last2)
> > diff --git a/test/utils.cpp b/test/utils.cpp
> > index 66b91f1203e1..a9d072030f1c 100644
> > --- a/test/utils.cpp
> > +++ b/test/utils.cpp
> > @@ -6,6 +6,8 @@
> >   */
> >
> >  #include <iostream>
> > +#include <map>
> > +#include <set>
> >  #include <sstream>
> >  #include <string>
> >  #include <vector>
> > @@ -144,6 +146,25 @@ protected:
> >  		if (TestPass != testDirname())
> >  			return TestFail;
> >
> > +
> > +		/* utils::map_keys() test. */
> > +		const std::map<std::string, unsigned int> map{
> > +			{ "zero", 0 },
> > +			{ "one", 1 },
> > +			{ "two", 2 },
> > +		};
> > +		const std::set<std::string> expectedKeys{
> > +			"zero",
> > +			"one",
> > +			"two",
> > +		};
> 
> How are keys sorted here ?

std::map<> and std::set<> are sorted automatically. I think the test
should actually use a different order in the initializer list of
expectedKeys, just to show it gets sorted.

> > +
> > +		const std::set<std::string> keys = utils::map_keys(map);
> > +		if (keys != expectedKeys) {
> 
> This matches the sorting order of expectedKeys by chance ? I see
> std::set::operator== assuming lhs and rhs to be sorted equally
> 
> > +			cerr << "utils::map_keys() test failed" << endl;
> > +			return TestFail;
> > +		}
> > +
> >  		return TestPass;
> >  	}
> >  };

-- 
Regards,

Laurent Pinchart


More information about the libcamera-devel mailing list