Port to libyang-cpp and sysrepo-cpp API change to std::string
Change-Id: I9e683e0ab3a5db696c35699d22cf1cb982c8ceda
Depends-on: https://gerrit.cesnet.cz/c/CzechLight/dependencies/+/5564
diff --git a/src/libyang_utils.cpp b/src/libyang_utils.cpp
index f3881fe..b09454e 100644
--- a/src/libyang_utils.cpp
+++ b/src/libyang_utils.cpp
@@ -123,9 +123,9 @@
libyang::DataNode treeToRpcInput(libyang::Context ctx, const std::string& path, DatastoreAccess::Tree in)
{
- auto root = ctx.newPath(path.c_str(), nullptr, libyang::CreationOptions::Update);
+ auto root = ctx.newPath(path, std::nullopt, libyang::CreationOptions::Update);
for (const auto& [k, v] : in) {
- root.newPath(k.c_str(), leafDataToString(v).c_str(), libyang::CreationOptions::Update);
+ root.newPath(k, leafDataToString(v), libyang::CreationOptions::Update);
}
return root;
diff --git a/src/netconf_access.cpp b/src/netconf_access.cpp
index 0c25cc8..a3d30ba 100644
--- a/src/netconf_access.cpp
+++ b/src/netconf_access.cpp
@@ -59,7 +59,7 @@
}
NetconfAccess::NetconfAccess(const std::string& hostname, uint16_t port, const std::string& user, const std::string& pubKey, const std::string& privKey)
- : m_context(nullptr, libyang::ContextOptions::SetPrivParsed)
+ : m_context(std::nullopt, libyang::ContextOptions::SetPrivParsed)
, m_session(libnetconf::client::Session::connectPubkey(hostname, port, user, pubKey, privKey, m_context))
, m_schema(std::make_shared<YangSchema>(m_context))
{
@@ -67,7 +67,7 @@
}
NetconfAccess::NetconfAccess(const int source, const int sink)
- : m_context(nullptr, libyang::ContextOptions::SetPrivParsed)
+ : m_context(std::nullopt, libyang::ContextOptions::SetPrivParsed)
, m_session(libnetconf::client::Session::connectFd(source, sink, m_context))
, m_schema(std::make_shared<YangSchema>(m_context))
{
@@ -82,7 +82,7 @@
}
NetconfAccess::NetconfAccess(const std::string& socketPath)
- : m_context(nullptr, libyang::ContextOptions::SetPrivParsed)
+ : m_context(std::nullopt, libyang::ContextOptions::SetPrivParsed)
, m_session(libnetconf::client::Session::connectSocket(socketPath, m_context))
, m_schema(std::make_shared<YangSchema>(m_context))
{
@@ -151,16 +151,16 @@
void NetconfAccess::moveItem(const std::string& source, std::variant<yang::move::Absolute, yang::move::Relative> move)
{
auto nodes = m_schema->dataNodeFromPath(source);
- auto sourceNode = *(nodes.createdNode->findPath(source.c_str()));
+ auto sourceNode = *(nodes.createdNode->findPath(source));
auto yangModule = *m_schema->getYangModule("yang");
- sourceNode.newMeta(yangModule, "insert", toYangInsert(move).c_str());
+ sourceNode.newMeta(yangModule, "insert", toYangInsert(move));
if (std::holds_alternative<yang::move::Relative>(move)) {
auto relative = std::get<yang::move::Relative>(move);
if (m_schema->nodeType(source) == yang::NodeTypes::LeafList) {
- sourceNode.newMeta(yangModule, "value", leafDataToString(relative.m_path.at(".")).c_str());
+ sourceNode.newMeta(yangModule, "value", leafDataToString(relative.m_path.at(".")));
} else {
- sourceNode.newMeta(yangModule, "key", instanceToString(relative.m_path, std::string{nodes.createdNode->schema().module().name()}).c_str());
+ sourceNode.newMeta(yangModule, "key", instanceToString(relative.m_path, std::string{nodes.createdNode->schema().module().name()}));
}
}
doEditFromDataNode(sourceNode);
@@ -222,15 +222,15 @@
std::vector<ListInstance> NetconfAccess::listInstances(const std::string& path)
{
std::vector<ListInstance> res;
- auto keys = m_session->libyangContext().findXPath(path.c_str()).front().asList().keys();
- auto nodes = m_session->libyangContext().newPath2(path.c_str(), nullptr, libyang::CreationOptions::Opaque);
+ auto keys = m_session->libyangContext().findXPath(path).front().asList().keys();
+ auto nodes = m_session->libyangContext().newPath2(path, std::nullopt, libyang::CreationOptions::Opaque);
// Here we create a tree with "selection leafs" for all they keys of our wanted list. These leafs tell NETCONF, that
// we only want the list's keys and not any other data.
for (const auto& keyLeaf : keys) {
// Selection leafs need to be inserted directly to the list using relative paths, that's why `newNode` is used
// here.
- nodes.createdNode->newPath(keyLeaf.name().data(), nullptr, libyang::CreationOptions::Opaque);
+ nodes.createdNode->newPath(keyLeaf.name().data(), std::nullopt, libyang::CreationOptions::Opaque);
}
// Have to use `newParent` in case our wanted list is a nested list. With `newNode` I would only send the inner
@@ -241,7 +241,7 @@
return res;
}
- for (const auto& instance : instances->findXPath(path.c_str())) {
+ for (const auto& instance : instances->findXPath(path)) {
ListInstance instanceRes;
for (const auto& keyLeaf : instance.child()->siblings()) {
diff --git a/src/sysrepo_access.cpp b/src/sysrepo_access.cpp
index 34d255a..34e0388 100644
--- a/src/sysrepo_access.cpp
+++ b/src/sysrepo_access.cpp
@@ -74,7 +74,7 @@
try {
m_session.switchDatastore(targetToDs_get(m_target));
- auto config = m_session.getData(((path == "/") ? "/*" : path).c_str());
+ auto config = m_session.getData((path == "/") ? "/*" : path);
if (config) {
lyNodesToTree(res, config->siblings());
}
@@ -89,7 +89,7 @@
try {
m_session.switchDatastore(targetToDs_set(m_target));
auto lyValue = value.type() == typeid(empty_) ? "" : leafDataToString(value);
- m_session.setItem(path.c_str(), lyValue.c_str(), sysrepo::EditOptions::Isolate);
+ m_session.setItem(path, lyValue, sysrepo::EditOptions::Isolate);
} catch (sysrepo::Error& ex) {
reportErrors();
}
@@ -99,7 +99,7 @@
{
try {
m_session.switchDatastore(targetToDs_set(m_target));
- m_session.setItem(path.c_str(), nullptr);
+ m_session.setItem(path, std::nullopt);
} catch (sysrepo::Error& ex) {
reportErrors();
}
@@ -112,7 +112,7 @@
// not supported.
// https://github.com/sysrepo/sysrepo/issues/1967#issuecomment-625085090
m_session.switchDatastore(targetToDs_set(m_target));
- m_session.deleteItem(path.c_str(), sysrepo::EditOptions::Isolate);
+ m_session.deleteItem(path, sysrepo::EditOptions::Isolate);
} catch (sysrepo::Error& ex) {
reportErrors();
}
@@ -146,7 +146,7 @@
}
}
m_session.switchDatastore(targetToDs_set(m_target));
- m_session.moveItem(source.c_str(), toSrMoveOp(move), destination.c_str());
+ m_session.moveItem(source, toSrMoveOp(move), destination);
}
void SysrepoAccess::commitChanges()
@@ -180,7 +180,7 @@
void SysrepoAccess::copyConfig(const Datastore source, const Datastore destination)
{
m_session.switchDatastore(toSrDatastore(destination));
- m_session.copyConfig(toSrDatastore(source), nullptr, OPERATION_TIMEOUT_MS);
+ m_session.copyConfig(toSrDatastore(source), std::nullopt, OPERATION_TIMEOUT_MS);
}
std::shared_ptr<Schema> SysrepoAccess::schema()
@@ -206,12 +206,12 @@
std::vector<ListInstance> SysrepoAccess::listInstances(const std::string& path)
{
std::vector<ListInstance> res;
- auto lists = m_session.getData(path.c_str());
+ auto lists = m_session.getData(path);
if (!lists) {
return res;
}
- auto instances = lists->findXPath(path.c_str());
+ auto instances = lists->findXPath(path);
if (instances.empty()) {
return res;
}
diff --git a/src/yang_access.cpp b/src/yang_access.cpp
index 7fd9010..6c18779 100644
--- a/src/yang_access.cpp
+++ b/src/yang_access.cpp
@@ -16,7 +16,7 @@
}
YangAccess::YangAccess()
- : m_ctx(nullptr, libyang::ContextOptions::DisableSearchCwd | libyang::ContextOptions::SetPrivParsed)
+ : m_ctx(std::nullopt, libyang::ContextOptions::DisableSearchCwd | libyang::ContextOptions::SetPrivParsed)
, m_datastore(std::nullopt)
, m_schema(std::make_shared<YangSchema>(m_ctx))
{
@@ -45,9 +45,9 @@
{
try {
if (m_datastore) {
- m_datastore->newPath(path.c_str(), value ? value->c_str() : nullptr, libyang::CreationOptions::Update);
+ m_datastore->newPath(path, value, libyang::CreationOptions::Update);
} else {
- m_datastore = m_ctx.newPath(path.c_str(), value ? value->c_str() : nullptr, libyang::CreationOptions::Update);
+ m_datastore = m_ctx.newPath(path, value, libyang::CreationOptions::Update);
}
} catch (libyang::Error&) {
getErrorsAndThrow();
@@ -82,7 +82,7 @@
// Otherwise the datastore just doesn't contain the wanted node.
throw DatastoreException{{DatastoreError{"Datastore is empty.", path}}};
}
- auto toRemove = m_datastore->findPath(path.c_str());
+ auto toRemove = m_datastore->findPath(path);
if (!toRemove) {
// Otherwise the datastore just doesn't contain the wanted node.
throw DatastoreException{{DatastoreError{"Data node doesn't exist.", path}}};
@@ -105,7 +105,7 @@
return res;
}
- auto set = m_datastore->findXPath(path == "/" ? "/*" : path.c_str());
+ auto set = m_datastore->findXPath(path == "/" ? "/*" : path);
lyNodesToTree(res, set);
return res;
@@ -134,7 +134,7 @@
void operator()(yang::move::Absolute absolute) const
{
- auto set = m_sourceNode.findXPath(m_sourceNode.schema().path().get().get());
+ auto set = m_sourceNode.findXPath(m_sourceNode.schema().path());
if (set.size() == 1) { // m_sourceNode is the sole instance, do nothing
return;
}
@@ -160,7 +160,7 @@
{
auto keySuffix = m_sourceNode.schema().nodeType() == libyang::NodeType::List ? instanceToString(relative.m_path)
: leafDataToString(relative.m_path.at("."));
- auto destNode = m_sourceNode.findSiblingVal(m_sourceNode.schema(), keySuffix.c_str());
+ auto destNode = m_sourceNode.findSiblingVal(m_sourceNode.schema(), keySuffix);
if (relative.m_position == yang::move::Relative::Position::After) {
destNode->insertAfter(m_sourceNode);
@@ -177,7 +177,7 @@
throw DatastoreException{{DatastoreError{"Datastore is empty.", source}}};
}
- auto sourceNode = m_datastore->findPath(source.c_str());
+ auto sourceNode = m_datastore->findPath(source);
if (!sourceNode) {
// The datastore doesn't contain the wanted node.
@@ -199,7 +199,7 @@
{
auto root = [&path, this] {
try {
- return m_ctx.newPath(path.c_str());
+ return m_ctx.newPath(path);
} catch (libyang::ErrorWithCode& err) {
getErrorsAndThrow();
}
@@ -211,7 +211,7 @@
}
try {
- root.newPath(k.c_str(), leafDataToString(v).c_str(), libyang::CreationOptions::Update);
+ root.newPath(k, leafDataToString(v), libyang::CreationOptions::Update);
} catch (libyang::ErrorWithCode& err) {
getErrorsAndThrow();
}
@@ -238,7 +238,7 @@
return res;
}
- auto instances = m_datastore->findXPath(path.c_str());
+ auto instances = m_datastore->findXPath(path);
for (const auto& list : instances) {
ListInstance instance;
for (const auto& child : list.child()->siblings()) {
@@ -297,7 +297,7 @@
std::cout << "Parsing \"" << path << "\" as " << (firstChar == '{' ? "JSON" : "XML") << "...\n";
auto dataNode = m_ctx.parseDataPath(
- path.c_str(),
+ path,
firstChar == '{' ? libyang::DataFormat::JSON : libyang::DataFormat::XML,
strict == StrictDataParsing::Yes ? std::optional{libyang::ParseOptions::Strict} : std::nullopt,
libyang::ValidationOptions::Present);
diff --git a/src/yang_schema.cpp b/src/yang_schema.cpp
index 1c2df80..5a31a49 100644
--- a/src/yang_schema.cpp
+++ b/src/yang_schema.cpp
@@ -32,7 +32,7 @@
};
YangSchema::YangSchema()
- : m_context(nullptr, libyang::ContextOptions::DisableSearchDirs | libyang::ContextOptions::SetPrivParsed)
+ : m_context(std::nullopt, libyang::ContextOptions::DisableSearchDirs | libyang::ContextOptions::SetPrivParsed)
{
}
@@ -60,7 +60,7 @@
bool YangSchema::isModule(const std::string& name) const
{
- return m_context.getModuleImplemented(name.c_str()).has_value();
+ return m_context.getModuleImplemented(name).has_value();
}
bool YangSchema::listHasKey(const schemaPath_& listPath, const std::string& key) const
@@ -86,14 +86,14 @@
//
// Also, we need to use findPath twice if we're trying to find output nodes.
try {
- return m_context.findPath(node.c_str());
+ return m_context.findPath(node);
} catch (libyang::ErrorWithCode& err) {
if (err.code() != libyang::ErrorCode::ValidationFailure) {
throw;
}
}
try {
- return m_context.findPath(node.c_str(), libyang::OutputNodes::Yes);
+ return m_context.findPath(node, libyang::OutputNodes::Yes);
} catch (libyang::ErrorWithCode& err) {
if (err.code() != libyang::ErrorCode::ValidationFailure) {
throw;
@@ -325,7 +325,7 @@
std::string topLevelModule;
if (path.type() == typeid(module_)) {
- nodeCollections.emplace_back(m_context.getModule(boost::get<module_>(path).m_name.c_str())->childInstantiables());
+ nodeCollections.emplace_back(m_context.getModule(boost::get<module_>(path).m_name)->childInstantiables());
} else {
auto schemaPath = anyPathToSchemaPath(path);
if (schemaPath.m_nodes.empty()) {
@@ -372,7 +372,7 @@
void YangSchema::loadModule(const std::string& moduleName)
{
- m_context.loadModule(moduleName.c_str());
+ m_context.loadModule(moduleName);
}
void YangSchema::setEnabledFeatures(const std::string& moduleName, const std::vector<std::string>& features)
@@ -389,16 +389,16 @@
}
}
-void YangSchema::registerModuleCallback(const std::function<std::string(const char*, const char*, const char*, const char*)>& clb)
+void YangSchema::registerModuleCallback(const std::function<std::string(const std::string_view, const std::optional<std::string_view>, const std::optional<std::string_view>, const std::optional<std::string_view>)>& clb)
{
- auto lambda = [clb](const char* mod_name, const char* mod_revision, const char* submod_name, const char* submod_revision) -> std::optional<libyang::ModuleInfo> {
+ auto lambda = [clb](const auto mod_name, const auto mod_revision, const auto submod_name, const auto submod_revision) -> std::optional<libyang::ModuleInfo> {
(void)submod_revision;
auto moduleSource = clb(mod_name, mod_revision, submod_name, submod_revision);
if (moduleSource.empty()) {
return std::nullopt;
}
return libyang::ModuleInfo {
- .data = moduleSource.c_str(),
+ .data = moduleSource,
.format = libyang::SchemaFormat::YANG
};
@@ -420,12 +420,12 @@
return std::optional<libyang::CreationOptions>{};
}();
- return m_context.newPath2(path.c_str(), value ? value->c_str() : nullptr, options);
+ return m_context.newPath2(path, value, options);
}
std::optional<libyang::Module> YangSchema::getYangModule(const std::string& name)
{
- return m_context.getModuleImplemented(name.c_str());
+ return m_context.getModuleImplemented(name);
}
namespace {
diff --git a/src/yang_schema.hpp b/src/yang_schema.hpp
index 82d9acf..fe5cf1c 100644
--- a/src/yang_schema.hpp
+++ b/src/yang_schema.hpp
@@ -42,7 +42,7 @@
[[nodiscard]] yang::Status status(const std::string& location) const override;
[[nodiscard]] bool hasInputNodes(const std::string& path) const override;
- void registerModuleCallback(const std::function<std::string(const char*, const char*, const char*, const char*)>& clb);
+ void registerModuleCallback(const std::function<std::string(const std::string_view, const std::optional<std::string_view>, const std::optional<std::string_view>, const std::optional<std::string_view>)>& clb);
/** @short Loads a module called moduleName. */
void loadModule(const std::string& moduleName);
diff --git a/submodules/dependencies b/submodules/dependencies
index f47525e..07f0bd8 160000
--- a/submodules/dependencies
+++ b/submodules/dependencies
@@ -1 +1 @@
-Subproject commit f47525e5878d57e748f066f8345d6437ae9c8bad
+Subproject commit 07f0bd86e8a12767e14ac5e3f51558e6d05e438a
diff --git a/tests/datastore_access.cpp b/tests/datastore_access.cpp
index 57871c0..1f8bb55 100644
--- a/tests/datastore_access.cpp
+++ b/tests/datastore_access.cpp
@@ -901,7 +901,7 @@
// `xpath` holds the subscription xpath which won't have list keys. We need the path with list keys and
// we'll find that in the input.
auto inputPath = input.findXPath("/example-schema:ports/shutdown").front().path();
- output.newPath(joinPaths(std::string{inputPath}, "success").c_str(), "true", libyang::CreationOptions::Output);
+ output.newPath(joinPaths(inputPath, "success"), "true", libyang::CreationOptions::Output);
return sysrepo::ErrorCode::Ok;
}
throw std::runtime_error("unrecognized RPC");
@@ -939,21 +939,21 @@
if (inputNode.path() == nukes + "/payload/kilotons") {
kilotons = std::get<uint64_t>(inputNode.asTerm().value());
- } else if (std::string_view{inputNode.path().get().get()}.find(nukes + "/cities") == 0) {
+ } else if (inputNode.path().find(nukes + "/cities") == 0) {
hasCities = true;
} else {
- throw std::runtime_error("RPC launch-nukes: unexpected input "s + inputNode.path().get().get());
+ throw std::runtime_error("RPC launch-nukes: unexpected input "s + inputNode.path());
}
}
if (kilotons == 333'666) {
// magic, just do not generate any output. This is important because the NETCONF RPC returns just <ok/>.
return sysrepo::ErrorCode::Ok;
}
- output.newPath((nukes + "/blast-radius").c_str(), "33666", libyang::CreationOptions::Output);
- output.newPath((nukes + "/actual-yield").c_str(), std::to_string(static_cast<uint64_t>(1.33 * kilotons)).c_str(), libyang::CreationOptions::Output);
+ output.newPath(nukes + "/blast-radius", "33666", libyang::CreationOptions::Output);
+ output.newPath(nukes + "/actual-yield", std::to_string(static_cast<uint64_t>(1.33 * kilotons)), libyang::CreationOptions::Output);
if (hasCities) {
- output.newPath((nukes + "/damaged-places/targets[city='London']/city").c_str(), "London", libyang::CreationOptions::Output);
- output.newPath((nukes + "/damaged-places/targets[city='Berlin']/city").c_str(), "Berlin", libyang::CreationOptions::Output);
+ output.newPath(nukes + "/damaged-places/targets[city='London']/city", "London", libyang::CreationOptions::Output);
+ output.newPath(nukes + "/damaged-places/targets[city='Berlin']/city", "Berlin", libyang::CreationOptions::Output);
}
return sysrepo::ErrorCode::Ok;
}
diff --git a/tests/mock/sysrepo_subscription.cpp b/tests/mock/sysrepo_subscription.cpp
index d4827bb..94d4c44 100644
--- a/tests/mock/sysrepo_subscription.cpp
+++ b/tests/mock/sysrepo_subscription.cpp
@@ -34,7 +34,7 @@
return sysrepo::ErrorCode::Ok;
}
- for (const auto& it : sess.getChanges(("/"s + module_name.data() + ":*//.").c_str())) {
+ for (const auto& it : sess.getChanges("/"s + module_name.data() + ":*//.")) {
auto xpath = it.node.path();
std::optional<std::string> oldValue;
std::optional<std::string> newValue;
@@ -72,7 +72,7 @@
SysrepoSubscription::SysrepoSubscription(const std::string& moduleName, Recorder* rec, sysrepo::Datastore ds)
: m_subscription([&moduleName, &rec, ds] { // This is an immediately invoked lambda.
- return sysrepo::Connection{}.sessionStart(ds).onModuleChange(moduleName.c_str(),
+ return sysrepo::Connection{}.sessionStart(ds).onModuleChange(moduleName,
rec ? sysrepo::ModuleChangeCb{MyCallback{moduleName, rec}}
: sysrepo::ModuleChangeCb{[](auto, auto, auto, auto, auto, auto) { return sysrepo::ErrorCode::Ok; }});
}())
@@ -97,9 +97,9 @@
auto data = m_dataSupplier.get_data(subXPath->data());
for (const auto& [p, v] : data) {
if (!output) {
- output = session.getContext().newPath(p.c_str(), v.type() == typeid(empty_) ? nullptr : leafDataToString(v).c_str());
+ output = session.getContext().newPath(p, v.type() == typeid(empty_) ? std::nullopt : std::optional<std::string>(leafDataToString(v)));
} else {
- output->newPath(p.c_str(), v.type() == typeid(empty_) ? nullptr : leafDataToString(v).c_str());
+ output->newPath(p, v.type() == typeid(empty_) ? std::nullopt : std::optional<std::string>(leafDataToString(v)));
}
}
return sysrepo::ErrorCode::Ok;
@@ -110,6 +110,6 @@
};
OperationalDataSubscription::OperationalDataSubscription(const std::string& moduleName, const std::string& path, const DataSupplier& dataSupplier)
- : m_subscription(sysrepo::Connection{}.sessionStart().onOperGet(moduleName.c_str(), OperationalDataCallback{dataSupplier}, path.c_str()))
+ : m_subscription(sysrepo::Connection{}.sessionStart().onOperGet(moduleName, OperationalDataCallback{dataSupplier}, path))
{
}
diff --git a/tests/utils.cpp b/tests/utils.cpp
index c24f4de..7d0af08 100644
--- a/tests/utils.cpp
+++ b/tests/utils.cpp
@@ -357,7 +357,7 @@
expectedLeafData = std::string{"Xaver"};
}
- auto leaf = dataNode->findPath(("/" + path).c_str());
+ auto leaf = dataNode->findPath("/" + path);
REQUIRE(leafValueFromNode(leaf->asTerm()) == expectedLeafData);
}
diff --git a/tests/yang.cpp b/tests/yang.cpp
index 205616c..2560f64 100644
--- a/tests/yang.cpp
+++ b/tests/yang.cpp
@@ -477,21 +477,19 @@
TEST_CASE("yangschema")
{
- using namespace std::string_literals;
- using namespace std::string_view_literals;
YangSchema ys;
- ys.registerModuleCallback([]([[maybe_unused]] auto modName, auto, auto subModule, auto) {
- if (modName != "example-schema"sv) {
- throw std::logic_error("unrecognized module "s + modName);
+ ys.registerModuleCallback([](const auto modName, auto, const auto subModule, auto) {
+ if (modName != "example-schema") {
+ throw std::logic_error("unrecognized module " + std::string{modName});
}
- if (subModule == nullptr) {
+ if (!subModule) {
return example_schema;
}
- if (subModule == "sub-module"sv) {
+ if (*subModule == "sub-module") {
return included_submodule;
}
- throw std::logic_error("unrecognized submodule "s + subModule);
+ throw std::logic_error("unrecognized submodule " + std::string{*subModule});
});
ys.addSchemaString(second_schema);
ys.addSchemaString(R"(