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);