[PATCH 02/11] libcamera: yaml_parser: Delegate YamlObject::get() to helper structure
Kieran Bingham
kieran.bingham at ideasonboard.com
Thu Jun 13 13:38:54 CEST 2024
Quoting Laurent Pinchart (2024-06-13 02:39:35)
> The YamlObject::get() function is a function template that gets fully
> specialized for various types. This works fine for non-template types,
> but specializing it for template types (e.g. a std::vector<U>) would
> require partial template specialization, which C++ allows for classes
> and variables but not functions.
>
> To work around this problem, delegate the implementation to a new
> YamlObject::Getter structure template, which will support partial
> specialization.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> ---
> include/libcamera/internal/yaml_parser.h | 12 +++-
> src/libcamera/yaml_parser.cpp | 78 +++++++++++++-----------
> 2 files changed, 55 insertions(+), 35 deletions(-)
>
> diff --git a/include/libcamera/internal/yaml_parser.h b/include/libcamera/internal/yaml_parser.h
> index 81cc0e25ae0f..06a41146ad01 100644
> --- a/include/libcamera/internal/yaml_parser.h
> +++ b/include/libcamera/internal/yaml_parser.h
> @@ -162,7 +162,10 @@ public:
> std::size_t size() const;
>
> template<typename T>
> - std::optional<T> get() const;
> + std::optional<T> get() const
> + {
> + return Getter<T>{}.get(*this);
> + }
Aha, this is the magic I missed on my first pass. I was curious how we
were changing all these fucntions to now need an object, and I couldn't
see core changes not passing it in - but it comes from here.
Ok so that's neat - and means nothing else is impacted during the
transition...
It all falls into place:
Reviewed-by: Kieran Bingham <kieran.bingham at ideasonboard.com>
>
> template<typename T, typename U>
> T get(U &&defaultValue) const
> @@ -199,6 +202,8 @@ public:
> private:
> LIBCAMERA_DISABLE_COPY_AND_MOVE(YamlObject)
>
> + template<typename T>
> + friend struct Getter;
> friend class YamlParserContext;
>
> enum class Type {
> @@ -207,6 +212,11 @@ private:
> Value,
> };
>
> + template<typename T>
> + struct Getter {
> + std::optional<T> get(const YamlObject &obj) const;
> + };
> +
> Type type_;
>
> std::string value_;
> diff --git a/src/libcamera/yaml_parser.cpp b/src/libcamera/yaml_parser.cpp
> index b68a44c15c35..56670ba7a584 100644
> --- a/src/libcamera/yaml_parser.cpp
> +++ b/src/libcamera/yaml_parser.cpp
> @@ -118,14 +118,15 @@ std::size_t YamlObject::size() const
> #ifndef __DOXYGEN__
>
> template<>
> -std::optional<bool> YamlObject::get() const
> +std::optional<bool>
> +YamlObject::Getter<bool>::get(const YamlObject &obj) const
> {
> - if (type_ != Type::Value)
> + if (obj.type_ != Type::Value)
> return std::nullopt;
>
> - if (value_ == "true")
> + if (obj.value_ == "true")
> return true;
> - else if (value_ == "false")
> + else if (obj.value_ == "false")
> return false;
>
> return std::nullopt;
> @@ -182,14 +183,15 @@ bool parseUnsignedInteger(const std::string &str, unsigned long max,
> } /* namespace */
>
> template<>
> -std::optional<int8_t> YamlObject::get() const
> +std::optional<int8_t>
> +YamlObject::Getter<int8_t>::get(const YamlObject &obj) const
> {
> - if (type_ != Type::Value)
> + if (obj.type_ != Type::Value)
> return std::nullopt;
>
> long value;
>
> - if (!parseSignedInteger(value_, std::numeric_limits<int8_t>::min(),
> + if (!parseSignedInteger(obj.value_, std::numeric_limits<int8_t>::min(),
> std::numeric_limits<int8_t>::max(), &value))
> return std::nullopt;
>
> @@ -197,14 +199,15 @@ std::optional<int8_t> YamlObject::get() const
> }
>
> template<>
> -std::optional<uint8_t> YamlObject::get() const
> +std::optional<uint8_t>
> +YamlObject::Getter<uint8_t>::get(const YamlObject &obj) const
> {
> - if (type_ != Type::Value)
> + if (obj.type_ != Type::Value)
> return std::nullopt;
>
> unsigned long value;
>
> - if (!parseUnsignedInteger(value_, std::numeric_limits<uint8_t>::max(),
> + if (!parseUnsignedInteger(obj.value_, std::numeric_limits<uint8_t>::max(),
> &value))
> return std::nullopt;
>
> @@ -212,14 +215,15 @@ std::optional<uint8_t> YamlObject::get() const
> }
>
> template<>
> -std::optional<int16_t> YamlObject::get() const
> +std::optional<int16_t>
> +YamlObject::Getter<int16_t>::get(const YamlObject &obj) const
> {
> - if (type_ != Type::Value)
> + if (obj.type_ != Type::Value)
> return std::nullopt;
>
> long value;
>
> - if (!parseSignedInteger(value_, std::numeric_limits<int16_t>::min(),
> + if (!parseSignedInteger(obj.value_, std::numeric_limits<int16_t>::min(),
> std::numeric_limits<int16_t>::max(), &value))
> return std::nullopt;
>
> @@ -227,14 +231,15 @@ std::optional<int16_t> YamlObject::get() const
> }
>
> template<>
> -std::optional<uint16_t> YamlObject::get() const
> +std::optional<uint16_t>
> +YamlObject::Getter<uint16_t>::get(const YamlObject &obj) const
> {
> - if (type_ != Type::Value)
> + if (obj.type_ != Type::Value)
> return std::nullopt;
>
> unsigned long value;
>
> - if (!parseUnsignedInteger(value_, std::numeric_limits<uint16_t>::max(),
> + if (!parseUnsignedInteger(obj.value_, std::numeric_limits<uint16_t>::max(),
> &value))
> return std::nullopt;
>
> @@ -242,14 +247,15 @@ std::optional<uint16_t> YamlObject::get() const
> }
>
> template<>
> -std::optional<int32_t> YamlObject::get() const
> +std::optional<int32_t>
> +YamlObject::Getter<int32_t>::get(const YamlObject &obj) const
> {
> - if (type_ != Type::Value)
> + if (obj.type_ != Type::Value)
> return std::nullopt;
>
> long value;
>
> - if (!parseSignedInteger(value_, std::numeric_limits<int32_t>::min(),
> + if (!parseSignedInteger(obj.value_, std::numeric_limits<int32_t>::min(),
> std::numeric_limits<int32_t>::max(), &value))
> return std::nullopt;
>
> @@ -257,14 +263,15 @@ std::optional<int32_t> YamlObject::get() const
> }
>
> template<>
> -std::optional<uint32_t> YamlObject::get() const
> +std::optional<uint32_t>
> +YamlObject::Getter<uint32_t>::get(const YamlObject &obj) const
> {
> - if (type_ != Type::Value)
> + if (obj.type_ != Type::Value)
> return std::nullopt;
>
> unsigned long value;
>
> - if (!parseUnsignedInteger(value_, std::numeric_limits<uint32_t>::max(),
> + if (!parseUnsignedInteger(obj.value_, std::numeric_limits<uint32_t>::max(),
> &value))
> return std::nullopt;
>
> @@ -272,18 +279,19 @@ std::optional<uint32_t> YamlObject::get() const
> }
>
> template<>
> -std::optional<double> YamlObject::get() const
> +std::optional<double>
> +YamlObject::Getter<double>::get(const YamlObject &obj) const
> {
> - if (type_ != Type::Value)
> + if (obj.type_ != Type::Value)
> return std::nullopt;
>
> - if (value_ == "")
> + if (obj.value_ == "")
> return std::nullopt;
>
> char *end;
>
> errno = 0;
> - double value = utils::strtod(value_.c_str(), &end);
> + double value = utils::strtod(obj.value_.c_str(), &end);
>
> if ('\0' != *end || errno == ERANGE)
> return std::nullopt;
> @@ -292,28 +300,30 @@ std::optional<double> YamlObject::get() const
> }
>
> template<>
> -std::optional<std::string> YamlObject::get() const
> +std::optional<std::string>
> +YamlObject::Getter<std::string>::get(const YamlObject &obj) const
> {
> - if (type_ != Type::Value)
> + if (obj.type_ != Type::Value)
> return std::nullopt;
>
> - return value_;
> + return obj.value_;
> }
>
> template<>
> -std::optional<Size> YamlObject::get() const
> +std::optional<Size>
> +YamlObject::Getter<Size>::get(const YamlObject &obj) const
> {
> - if (type_ != Type::List)
> + if (obj.type_ != Type::List)
> return std::nullopt;
>
> - if (list_.size() != 2)
> + if (obj.list_.size() != 2)
> return std::nullopt;
>
> - auto width = list_[0].value->get<uint32_t>();
> + auto width = obj.list_[0].value->get<uint32_t>();
> if (!width)
> return std::nullopt;
>
> - auto height = list_[1].value->get<uint32_t>();
> + auto height = obj.list_[1].value->get<uint32_t>();
> if (!height)
> return std::nullopt;
>
> --
> Regards,
>
> Laurent Pinchart
>
More information about the libcamera-devel
mailing list