[v3,07/37] libcamera: yaml_parser: Add functions to add children
diff mbox series

Message ID 20260423230059.3180987-8-laurent.pinchart@ideasonboard.com
State Accepted
Headers show
Series
  • libcamera: Global configuration file improvements
Related show

Commit Message

Laurent Pinchart April 23, 2026, 11 p.m. UTC
Add YamlObject::add() functions to add children to a list or dictionary
object. This will be used by the YamlParserContext to replace direct
access to YamlObject member variables to decouple the two classes.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Isaac Scott <isaac.scott@ideasonboard.com>
---
Changes since v2:

- Fix typo in documentation

Changes since v1:

- Avoid std::map lookup before insertion in YamlObject::add()
- Don't move child node if add fails
---
 include/libcamera/internal/yaml_parser.h |  5 ++-
 src/libcamera/yaml_parser.cpp            | 55 ++++++++++++++++++++++++
 2 files changed, 59 insertions(+), 1 deletion(-)

Comments

Pőcze Barnabás April 24, 2026, 7:52 a.m. UTC | #1
2026. 04. 24. 1:00 keltezéssel, Laurent Pinchart írta:
> Add YamlObject::add() functions to add children to a list or dictionary
> object. This will be used by the YamlParserContext to replace direct
> access to YamlObject member variables to decouple the two classes.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Reviewed-by: Isaac Scott <isaac.scott@ideasonboard.com>
> ---
> Changes since v2:
> 
> - Fix typo in documentation
> 
> Changes since v1:
> 
> - Avoid std::map lookup before insertion in YamlObject::add()
> - Don't move child node if add fails
> ---

Reviewed-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>


>   include/libcamera/internal/yaml_parser.h |  5 ++-
>   src/libcamera/yaml_parser.cpp            | 55 ++++++++++++++++++++++++
>   2 files changed, 59 insertions(+), 1 deletion(-)
> 
> diff --git a/include/libcamera/internal/yaml_parser.h b/include/libcamera/internal/yaml_parser.h
> index 0666762308ac..3be61c503c88 100644
> --- a/include/libcamera/internal/yaml_parser.h
> +++ b/include/libcamera/internal/yaml_parser.h
> @@ -28,7 +28,7 @@ class YamlObject
>   {
>   private:
>   	struct Value {
> -		Value(std::string &&k, std::unique_ptr<YamlObject> &&v)
> +		Value(std::string k, std::unique_ptr<YamlObject> &&v)
>   			: key(std::move(k)), value(std::move(v))
>   		{
>   		}
> @@ -197,6 +197,9 @@ public:
>   	bool contains(std::string_view key) const;
>   	const YamlObject &operator[](std::string_view key) const;
> 
> +	YamlObject *add(std::unique_ptr<YamlObject> &&child);
> +	YamlObject *add(std::string key, std::unique_ptr<YamlObject> &&child);
> +
>   private:
>   	LIBCAMERA_DISABLE_COPY_AND_MOVE(YamlObject)
> 
> diff --git a/src/libcamera/yaml_parser.cpp b/src/libcamera/yaml_parser.cpp
> index 8c84f560ff0f..5b2e743ee41a 100644
> --- a/src/libcamera/yaml_parser.cpp
> +++ b/src/libcamera/yaml_parser.cpp
> @@ -436,6 +436,61 @@ const YamlObject &YamlObject::operator[](std::string_view key) const
>   	return *iter->second;
>   }
> 
> +/**
> + * \brief Add a child object to a list
> + * \param[in] child The child object
> + *
> + * Append the \a child object as the last element of this object's children
> + * list. This object must be empty, in which case it is converted to the
> + * Type::List type, or be a list. Otherwise, the function returns a nullptr and
> + * the \a child is not modified.
> + *
> + * \return A pointer to the child object if successfully added, nullptr
> + * otherwise
> + */
> +YamlObject *YamlObject::add(std::unique_ptr<YamlObject> &&child)
> +{
> +	if (type_ == Type::Empty)
> +		type_ = Type::List;
> +
> +	if (type_ != Type::List)
> +		return nullptr;
> +
> +	Value &elem = list_.emplace_back(std::string{}, std::move(child));
> +	return elem.value.get();
> +}
> +
> +/**
> + * \brief Add a child object to a dictionary
> + * \param[in] key The dictionary key
> + * \param[in] child The child object
> + *
> + * Add the \a child object with the given \a key to this object's children. This
> + * object must be empty, in which case it is converted to the Type::Dictionary
> + * type, or be a dictionary. Otherwise, the function returns a nullptr and the
> + * \a child is not modified.
> + *
> + * Keys are unique. If a child with the same \a key already exists, the function
> + * returns a nullptr and the \a child is not modified.
> + *
> + * \return A pointer to the child object if successfully added, nullptr
> + * otherwise
> + */
> +YamlObject *YamlObject::add(std::string key, std::unique_ptr<YamlObject> &&child)
> +{
> +	if (type_ == Type::Empty)
> +		type_ = Type::Dictionary;
> +
> +	if (type_ != Type::Dictionary)
> +		return nullptr;
> +
> +	auto [it, inserted] = dictionary_.try_emplace(std::move(key), child.get());
> +	if (!inserted)
> +		return nullptr;
> +
> +	return list_.emplace_back(it->first, std::move(child)).value.get();
> +}
> +
>   #ifndef __DOXYGEN__
> 
>   class YamlParserContext
> --
> Regards,
> 
> Laurent Pinchart
>

Patch
diff mbox series

diff --git a/include/libcamera/internal/yaml_parser.h b/include/libcamera/internal/yaml_parser.h
index 0666762308ac..3be61c503c88 100644
--- a/include/libcamera/internal/yaml_parser.h
+++ b/include/libcamera/internal/yaml_parser.h
@@ -28,7 +28,7 @@  class YamlObject
 {
 private:
 	struct Value {
-		Value(std::string &&k, std::unique_ptr<YamlObject> &&v)
+		Value(std::string k, std::unique_ptr<YamlObject> &&v)
 			: key(std::move(k)), value(std::move(v))
 		{
 		}
@@ -197,6 +197,9 @@  public:
 	bool contains(std::string_view key) const;
 	const YamlObject &operator[](std::string_view key) const;
 
+	YamlObject *add(std::unique_ptr<YamlObject> &&child);
+	YamlObject *add(std::string key, std::unique_ptr<YamlObject> &&child);
+
 private:
 	LIBCAMERA_DISABLE_COPY_AND_MOVE(YamlObject)
 
diff --git a/src/libcamera/yaml_parser.cpp b/src/libcamera/yaml_parser.cpp
index 8c84f560ff0f..5b2e743ee41a 100644
--- a/src/libcamera/yaml_parser.cpp
+++ b/src/libcamera/yaml_parser.cpp
@@ -436,6 +436,61 @@  const YamlObject &YamlObject::operator[](std::string_view key) const
 	return *iter->second;
 }
 
+/**
+ * \brief Add a child object to a list
+ * \param[in] child The child object
+ *
+ * Append the \a child object as the last element of this object's children
+ * list. This object must be empty, in which case it is converted to the
+ * Type::List type, or be a list. Otherwise, the function returns a nullptr and
+ * the \a child is not modified.
+ *
+ * \return A pointer to the child object if successfully added, nullptr
+ * otherwise
+ */
+YamlObject *YamlObject::add(std::unique_ptr<YamlObject> &&child)
+{
+	if (type_ == Type::Empty)
+		type_ = Type::List;
+
+	if (type_ != Type::List)
+		return nullptr;
+
+	Value &elem = list_.emplace_back(std::string{}, std::move(child));
+	return elem.value.get();
+}
+
+/**
+ * \brief Add a child object to a dictionary
+ * \param[in] key The dictionary key
+ * \param[in] child The child object
+ *
+ * Add the \a child object with the given \a key to this object's children. This
+ * object must be empty, in which case it is converted to the Type::Dictionary
+ * type, or be a dictionary. Otherwise, the function returns a nullptr and the
+ * \a child is not modified.
+ *
+ * Keys are unique. If a child with the same \a key already exists, the function
+ * returns a nullptr and the \a child is not modified.
+ *
+ * \return A pointer to the child object if successfully added, nullptr
+ * otherwise
+ */
+YamlObject *YamlObject::add(std::string key, std::unique_ptr<YamlObject> &&child)
+{
+	if (type_ == Type::Empty)
+		type_ = Type::Dictionary;
+
+	if (type_ != Type::Dictionary)
+		return nullptr;
+
+	auto [it, inserted] = dictionary_.try_emplace(std::move(key), child.get());
+	if (!inserted)
+		return nullptr;
+
+	return list_.emplace_back(it->first, std::move(child)).value.get();
+}
+
 #ifndef __DOXYGEN__
 
 class YamlParserContext