Skip to content

Commit

Permalink
Wrap lyd_compare_single and lyd_compare_siblings
Browse files Browse the repository at this point in the history
Bug: #19
Change-Id: I5c48212a90cc4b538fa6582a5682a3b52b88785f
  • Loading branch information
jktjkt committed Jan 19, 2024
1 parent 6672c88 commit 1af87af
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 0 deletions.
3 changes: 3 additions & 0 deletions include/libyang-cpp/DataNode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ class LIBYANG_CPP_EXPORT DataNode {
const std::optional<ParseOptions> parseOpts = std::nullopt,
const std::optional<ValidationOptions> validationOpts = std::nullopt);

bool isEqual(const libyang::DataNode& other, const DataCompare flags=DataCompare::NoOptions) const;
bool siblingsEqual(const libyang::DataNode& other, const DataCompare flags=DataCompare::NoOptions) const;

friend Context;
friend DataNodeAny;
friend Set<DataNode>;
Expand Down
15 changes: 15 additions & 0 deletions include/libyang-cpp/Enum.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,16 @@ enum class SchemaPrintFlags : uint32_t {
Shrink = 0x02,
};

/**
* @brief Wraps LYD_COMPARE_* flags.
*/
enum class DataCompare : uint32_t {
NoOptions = 0x00, /**< Equivalent of a raw C 0 to say "no flags given" in a typesafe manner */
DistinguishExplicitDefaults = 0x02, /**< LYD_COMPARE_DEFAULTS */
FullRecursion = 0x01, /**< LYD_COMPARE_FULL_RECURSION*/
OpaqueAsData = 0x04, /**< LYD_COMPARE_OPAQ */
};

template <typename Enum>
constexpr Enum implEnumBitOr(const Enum a, const Enum b)
{
Expand Down Expand Up @@ -331,6 +341,11 @@ constexpr SchemaPrintFlags operator|(const SchemaPrintFlags a, const SchemaPrint
return implEnumBitOr(a, b);
}

constexpr DataCompare operator|(const DataCompare a, const DataCompare b)
{
return implEnumBitOr(a, b);
}

LIBYANG_CPP_EXPORT std::ostream& operator<<(std::ostream& os, const NodeType& type);
LIBYANG_CPP_EXPORT std::ostream& operator<<(std::ostream& os, const ErrorCode& err);
LIBYANG_CPP_EXPORT std::ostream& operator<<(std::ostream& os, const ValidationErrorCode& err);
Expand Down
36 changes: 36 additions & 0 deletions src/DataNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1223,4 +1223,40 @@ void DataNode::parseSubtree(
throwIfError(ret, "DataNode::parseSubtree: lyd_parse_data failed");
}

/**
* @short Compare a single node, possibly recusrively, possibly across contexts.
*
* Wraps `lyd_compare_single()`.
*/
bool DataNode::isEqual(const libyang::DataNode& other, const DataCompare flags) const
{
auto res = lyd_compare_single(m_node, other.m_node, utils::toDataCompareOptions(flags));
switch (res) {
case LY_SUCCESS:
return true;
case LY_ENOT:
return false;
default:
throwError(res, "lyd_compare_single");
}
}

/**
* @short Compare a node along its siblings, possibly recursively, possibly across contexts.
*
* Wraps `lyd_compare_siblings()`.
*/
bool DataNode::siblingsEqual(const libyang::DataNode& other, const DataCompare flags) const
{
auto res = lyd_compare_siblings(m_node, other.m_node, utils::toDataCompareOptions(flags));
switch (res) {
case LY_SUCCESS:
return true;
case LY_ENOT:
return false;
default:
throwError(res, "lyd_compare_single");
}
}

}
10 changes: 10 additions & 0 deletions src/utils/enum.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,4 +262,14 @@ constexpr uint32_t toSchemaPrintFlags(const SchemaPrintFlags flags)
static_assert(toSchemaPrintFlags(SchemaPrintFlags::Shrink) == LYS_PRINT_SHRINK);
static_assert(toSchemaPrintFlags(SchemaPrintFlags::NoSubStatements) == LYS_PRINT_NO_SUBSTMT);
static_assert(toSchemaPrintFlags(SchemaPrintFlags::Shrink | SchemaPrintFlags::NoSubStatements) == (LYS_PRINT_SHRINK | LYS_PRINT_NO_SUBSTMT));

constexpr uint32_t toDataCompareOptions(const DataCompare flags)
{
return static_cast<uint32_t>(flags);
}
static_assert(toDataCompareOptions(DataCompare::DistinguishExplicitDefaults) == LYD_COMPARE_DEFAULTS);
static_assert(toDataCompareOptions(DataCompare::FullRecursion) == LYD_COMPARE_FULL_RECURSION);
static_assert(toDataCompareOptions(DataCompare::OpaqueAsData) == LYD_COMPARE_OPAQ);
static_assert(toDataCompareOptions(DataCompare::FullRecursion | DataCompare::NoOptions) == LYD_COMPARE_FULL_RECURSION);
static_assert(toDataCompareOptions(DataCompare::DistinguishExplicitDefaults | DataCompare::FullRecursion | DataCompare::OpaqueAsData) == (LYD_COMPARE_DEFAULTS | LYD_COMPARE_FULL_RECURSION | LYD_COMPARE_OPAQ));
}
34 changes: 34 additions & 0 deletions tests/data_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2116,6 +2116,40 @@ TEST_CASE("Data Node manipulation")
}
}
}

DOCTEST_SUBCASE("comparing") {
libyang::Context ctxB(std::nullopt, libyang::ContextOptions::NoYangLibrary | libyang::ContextOptions::DisableSearchCwd);
ctxB.parseModule(example_schema, libyang::SchemaFormat::YANG);

// Differences from `data2`:
// - `/example-schema:leafInt8` is missing
// - `/example-schema:first/second/third/fourth/fifth` has a different value
const auto fifth666 = R"({
"example-schema:first": {
"second": {
"third": {
"fourth": {
"fifth": "666"
}
}
}
}
}
)"s;

auto rootA = ctx.parseData(data2, libyang::DataFormat::JSON);
auto rootB = ctxB.parseData(data2, libyang::DataFormat::JSON);
auto rootC = ctxB.parseData(fifth666, libyang::DataFormat::JSON);

auto secondA = *rootA->findPath("/example-schema:first/second");
auto secondB = *rootB->findPath("/example-schema:first/second");
auto secondC = *rootC->findPath("/example-schema:first/second");
REQUIRE(secondA.isEqual(secondB));
REQUIRE(secondA.siblingsEqual(secondB));
REQUIRE(secondA.isEqual(secondC));
REQUIRE(!secondA.siblingsEqual(secondC));
REQUIRE(!secondA.isEqual(secondC, libyang::DataCompare::FullRecursion));
}
}

TEST_CASE("union data types")
Expand Down

0 comments on commit 1af87af

Please sign in to comment.