Skip to content

Commit

Permalink
Add Module::child(), Module::childrenDfs() and `Module::immediate…
Browse files Browse the repository at this point in the history
…Children()`

Those functions are implemented in the same manner as in `SchemaNode`
and allows to walk through modules children. This is counterpart to
already implemented `Module::childInstantiables()` that returns
instantiables schema nodes. These return all nodes, including
the schema-only nodes such as choice and case if end-user needs
to read its schema.

While the implementation is inspired by functions in `SchemaNode`,
imlementation of `Module::parent()` and `Module::siblings()` was omitted
as those do no make sense on `Module`.

Change-Id: I38c8374304f859d65343d04d08302e07deb05f27
  • Loading branch information
bedrich-schindler committed Jan 7, 2025
1 parent 01f2633 commit 32b200e
Show file tree
Hide file tree
Showing 6 changed files with 346 additions and 135 deletions.
1 change: 1 addition & 0 deletions include/libyang-cpp/Collection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class LIBYANG_CPP_EXPORT Collection {
public:
friend DataNode;
friend Iterator<NodeType, ITER_TYPE>;
friend Module;
friend SchemaNode;
~Collection();
Collection(const Collection<NodeType, ITER_TYPE>&);
Expand Down
5 changes: 5 additions & 0 deletions include/libyang-cpp/Module.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class ChildInstanstiables;
class Identity;
class SchemaNode;
class SubmoduleParsed;
template <typename NodeType, IterationType ITER_TYPE>
class Collection;

namespace types {
class IdentityRef;
Expand Down Expand Up @@ -86,7 +88,10 @@ class LIBYANG_CPP_EXPORT Module {

std::vector<Identity> identities() const;

std::optional<SchemaNode> child() const;
ChildInstanstiables childInstantiables() const;
libyang::Collection<SchemaNode, IterationType::Dfs> childrenDfs() const;
Collection<SchemaNode, IterationType::Sibling> immediateChildren() const;
std::vector<SchemaNode> actionRpcs() const;

std::string printStr(const SchemaOutputFormat format, const std::optional<SchemaPrintFlags> flags = std::nullopt, std::optional<size_t> lineLength = std::nullopt) const;
Expand Down
40 changes: 40 additions & 0 deletions src/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include <algorithm>
#include <libyang-cpp/ChildInstantiables.hpp>
#include <libyang-cpp/Collection.hpp>
#include <libyang-cpp/Module.hpp>
#include <libyang-cpp/Utils.hpp>
#include <libyang/libyang.h>
Expand Down Expand Up @@ -178,6 +179,23 @@ std::vector<Identity> Module::identities() const
return res;
}

/**
* @brief Returns the first child node of this module.
* @return The child, or std::nullopt if there are no children.
*/
std::optional<SchemaNode> Module::child() const
{
if (!m_module->implemented) {
throw Error{"Module::child: module is not implemented"};
}

if (!m_module->compiled->data) {
return std::nullopt;
}

return SchemaNode{m_module->compiled->data, m_ctx};
}

/**
* @brief Returns a collection of data instantiable top-level nodes of this module.
*
Expand All @@ -191,6 +209,28 @@ ChildInstanstiables Module::childInstantiables() const
return ChildInstanstiables{nullptr, m_module->compiled, m_ctx};
}

/**
* @brief Returns a collection for iterating depth-first over the subtree this module points to.
*/
Collection<SchemaNode, IterationType::Dfs> Module::childrenDfs() const
{
if (!m_module->implemented) {
throw Error{"Module::childrenDfs: module is not implemented"};
}
return Collection<SchemaNode, IterationType::Dfs>{m_module->compiled->data, m_ctx};
}

/**
* @brief Returns a collection for iterating over the immediate children of where this module points to.
*
* This is a convenience function for iterating over this->child().siblings() which does not throw even when module has no children.
*/
Collection<SchemaNode, IterationType::Sibling> Module::immediateChildren() const
{
auto c = child();
return c ? c->siblings() : Collection<SchemaNode, IterationType::Sibling>{nullptr, nullptr};
}

/**
* @brief Returns a collection of RPC nodes (not action nodes) as SchemaNode
*
Expand Down
5 changes: 5 additions & 0 deletions tests/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,11 @@ TEST_CASE("context")
+--rw anydataWithMandatoryChild anydata
+--rw anyxmlBasic? anyxml
+--rw anyxmlWithMandatoryChild anyxml
+--rw (choiceOnModule)?
| +--:(case1)
| | +--rw choiceOnModuleLeaf1? string
| +--:(case2)
| +--rw choiceOnModuleLeaf2? string
+--rw choiceBasicContainer
| +--rw (choiceBasic)?
| +--:(case1)
Expand Down
21 changes: 21 additions & 0 deletions tests/example_schema.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,19 @@ module type_module {
mandatory true;
}
choice choiceOnModule {
case case1 {
leaf choiceOnModuleLeaf1 {
type string;
}
}
case case2 {
leaf choiceOnModuleLeaf2 {
type string;
}
}
}
container choiceBasicContainer {
choice choiceBasic {
case case1 {
Expand Down Expand Up @@ -787,6 +800,14 @@ module type_module {
}
)"s;

const auto empty_module = R"(
module empty_module {
yang-version 1.1;
namespace "e";
prefix "e";
}
)"s;

const auto with_inet_types_module = R"(
module with-inet-types {
yang-version 1.1;
Expand Down
Loading

0 comments on commit 32b200e

Please sign in to comment.