From 922686067a2d610a93072cc9bbd3d9758087f4d1 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 13 Jun 2024 02:31:07 +0300 Subject: libcamera: yaml_parser: Delegate YamlObject::get() to helper structure 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) 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 Reviewed-by: Paul Elder Reviewed-by: Kieran Bingham --- 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 81cc0e25..06a41146 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 - std::optional get() const; + std::optional get() const + { + return Getter{}.get(*this); + } template T get(U &&defaultValue) const @@ -199,6 +202,8 @@ public: private: LIBCAMERA_DISABLE_COPY_AND_MOVE(YamlObject) + template + friend struct Getter; friend class YamlParserContext; enum class Type { @@ -207,6 +212,11 @@ private: Value, }; + template + struct Getter { + std::optional 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 b68a44c1..56670ba7 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 YamlObject::get() const +std::optional +YamlObject::Getter::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 YamlObject::get() const +std::optional +YamlObject::Getter::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::min(), + if (!parseSignedInteger(obj.value_, std::numeric_limits::min(), std::numeric_limits::max(), &value)) return std::nullopt; @@ -197,14 +199,15 @@ std::optional YamlObject::get() const } template<> -std::optional YamlObject::get() const +std::optional +YamlObject::Getter::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::max(), + if (!parseUnsignedInteger(obj.value_, std::numeric_limits::max(), &value)) return std::nullopt; @@ -212,14 +215,15 @@ std::optional YamlObject::get() const } template<> -std::optional YamlObject::get() const +std::optional +YamlObject::Getter::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::min(), + if (!parseSignedInteger(obj.value_, std::numeric_limits::min(), std::numeric_limits::max(), &value)) return std::nullopt; @@ -227,14 +231,15 @@ std::optional YamlObject::get() const } template<> -std::optional YamlObject::get() const +std::optional +YamlObject::Getter::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::max(), + if (!parseUnsignedInteger(obj.value_, std::numeric_limits::max(), &value)) return std::nullopt; @@ -242,14 +247,15 @@ std::optional YamlObject::get() const } template<> -std::optional YamlObject::get() const +std::optional +YamlObject::Getter::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::min(), + if (!parseSignedInteger(obj.value_, std::numeric_limits::min(), std::numeric_limits::max(), &value)) return std::nullopt; @@ -257,14 +263,15 @@ std::optional YamlObject::get() const } template<> -std::optional YamlObject::get() const +std::optional +YamlObject::Getter::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::max(), + if (!parseUnsignedInteger(obj.value_, std::numeric_limits::max(), &value)) return std::nullopt; @@ -272,18 +279,19 @@ std::optional YamlObject::get() const } template<> -std::optional YamlObject::get() const +std::optional +YamlObject::Getter::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 YamlObject::get() const } template<> -std::optional YamlObject::get() const +std::optional +YamlObject::Getter::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 YamlObject::get() const +std::optional +YamlObject::Getter::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(); + auto width = obj.list_[0].value->get(); if (!width) return std::nullopt; - auto height = list_[1].value->get(); + auto height = obj.list_[1].value->get(); if (!height) return std::nullopt; -- cgit v1.2.1