| Message ID | 20260423230059.3180987-19-laurent.pinchart@ideasonboard.com |
|---|---|
| State | Accepted |
| Headers | show |
| Series |
|
| Related | show |
2026. 04. 24. 1:00 keltezéssel, Laurent Pinchart írta: > The GlobalConfiguration class will need to add nested children to a > ValueNode. Add a new overload to the add() function for this purpose. > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > --- > Changes since v2: > > - Do not move child if node->add() fails > > Changes since v1: > > - Documentation improvements > - Replace NULL with nullptr > - Don't move child node if add fails > --- Reviewed-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> > include/libcamera/internal/value_node.h | 3 ++ > src/libcamera/value_node.cpp | 58 +++++++++++++++++++++++++ > 2 files changed, 61 insertions(+) > > diff --git a/include/libcamera/internal/value_node.h b/include/libcamera/internal/value_node.h > index da68a74c5e14..578413199df1 100644 > --- a/include/libcamera/internal/value_node.h > +++ b/include/libcamera/internal/value_node.h > @@ -8,6 +8,7 @@ > > #pragma once > > +#include <initializer_list> > #include <iterator> > #include <map> > #include <memory> > @@ -239,6 +240,8 @@ public: > > ValueNode *add(std::unique_ptr<ValueNode> &&child); > ValueNode *add(std::string key, std::unique_ptr<ValueNode> &&child); > + ValueNode *add(std::initializer_list<std::string_view> path, > + std::unique_ptr<ValueNode> &&child); > > private: > LIBCAMERA_DISABLE_COPY_AND_MOVE(ValueNode) > diff --git a/src/libcamera/value_node.cpp b/src/libcamera/value_node.cpp > index fbf9ac470359..3b4041b7bbf0 100644 > --- a/src/libcamera/value_node.cpp > +++ b/src/libcamera/value_node.cpp > @@ -13,6 +13,8 @@ > #include <string> > #include <vector> > > +#include <libcamera/base/log.h> > +#include <libcamera/base/span.h> > #include <libcamera/base/utils.h> > > /** > @@ -22,6 +24,8 @@ > > namespace libcamera { > > +LOG_DEFINE_CATEGORY(ValueNode) > + > namespace { > > /* Empty static ValueNode as a safe result for invalid operations */ > @@ -539,4 +543,58 @@ ValueNode *ValueNode::add(std::string key, std::unique_ptr<ValueNode> &&child) > return list_.emplace_back(it->first, std::move(child)).value.get(); > } > > +/** > + * \brief Add a child node at the given path > + * \param[in] path The path > + * \param[in] child The child node > + * > + * Add the \a child node at the given \a path starting at this node. Missing > + * nodes are created along the path. Nodes along the path must be empty (in > + * which case they are converted to the Type::Dictionary type), be a dictionary, > + * or be missing. Otherwise, the function returns a nullptr and the \a child is > + * not modified. > + * > + * Path elements are unique in the context of a parent node. If a child with the > + * same \a key already exist at the end of the path, the function returns a > + * nullptr and the \a child is not modified. > + * > + * \note Any node added along the \a path will remain even if this function > + * returns a failure. > + * > + * \return A pointer to the \a child node if successfully added, nullptr > + * otherwise > + */ > +ValueNode *ValueNode::add(std::initializer_list<std::string_view> path, > + std::unique_ptr<ValueNode> &&child) > +{ > + if (!path.size()) > + return nullptr; > + > + ValueNode *node = this; > + > + for (const auto [i, name] : utils::enumerate(path)) { > + auto iter = node->dictionary_.find(name); > + if (iter == node->dictionary_.end()) { > + std::unique_ptr<ValueNode> obj; > + > + if (i < path.size() - 1) > + obj = std::make_unique<ValueNode>(); > + > + node = node->add(std::string{ name }, > + obj ? std::move(obj) : std::move(child)); > + if (!node) { > + Span<const std::string_view> pathName{ std::data(path), i + 1 }; > + LOG(ValueNode, Error) > + << "Failed to populate '" > + << utils::join(pathName, "/") << "'"; > + return nullptr; > + } > + } else { > + node = iter->second; > + } > + } > + > + return node; > +} > + > } /* namespace libcamera */ > -- > Regards, > > Laurent Pinchart >
diff --git a/include/libcamera/internal/value_node.h b/include/libcamera/internal/value_node.h index da68a74c5e14..578413199df1 100644 --- a/include/libcamera/internal/value_node.h +++ b/include/libcamera/internal/value_node.h @@ -8,6 +8,7 @@ #pragma once +#include <initializer_list> #include <iterator> #include <map> #include <memory> @@ -239,6 +240,8 @@ public: ValueNode *add(std::unique_ptr<ValueNode> &&child); ValueNode *add(std::string key, std::unique_ptr<ValueNode> &&child); + ValueNode *add(std::initializer_list<std::string_view> path, + std::unique_ptr<ValueNode> &&child); private: LIBCAMERA_DISABLE_COPY_AND_MOVE(ValueNode) diff --git a/src/libcamera/value_node.cpp b/src/libcamera/value_node.cpp index fbf9ac470359..3b4041b7bbf0 100644 --- a/src/libcamera/value_node.cpp +++ b/src/libcamera/value_node.cpp @@ -13,6 +13,8 @@ #include <string> #include <vector> +#include <libcamera/base/log.h> +#include <libcamera/base/span.h> #include <libcamera/base/utils.h> /** @@ -22,6 +24,8 @@ namespace libcamera { +LOG_DEFINE_CATEGORY(ValueNode) + namespace { /* Empty static ValueNode as a safe result for invalid operations */ @@ -539,4 +543,58 @@ ValueNode *ValueNode::add(std::string key, std::unique_ptr<ValueNode> &&child) return list_.emplace_back(it->first, std::move(child)).value.get(); } +/** + * \brief Add a child node at the given path + * \param[in] path The path + * \param[in] child The child node + * + * Add the \a child node at the given \a path starting at this node. Missing + * nodes are created along the path. Nodes along the path must be empty (in + * which case they are converted to the Type::Dictionary type), be a dictionary, + * or be missing. Otherwise, the function returns a nullptr and the \a child is + * not modified. + * + * Path elements are unique in the context of a parent node. If a child with the + * same \a key already exist at the end of the path, the function returns a + * nullptr and the \a child is not modified. + * + * \note Any node added along the \a path will remain even if this function + * returns a failure. + * + * \return A pointer to the \a child node if successfully added, nullptr + * otherwise + */ +ValueNode *ValueNode::add(std::initializer_list<std::string_view> path, + std::unique_ptr<ValueNode> &&child) +{ + if (!path.size()) + return nullptr; + + ValueNode *node = this; + + for (const auto [i, name] : utils::enumerate(path)) { + auto iter = node->dictionary_.find(name); + if (iter == node->dictionary_.end()) { + std::unique_ptr<ValueNode> obj; + + if (i < path.size() - 1) + obj = std::make_unique<ValueNode>(); + + node = node->add(std::string{ name }, + obj ? std::move(obj) : std::move(child)); + if (!node) { + Span<const std::string_view> pathName{ std::data(path), i + 1 }; + LOG(ValueNode, Error) + << "Failed to populate '" + << utils::join(pathName, "/") << "'"; + return nullptr; + } + } else { + node = iter->second; + } + } + + return node; +} + } /* namespace libcamera */
The GlobalConfiguration class will need to add nested children to a ValueNode. Add a new overload to the add() function for this purpose. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> --- Changes since v2: - Do not move child if node->add() fails Changes since v1: - Documentation improvements - Replace NULL with nullptr - Don't move child node if add fails --- include/libcamera/internal/value_node.h | 3 ++ src/libcamera/value_node.cpp | 58 +++++++++++++++++++++++++ 2 files changed, 61 insertions(+)