Message ID | 20220727084052.590421-2-fsylvestre@baylibre.com |
---|---|
State | Accepted |
Headers | show |
Series |
|
Related | show |
Hi Florian, On Wed, Jul 27, 2022 at 10:40:48AM +0200, Florian Sylvestre wrote: > Allow to retrieve a YAML list of any already supported types in a std::vector. > > Signed-off-by: Florian Sylvestre <fsylvestre@baylibre.com> > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> I've rebased this patch on top of "[PATCH v7 01/14] libcamera: yaml_parser: Replace ok flag to get() with std::optional". I'll send a v5 of your pending series rebased on top of that change. > --- > include/libcamera/internal/yaml_parser.h | 16 ++++++ > src/libcamera/yaml_parser.cpp | 66 ++++++++++++++++++++++++ > test/yaml-parser.cpp | 6 +++ > 3 files changed, 88 insertions(+) > > diff --git a/include/libcamera/internal/yaml_parser.h b/include/libcamera/internal/yaml_parser.h > index 064cf443..39161bbb 100644 > --- a/include/libcamera/internal/yaml_parser.h > +++ b/include/libcamera/internal/yaml_parser.h > @@ -167,6 +167,22 @@ public: > #endif > T get(const T &defaultValue, bool *ok = nullptr) const; > > +#ifndef __DOXYGEN__ > + template<typename T, > + typename std::enable_if_t< > + std::is_same_v<bool, T> || > + std::is_same_v<double, T> || > + std::is_same_v<int16_t, T> || > + std::is_same_v<uint16_t, T> || > + std::is_same_v<int32_t, T> || > + std::is_same_v<uint32_t, T> || > + std::is_same_v<std::string, T> || > + std::is_same_v<Size, T>> * = nullptr> > +#else > + template<typename T> > +#endif > + std::vector<T> getList(bool *ok = nullptr) const; > + > DictAdapter asDict() const { return DictAdapter{ dictionary_ }; } > ListAdapter asList() const { return ListAdapter{ list_ }; } > > diff --git a/src/libcamera/yaml_parser.cpp b/src/libcamera/yaml_parser.cpp > index 5c45e44e..125a348e 100644 > --- a/src/libcamera/yaml_parser.cpp > +++ b/src/libcamera/yaml_parser.cpp > @@ -325,6 +325,72 @@ Size YamlObject::get(const Size &defaultValue, bool *ok) const > > #endif /* __DOXYGEN__ */ > > +/** > + * \fn template<typename T> YamlObject::getList<T>(bool *ok) const > + * \brief Parse the YamlObject as a list of \a T > + * \param[out] ok The result of whether the parse succeeded > + * > + * This function parses the value of the YamlObject as a list of \a T objects, > + * and returns the value as a \a std::vector<T>. If parsing fails \a ok is set > + * to false and a default empty vector is returned. Otherwise, the > + * YamlObject list of values is returned, and \a ok is set to true. > + * > + * The \a ok pointer is optional and can be a nullptr if the caller doesn't > + * need to know if parsing succeeded. > + * > + * \return Value as a std::vector<T> type > + */ > + > +#ifndef __DOXYGEN__ > + > +template<typename T, > + typename std::enable_if_t< > + std::is_same_v<bool, T> || > + std::is_same_v<double, T> || > + std::is_same_v<int16_t, T> || > + std::is_same_v<uint16_t, T> || > + std::is_same_v<int32_t, T> || > + std::is_same_v<uint32_t, T> || > + std::is_same_v<std::string, T> || > + std::is_same_v<Size, T>> *> > +std::vector<T> YamlObject::getList(bool *ok) const > +{ > + setOk(ok, false); > + > + if (type_ != Type::List) > + return {}; > + > + std::vector<T> value; > + value.reserve(list_.size()); > + > + /* > + * Provide somme dummy defaultValue to get() function and rely on the > + * ok variable to know if the parsing was correct. > + */ > + T defaultValue{}; > + > + for (const YamlObject &entry : asList()) { > + bool result; > + value.emplace_back(entry.get<T>(defaultValue, &result)); > + if (!result) > + return {}; > + } > + > + setOk(ok, true); > + return value; > +} > + > +template std::vector<bool> YamlObject::getList<bool>(bool *ok) const; > +template std::vector<double> YamlObject::getList<double>(bool *ok) const; > +template std::vector<int16_t> YamlObject::getList<int16_t>(bool *ok) const; > +template std::vector<uint16_t> YamlObject::getList<uint16_t>(bool *ok) const; > +template std::vector<int32_t> YamlObject::getList<int32_t>(bool *ok) const; > +template std::vector<uint32_t> YamlObject::getList<uint32_t>(bool *ok) const; > +template std::vector<std::string> YamlObject::getList<std::string>(bool *ok) const; > +template std::vector<Size> YamlObject::getList<Size>(bool *ok) const; > + > +#endif /* __DOXYGEN__ */ > + > /** > * \fn YamlObject::asDict() const > * \brief Wrap a dictionary YamlObject in an adapter that exposes iterators > diff --git a/test/yaml-parser.cpp b/test/yaml-parser.cpp > index 38f84823..bb96a11b 100644 > --- a/test/yaml-parser.cpp > +++ b/test/yaml-parser.cpp > @@ -524,6 +524,12 @@ protected: > return TestFail; > } > > + std::vector<uint16_t> values = firstElement.getList<uint16_t>(); > + if (values.size() != 2 || values[0] != 1 || values[1] != 2) { > + cerr << "getList() failed to return correct vector" << std::endl; > + return TestFail; > + } > + > auto &secondElement = level2Obj[1]; > if (!secondElement.isDictionary() || > !secondElement.contains("one") ||
diff --git a/include/libcamera/internal/yaml_parser.h b/include/libcamera/internal/yaml_parser.h index 064cf443..39161bbb 100644 --- a/include/libcamera/internal/yaml_parser.h +++ b/include/libcamera/internal/yaml_parser.h @@ -167,6 +167,22 @@ public: #endif T get(const T &defaultValue, bool *ok = nullptr) const; +#ifndef __DOXYGEN__ + template<typename T, + typename std::enable_if_t< + std::is_same_v<bool, T> || + std::is_same_v<double, T> || + std::is_same_v<int16_t, T> || + std::is_same_v<uint16_t, T> || + std::is_same_v<int32_t, T> || + std::is_same_v<uint32_t, T> || + std::is_same_v<std::string, T> || + std::is_same_v<Size, T>> * = nullptr> +#else + template<typename T> +#endif + std::vector<T> getList(bool *ok = nullptr) const; + DictAdapter asDict() const { return DictAdapter{ dictionary_ }; } ListAdapter asList() const { return ListAdapter{ list_ }; } diff --git a/src/libcamera/yaml_parser.cpp b/src/libcamera/yaml_parser.cpp index 5c45e44e..125a348e 100644 --- a/src/libcamera/yaml_parser.cpp +++ b/src/libcamera/yaml_parser.cpp @@ -325,6 +325,72 @@ Size YamlObject::get(const Size &defaultValue, bool *ok) const #endif /* __DOXYGEN__ */ +/** + * \fn template<typename T> YamlObject::getList<T>(bool *ok) const + * \brief Parse the YamlObject as a list of \a T + * \param[out] ok The result of whether the parse succeeded + * + * This function parses the value of the YamlObject as a list of \a T objects, + * and returns the value as a \a std::vector<T>. If parsing fails \a ok is set + * to false and a default empty vector is returned. Otherwise, the + * YamlObject list of values is returned, and \a ok is set to true. + * + * The \a ok pointer is optional and can be a nullptr if the caller doesn't + * need to know if parsing succeeded. + * + * \return Value as a std::vector<T> type + */ + +#ifndef __DOXYGEN__ + +template<typename T, + typename std::enable_if_t< + std::is_same_v<bool, T> || + std::is_same_v<double, T> || + std::is_same_v<int16_t, T> || + std::is_same_v<uint16_t, T> || + std::is_same_v<int32_t, T> || + std::is_same_v<uint32_t, T> || + std::is_same_v<std::string, T> || + std::is_same_v<Size, T>> *> +std::vector<T> YamlObject::getList(bool *ok) const +{ + setOk(ok, false); + + if (type_ != Type::List) + return {}; + + std::vector<T> value; + value.reserve(list_.size()); + + /* + * Provide somme dummy defaultValue to get() function and rely on the + * ok variable to know if the parsing was correct. + */ + T defaultValue{}; + + for (const YamlObject &entry : asList()) { + bool result; + value.emplace_back(entry.get<T>(defaultValue, &result)); + if (!result) + return {}; + } + + setOk(ok, true); + return value; +} + +template std::vector<bool> YamlObject::getList<bool>(bool *ok) const; +template std::vector<double> YamlObject::getList<double>(bool *ok) const; +template std::vector<int16_t> YamlObject::getList<int16_t>(bool *ok) const; +template std::vector<uint16_t> YamlObject::getList<uint16_t>(bool *ok) const; +template std::vector<int32_t> YamlObject::getList<int32_t>(bool *ok) const; +template std::vector<uint32_t> YamlObject::getList<uint32_t>(bool *ok) const; +template std::vector<std::string> YamlObject::getList<std::string>(bool *ok) const; +template std::vector<Size> YamlObject::getList<Size>(bool *ok) const; + +#endif /* __DOXYGEN__ */ + /** * \fn YamlObject::asDict() const * \brief Wrap a dictionary YamlObject in an adapter that exposes iterators diff --git a/test/yaml-parser.cpp b/test/yaml-parser.cpp index 38f84823..bb96a11b 100644 --- a/test/yaml-parser.cpp +++ b/test/yaml-parser.cpp @@ -524,6 +524,12 @@ protected: return TestFail; } + std::vector<uint16_t> values = firstElement.getList<uint16_t>(); + if (values.size() != 2 || values[0] != 1 || values[1] != 2) { + cerr << "getList() failed to return correct vector" << std::endl; + return TestFail; + } + auto &secondElement = level2Obj[1]; if (!secondElement.isDictionary() || !secondElement.contains("one") ||