Skip to content

Commit 0ef4516

Browse files
extension instances and extension definitions can be extended
This was inspired by a patch from Bedrich (Ib0dfb68afaf0f74d3defe87b16b7c34457cc4899); I preserved the implementation, but I really wanted to document what is going on. Change-Id: I228430278de1cfa7ac192574d25e50cf157c70a1 Co-authored-by: Bedřich Schindler <[email protected]>
1 parent c92f06d commit 0ef4516

4 files changed

Lines changed: 51 additions & 1 deletion

File tree

include/libyang-cpp/Module.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ class LIBYANG_CPP_EXPORT ExtensionInstance {
165165
Module module() const;
166166
Extension definition() const;
167167
std::optional<std::string> argument() const;
168+
std::vector<ExtensionInstance> extensionInstances() const;
168169

169170
private:
170171
ExtensionInstance(const lysc_ext_instance* instance, std::shared_ptr<ly_ctx> ctx);
@@ -175,6 +176,7 @@ class LIBYANG_CPP_EXPORT ExtensionInstance {
175176
friend Module;
176177
friend Context;
177178
friend DataNode;
179+
friend Extension;
178180
friend SchemaNode;
179181
};
180182

@@ -187,6 +189,7 @@ class LIBYANG_CPP_EXPORT Extension {
187189
public:
188190
Module module() const;
189191
std::string name() const;
192+
std::vector<ExtensionInstance> extensionInstances() const;
190193

191194
private:
192195
Extension(const lysc_ext* def, std::shared_ptr<ly_ctx> ctx);

src/Module.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,20 @@ Extension ExtensionInstance::definition() const
427427
return Extension{m_instance->def, m_ctx};
428428
}
429429

430+
/**
431+
* @brief Returns instances of extensions which are extending this particular extensions instance
432+
*
433+
* Wraps `lysc_ext_instance::exts`.
434+
*/
435+
std::vector<ExtensionInstance> ExtensionInstance::extensionInstances() const
436+
{
437+
std::vector<ExtensionInstance> res;
438+
for (const auto& ext : std::span(m_instance->exts, LY_ARRAY_COUNT(m_instance->exts))) {
439+
res.emplace_back(ExtensionInstance{&ext, m_ctx});
440+
}
441+
return res;
442+
}
443+
430444
Extension::Extension(const lysc_ext* ext, std::shared_ptr<ly_ctx> ctx)
431445
: m_ext(ext)
432446
, m_ctx(ctx)
@@ -455,4 +469,18 @@ std::string Extension::name() const
455469
{
456470
return m_ext->name;
457471
}
472+
473+
/**
474+
* @brief Returns all extension instances which extend this extension definition
475+
*
476+
* Wraps `lysc_ext::exts`.
477+
*/
478+
std::vector<ExtensionInstance> Extension::extensionInstances() const
479+
{
480+
std::vector<ExtensionInstance> res;
481+
for (const auto& ext : std::span(m_ext->exts, LY_ARRAY_COUNT(m_ext->exts))) {
482+
res.emplace_back(ExtensionInstance{&ext, m_ctx});
483+
}
484+
return res;
485+
}
458486
}

tests/example_schema.hpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -762,8 +762,14 @@ module augmenting-extensions {
762762
import with-extensions {
763763
prefix "we";
764764
}
765+
extension another-annotation {
766+
we:annotation wtf-is-this;
767+
}
765768
augment "/we:c" {
766-
we:annotation last-modified;
769+
we:annotation last-modified {
770+
ae:another-annotation {
771+
}
772+
}
767773
}
768774
}
769775
)"s;

tests/schema_node.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,19 @@ TEST_CASE("SchemaNode")
374374
REQUIRE(elem.extensionInstances()[0].definition().module().name() == "with-extensions");
375375
REQUIRE(elem.extensionInstances()[0].definition().name() == "annotation");
376376
REQUIRE(elem.extensionInstances()[0].argument() == "last-modified");
377+
// a funny thing about an extension instance is that it can be also extended...
378+
REQUIRE(elem.extensionInstances()[0].extensionInstances().size() == 1);
379+
REQUIRE(elem.extensionInstances()[0].extensionInstances()[0].module().name() == "augmenting-extensions");
380+
REQUIRE(elem.extensionInstances()[0].extensionInstances()[0].definition().module().name() == "augmenting-extensions");
381+
REQUIRE(elem.extensionInstances()[0].extensionInstances()[0].definition().name() == "another-annotation");
382+
REQUIRE(!elem.extensionInstances()[0].extensionInstances()[0].argument());
383+
// ...and of course extension definitions are no exception and can be extended as well, yay!
384+
REQUIRE(elem.extensionInstances()[0].extensionInstances()[0].definition().extensionInstances().size() == 1);
385+
REQUIRE(elem.extensionInstances()[0].extensionInstances()[0].definition().extensionInstances()[0].module().name() == "augmenting-extensions");
386+
REQUIRE(elem.extensionInstances()[0].extensionInstances()[0].definition().extensionInstances()[0].definition().module().name() == "with-extensions");
387+
REQUIRE(elem.extensionInstances()[0].extensionInstances()[0].definition().extensionInstances()[0].definition().name() == "annotation");
388+
REQUIRE(elem.extensionInstances()[0].extensionInstances()[0].definition().extensionInstances()[0].argument() == "wtf-is-this");
389+
// OK, enough with that. These are the "old" extensions from the original module pre-augmentation:
377390
REQUIRE(elem.extensionInstances()[1].module().name() == "with-extensions");
378391
REQUIRE(elem.extensionInstances()[1].definition().module().name() == "ietf-netconf-acm");
379392
REQUIRE(elem.extensionInstances()[1].definition().name() == "default-deny-write");

0 commit comments

Comments
 (0)