[{"id":38639,"web_url":"https://patchwork.libcamera.org/comment/38639/","msgid":"<80f5e0d8-f57f-440c-a023-b15c7af9cb3b@ideasonboard.com>","date":"2026-04-24T07:53:45","subject":"Re: [PATCH v3 18/37] libcamera: value_node: Support adding nested\n\tchildren in one operation","submitter":{"id":216,"url":"https://patchwork.libcamera.org/api/people/216/","name":"Barnabás Pőcze","email":"barnabas.pocze@ideasonboard.com"},"content":"2026. 04. 24. 1:00 keltezéssel, Laurent Pinchart írta:\n> The GlobalConfiguration class will need to add nested children to a\n> ValueNode. Add a new overload to the add() function for this purpose.\n> \n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> ---\n> Changes since v2:\n> \n> - Do not move child if node->add() fails\n> \n> Changes since v1:\n> \n> - Documentation improvements\n> - Replace NULL with nullptr\n> - Don't move child node if add fails\n> ---\n\nReviewed-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>\n\n\n>   include/libcamera/internal/value_node.h |  3 ++\n>   src/libcamera/value_node.cpp            | 58 +++++++++++++++++++++++++\n>   2 files changed, 61 insertions(+)\n> \n> diff --git a/include/libcamera/internal/value_node.h b/include/libcamera/internal/value_node.h\n> index da68a74c5e14..578413199df1 100644\n> --- a/include/libcamera/internal/value_node.h\n> +++ b/include/libcamera/internal/value_node.h\n> @@ -8,6 +8,7 @@\n> \n>   #pragma once\n> \n> +#include <initializer_list>\n>   #include <iterator>\n>   #include <map>\n>   #include <memory>\n> @@ -239,6 +240,8 @@ public:\n> \n>   \tValueNode *add(std::unique_ptr<ValueNode> &&child);\n>   \tValueNode *add(std::string key, std::unique_ptr<ValueNode> &&child);\n> +\tValueNode *add(std::initializer_list<std::string_view> path,\n> +\t\t       std::unique_ptr<ValueNode> &&child);\n> \n>   private:\n>   \tLIBCAMERA_DISABLE_COPY_AND_MOVE(ValueNode)\n> diff --git a/src/libcamera/value_node.cpp b/src/libcamera/value_node.cpp\n> index fbf9ac470359..3b4041b7bbf0 100644\n> --- a/src/libcamera/value_node.cpp\n> +++ b/src/libcamera/value_node.cpp\n> @@ -13,6 +13,8 @@\n>   #include <string>\n>   #include <vector>\n> \n> +#include <libcamera/base/log.h>\n> +#include <libcamera/base/span.h>\n>   #include <libcamera/base/utils.h>\n> \n>   /**\n> @@ -22,6 +24,8 @@\n> \n>   namespace libcamera {\n> \n> +LOG_DEFINE_CATEGORY(ValueNode)\n> +\n>   namespace {\n> \n>   /* Empty static ValueNode as a safe result for invalid operations */\n> @@ -539,4 +543,58 @@ ValueNode *ValueNode::add(std::string key, std::unique_ptr<ValueNode> &&child)\n>   \treturn list_.emplace_back(it->first, std::move(child)).value.get();\n>   }\n> \n> +/**\n> + * \\brief Add a child node at the given path\n> + * \\param[in] path The path\n> + * \\param[in] child The child node\n> + *\n> + * Add the \\a child node at the given \\a path starting at this node. Missing\n> + * nodes are created along the path. Nodes along the path must be empty (in\n> + * which case they are converted to the Type::Dictionary type), be a dictionary,\n> + * or be missing. Otherwise, the function returns a nullptr and the \\a child is\n> + * not modified.\n> + *\n> + * Path elements are unique in the context of a parent node. If a child with the\n> + * same \\a key already exist at the end of the path, the function returns a\n> + * nullptr and the \\a child is not modified.\n> + *\n> + * \\note Any node added along the \\a path will remain even if this function\n> + * returns a failure.\n> + *\n> + * \\return A pointer to the \\a child node if successfully added, nullptr\n> + * otherwise\n> + */\n> +ValueNode *ValueNode::add(std::initializer_list<std::string_view> path,\n> +\t\t\t  std::unique_ptr<ValueNode> &&child)\n> +{\n> +\tif (!path.size())\n> +\t\treturn nullptr;\n> +\n> +\tValueNode *node = this;\n> +\n> +\tfor (const auto [i, name] : utils::enumerate(path)) {\n> +\t\tauto iter = node->dictionary_.find(name);\n> +\t\tif (iter == node->dictionary_.end()) {\n> +\t\t\tstd::unique_ptr<ValueNode> obj;\n> +\n> +\t\t\tif (i < path.size() - 1)\n> +\t\t\t\tobj = std::make_unique<ValueNode>();\n> +\n> +\t\t\tnode = node->add(std::string{ name },\n> +\t\t\t\t\t obj ? std::move(obj) : std::move(child));\n> +\t\t\tif (!node) {\n> +\t\t\t\tSpan<const std::string_view> pathName{ std::data(path), i + 1 };\n> +\t\t\t\tLOG(ValueNode, Error)\n> +\t\t\t\t\t<< \"Failed to populate '\"\n> +\t\t\t\t\t<< utils::join(pathName, \"/\") << \"'\";\n> +\t\t\t\treturn nullptr;\n> +\t\t\t}\n> +\t\t} else {\n> +\t\t\tnode = iter->second;\n> +\t\t}\n> +\t}\n> +\n> +\treturn node;\n> +}\n> +\n>   } /* namespace libcamera */\n> --\n> Regards,\n> \n> Laurent Pinchart\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 84BA2BDCB5\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 24 Apr 2026 07:53:51 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 353A762F6E;\n\tFri, 24 Apr 2026 09:53:51 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id E3F9062CE6\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 24 Apr 2026 09:53:48 +0200 (CEST)","from [192.168.33.62] (185.221.140.120.nat.pool.zt.hu\n\t[185.221.140.120])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 34A3B802;\n\tFri, 24 Apr 2026 09:52:09 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"KYUUpuEB\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1777017129;\n\tbh=I//Bv8gmH3z7/d5tg+ZnoEkjO6bhJwPYpo/cYkj89gk=;\n\th=Date:Subject:To:References:From:In-Reply-To:From;\n\tb=KYUUpuEBCvxWt7ucS+T4dtfr5/o9wihHLFB8p9ZD3dgpXHxUs0Ozr1AvjSbSdtpsk\n\tGk0GmHionsgorZMQeEksIdm3qgjhuB2Z2AP30O/JzfZU6/3hIJlNtvjp1Qp/7d43eX\n\tKrIXPFktQ/6Qrprdt7OOM+WGyirleq5B9pAbPqv4=","Message-ID":"<80f5e0d8-f57f-440c-a023-b15c7af9cb3b@ideasonboard.com>","Date":"Fri, 24 Apr 2026 09:53:45 +0200","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH v3 18/37] libcamera: value_node: Support adding nested\n\tchildren in one operation","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","References":"<20260423230059.3180987-1-laurent.pinchart@ideasonboard.com>\n\t<THcgUSzRGLf6eCahexU9447YOzALVPN9ef3pBpkt_Xyhi0jQvl9oXXAIkmdkL198046-tO003QUQ3u3fdAeX6Q==@protonmail.internalid>\n\t<20260423230059.3180987-19-laurent.pinchart@ideasonboard.com>","From":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>","Content-Language":"en-US, hu-HU","In-Reply-To":"<20260423230059.3180987-19-laurent.pinchart@ideasonboard.com>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"8bit","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]