diff --git a/cpp/src/srpcpp/common.cpp b/cpp/src/srpcpp/common.cpp index e99b131..86d9c0c 100644 --- a/cpp/src/srpcpp/common.cpp +++ b/cpp/src/srpcpp/common.cpp @@ -4,6 +4,19 @@ namespace srpc { + +/** + * @brief Escape special characters in the incoming string so that it can be used in a regular expression. + * + * @param s Incoming string + * @return std::string Escaped string + */ +static std::string EscapeForRegex(const std::string &s) +{ + static const std::regex meta_characters{R"([-[\]{}()*+?.\^$|\s])"}; + return std::regex_replace(s, meta_characters, R"(\$&)"); +} + /** * @brief Extracts the key from the list XPath. * @@ -18,7 +31,7 @@ const std::string extractListKeyFromXPath(const std::string &list, const std::st std::stringstream ss; - ss << list << "\\[" << key << "='([^']*)'\\]"; + ss << EscapeForRegex(list) << "\\[" << key << "='([^']*)'\\]"; const auto &xpath_expr = ss.str(); @@ -49,18 +62,18 @@ std::unordered_map extractListKeysFromXpath(const std: std::unordered_map keys_map; int starting_point = xpath.find(list + "["); - + std::string chunk(xpath.begin() + starting_point, xpath.end()); - + int ending_point = chunk.find("]/"); if(ending_point == std::string::npos){ //this means it can be last ending_point = chunk.find_last_of(']'); } - + chunk.erase(chunk.begin() + ending_point + 1, chunk.end()); - + int begin = chunk.find('['); int end = chunk.find(']'); // list is found, continue diff --git a/cpp/src/srpcpp/datastore.hpp b/cpp/src/srpcpp/datastore.hpp index ff4ede5..1057561 100644 --- a/cpp/src/srpcpp/datastore.hpp +++ b/cpp/src/srpcpp/datastore.hpp @@ -8,13 +8,29 @@ class IAssignedPaths { public: /** - * @brief Get the paths which the checker/applier is assigned for. + * @brief Get the paths which the initializer/checker/applier is assigned for. * * @return Assigned paths. */ virtual std::list getPaths() = 0; }; +/** + * @brief Interface used for applying datastore content to the system. + */ +class IDatastoreInitializer : public IAssignedPaths +{ + public: + /** + * @brief Initialize datastore content using the provided session. + * + * @note The datastore that's initialized is not necessarily the active datastore of @p session. + * + * @param session Session to use for retreiving datastore data. + */ + virtual void initializeDatastore(sysrepo::Session &session) = 0; +}; + /** * @brief Interface used for applying datastore content to the system. */ @@ -58,7 +74,13 @@ class IDatastoreChecker : public IAssignedPaths }; /** - * @brief Datastore checker concept for determining a valid datastore checker. + * @brief Datastore initializer concept for determining a valid datastore initializer. + */ +template +concept DatastoreValueInitializer = std::is_base_of::value; + +/** + * @brief Datastore applier concept for determining a valid datastore applier. */ template concept DatastoreValueApplier = std::is_base_of::value; diff --git a/cpp/src/srpcpp/module-registry.hpp b/cpp/src/srpcpp/module-registry.hpp index 2ab4d30..5f0e5d3 100644 --- a/cpp/src/srpcpp/module-registry.hpp +++ b/cpp/src/srpcpp/module-registry.hpp @@ -31,12 +31,22 @@ template class ModuleRegistry /** * Register a module. */ - template ModuleType> size_t registerModule(PluginContextType &plugin_ctx) + template ModuleType> size_t registerModule(PluginContextType &plugin_ctx, const std::string &module_name) { - m_modules.push_back(std::make_unique(plugin_ctx)); + m_modules.push_back(std::make_unique(plugin_ctx, module_name)); return m_modules.size() - 1; } + /** + * Unregister a module. + */ + void unregisterModule(const std::string &module_name) + { + std::erase_if(m_modules, [&module_name](const auto &module) { + return module->getName() == module_name; + }); + } + /** * Returns the list of registered modules. */ diff --git a/cpp/src/srpcpp/module.hpp b/cpp/src/srpcpp/module.hpp index a62ef7d..cd8498d 100644 --- a/cpp/src/srpcpp/module.hpp +++ b/cpp/src/srpcpp/module.hpp @@ -37,21 +37,6 @@ template class IModule return m_pluginContext; } - /** - * Return the operational context from the module. - */ - virtual std::shared_ptr getOperationalContext() = 0; - - /** - * Return the module changes context from the module. - */ - virtual std::shared_ptr getModuleChangesContext() = 0; - - /** - * Return the RPC context from the module. - */ - virtual std::shared_ptr getRpcContext() = 0; - /** * Get all operational callbacks which the module should use. */ @@ -67,6 +52,14 @@ template class IModule */ virtual std::list getRpcCallbacks() = 0; + /** + * Get all datastore initializers that this module provides. + */ + std::list> getDatastoreInitializers() + { + return m_datastore_initializers; + } + /** * Get all datastore value checkers that this module provides. */ @@ -96,23 +89,32 @@ template class IModule } protected: + /** + * @brief Add a datastore initializer to the module. + */ + template void addDatastoreInitializer(std::shared_ptr& initializer) + { + m_datastore_initializers.push_back(initializer); + } + /** * @brief Add a value checker to the module. */ - template void addValueChecker() + template void addValueChecker(std::shared_ptr& checker) { - m_checkers.push_back(std::make_shared()); + m_checkers.push_back(checker); } /** * @brief Add a value applier to the module. */ - template void addValueApplier() + template void addValueApplier(std::shared_ptr& applier) { - m_appliers.push_back(std::make_shared()); + m_appliers.push_back(applier); } private: + std::list> m_datastore_initializers; ///< Plugin datastore initializers. std::list> m_checkers; ///< Plugin data checkers. std::list> m_appliers; ///< Plugin datastore data appliers. PluginContextType &m_pluginContext; ///< Plugin context used to share data between different parts of the module.