[{"id":37600,"web_url":"https://patchwork.libcamera.org/comment/37600/","msgid":"<f284a0be-dd89-4a85-9bfd-5de2139cfef3@ideasonboard.com>","date":"2026-01-13T12:49:39","subject":"Re: [PATCH 30/36] libcamera: value_node: Support looking up 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. 01. 13. 1:08 keltezéssel, Laurent Pinchart írta:\n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> ---\n>   include/libcamera/internal/value_node.h |  1 +\n>   src/libcamera/value_node.cpp            | 23 +++++++++++++++++++++++\n>   2 files changed, 24 insertions(+)\n> \n> diff --git a/include/libcamera/internal/value_node.h b/include/libcamera/internal/value_node.h\n> index abb0991fd87e..da72651d2161 100644\n> --- a/include/libcamera/internal/value_node.h\n> +++ b/include/libcamera/internal/value_node.h\n> @@ -235,6 +235,7 @@ public:\n>   \tbool contains(std::string_view key) const;\n>   \tValueNode *at(std::string_view key);\n>   \tconst ValueNode &operator[](std::string_view key) const;\n> +\tconst ValueNode &operator[](std::initializer_list<std::string_view> path) const;\n>   \n>   \tValueNode *add(std::unique_ptr<ValueNode> child);\n>   \tValueNode *add(std::string key, std::unique_ptr<ValueNode> child);\n> diff --git a/src/libcamera/value_node.cpp b/src/libcamera/value_node.cpp\n> index 1256adf8361d..55d5a1a29991 100644\n> --- a/src/libcamera/value_node.cpp\n> +++ b/src/libcamera/value_node.cpp\n> @@ -487,6 +487,29 @@ const ValueNode &ValueNode::operator[](std::string_view key) const\n>   \treturn *iter->second;\n>   }\n>   \n> +/**\n> + * \\brief Retrieve a descendant node by path\n> + * \\param[in] path The path\n> + *\n> + * This function retrieves a descendant of a ValueNode by following a \\a path.\n> + * The path is a list of keys that index nested dictionary nodes. If any node\n> + * along the path is not a Dictionary node, an empty node is returned.\n> + *\n> + * \\return The ValueNode corresponding to the \\a path\n> + */\n> +const ValueNode &ValueNode::operator[](std::initializer_list<std::string_view> path) const\n> +{\n> +\tconst ValueNode *node = this;\n> +\n> +\tfor (const auto part : path) {\n\n   const auto &part\n\n\n> +\t\tnode = &(*node)[part];\n> +\t\tif (!*node)\n\nI feel like it would be nicer to have a const qualified `at()` as checking\nfor a nullptr is simpler that reading out the type and comparing it with `Type::Empty`.\n(At it would avoid the need for `&*`.) But in any case, it looks ok.\n\nReviewed-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>\n\n\n> +\t\t\treturn empty;\n> +\t}\n> +\n> +\treturn *node;\n> +}\n> +\n>   /**\n>    * \\brief Add a child node to a list\n>    * \\param[in] child The child node","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 9158BBE08B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 13 Jan 2026 12:49:45 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id D0BD961FA3;\n\tTue, 13 Jan 2026 13:49:44 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 7C4B661FA0\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 13 Jan 2026 13:49:43 +0100 (CET)","from [192.168.33.30] (185.221.143.114.nat.pool.zt.hu\n\t[185.221.143.114])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 70FF850A;\n\tTue, 13 Jan 2026 13:49:17 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"qNaK668Q\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1768308557;\n\tbh=8GctdR7DdZQZhTN4ZXutmuzmXPuk+udrtECiybogym8=;\n\th=Date:Subject:To:References:From:In-Reply-To:From;\n\tb=qNaK668Qv9R8h9i+ajRT0PPUV+2MZ+K4VZHkLj1Grm6iad3o7zo0XAR/wjr31rmMH\n\trYT4aJUyfcknaQbhYVWx2azT7UUfu6zBMgvKzVBhjvQQTJGSoJGjTgpm0X6hYL+Cag\n\tBgN30HRQFuUdvQ5hrRB3f/EMw+FP5USZNT5U5pVw=","Message-ID":"<f284a0be-dd89-4a85-9bfd-5de2139cfef3@ideasonboard.com>","Date":"Tue, 13 Jan 2026 13:49:39 +0100","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH 30/36] libcamera: value_node: Support looking up nested\n\tchildren in one operation","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","References":"<20260113000808.15395-1-laurent.pinchart@ideasonboard.com>\n\t<20260113000808.15395-31-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":"<20260113000808.15395-31-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>"}},{"id":37609,"web_url":"https://patchwork.libcamera.org/comment/37609/","msgid":"<20260113141339.GK6198@pendragon.ideasonboard.com>","date":"2026-01-13T14:13:39","subject":"Re: [PATCH 30/36] libcamera: value_node: Support looking up nested\n\tchildren in one operation","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"On Tue, Jan 13, 2026 at 01:49:39PM +0100, Barnabás Pőcze wrote:\n> 2026. 01. 13. 1:08 keltezéssel, Laurent Pinchart írta:\n> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> > ---\n> >   include/libcamera/internal/value_node.h |  1 +\n> >   src/libcamera/value_node.cpp            | 23 +++++++++++++++++++++++\n> >   2 files changed, 24 insertions(+)\n> > \n> > diff --git a/include/libcamera/internal/value_node.h b/include/libcamera/internal/value_node.h\n> > index abb0991fd87e..da72651d2161 100644\n> > --- a/include/libcamera/internal/value_node.h\n> > +++ b/include/libcamera/internal/value_node.h\n> > @@ -235,6 +235,7 @@ public:\n> >   \tbool contains(std::string_view key) const;\n> >   \tValueNode *at(std::string_view key);\n> >   \tconst ValueNode &operator[](std::string_view key) const;\n> > +\tconst ValueNode &operator[](std::initializer_list<std::string_view> path) const;\n> >   \n> >   \tValueNode *add(std::unique_ptr<ValueNode> child);\n> >   \tValueNode *add(std::string key, std::unique_ptr<ValueNode> child);\n> > diff --git a/src/libcamera/value_node.cpp b/src/libcamera/value_node.cpp\n> > index 1256adf8361d..55d5a1a29991 100644\n> > --- a/src/libcamera/value_node.cpp\n> > +++ b/src/libcamera/value_node.cpp\n> > @@ -487,6 +487,29 @@ const ValueNode &ValueNode::operator[](std::string_view key) const\n> >   \treturn *iter->second;\n> >   }\n> >   \n> > +/**\n> > + * \\brief Retrieve a descendant node by path\n> > + * \\param[in] path The path\n> > + *\n> > + * This function retrieves a descendant of a ValueNode by following a \\a path.\n> > + * The path is a list of keys that index nested dictionary nodes. If any node\n> > + * along the path is not a Dictionary node, an empty node is returned.\n> > + *\n> > + * \\return The ValueNode corresponding to the \\a path\n> > + */\n> > +const ValueNode &ValueNode::operator[](std::initializer_list<std::string_view> path) const\n> > +{\n> > +\tconst ValueNode *node = this;\n> > +\n> > +\tfor (const auto part : path) {\n> \n>    const auto &part\n> \n> > +\t\tnode = &(*node)[part];\n> > +\t\tif (!*node)\n> \n> I feel like it would be nicer to have a const qualified `at()` as checking\n> for a nullptr is simpler that reading out the type and comparing it with `Type::Empty`.\n> (At it would avoid the need for `&*`.) But in any case, it looks ok.\n\nYes, I'm not too happy with operator[]. It is kind of OK for this\nseries, but once we'll build something on top it may become clear that a\nnicer ValueNode API is needed. In particular, I'm thinking of allowing a\nnode to contain a value *and* child elements at the same time, as well\nas merging list and dictionaries together into a single type. Nothing\nwould change for YAML parsing as a YAML document wouldn't make use of\nthose features, but it would simplify error handling.\n\nI think we should decide on this when extending CameraManager::start()\nwith a parameter to specify configuration parameters (and the first\nquestion we'll have to ask then will be if ValueNode should be exposed\nto applications, or if we should pass the data in a different way)\n\n> Reviewed-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>\n> \n> > +\t\t\treturn empty;\n> > +\t}\n> > +\n> > +\treturn *node;\n> > +}\n> > +\n> >   /**\n> >    * \\brief Add a child node to a list\n> >    * \\param[in] child The child node\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 B23C6BE08B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 13 Jan 2026 14:14:02 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id A071E61FBC;\n\tTue, 13 Jan 2026 15:14:01 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id A82FA61FA0\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 13 Jan 2026 15:14:00 +0100 (CET)","from pendragon.ideasonboard.com (81-175-209-152.bb.dnainternet.fi\n\t[81.175.209.152])\n\tby perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id 5571250A;\n\tTue, 13 Jan 2026 15:13:34 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"gLxDJDKx\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1768313614;\n\tbh=X9ZgdMAxi1tBdJQbMfYQ9AHTxCzOmSLhJd0Q+aUt3Ck=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=gLxDJDKxrEkZ/muEH0MYdSyys8t3riCcKYuZGa2z5PtKHvAeAp12ZV5nrqw/1Ym/4\n\twpTiMZbrbW3EUsg6eFbYNoHLa15TiGY6M4dYDXvZrHYuaS/NzwQ+a2G27xwx4kJegi\n\tLdi37mlqjRy1JcwwvLCMi9TNoGRIU5hegAXBao/s=","Date":"Tue, 13 Jan 2026 16:13:39 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH 30/36] libcamera: value_node: Support looking up nested\n\tchildren in one operation","Message-ID":"<20260113141339.GK6198@pendragon.ideasonboard.com>","References":"<20260113000808.15395-1-laurent.pinchart@ideasonboard.com>\n\t<20260113000808.15395-31-laurent.pinchart@ideasonboard.com>\n\t<f284a0be-dd89-4a85-9bfd-5de2139cfef3@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<f284a0be-dd89-4a85-9bfd-5de2139cfef3@ideasonboard.com>","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>"}}]