Skip to content
23 changes: 18 additions & 5 deletions cpp/src/srpcpp/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand All @@ -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();

Expand Down Expand Up @@ -49,18 +62,18 @@ std::unordered_map<std::string, std::string> extractListKeysFromXpath(const std:
std::unordered_map<std::string, std::string> 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
Expand Down
26 changes: 24 additions & 2 deletions cpp/src/srpcpp/datastore.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::string> 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.
*/
Expand Down Expand Up @@ -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 <typename T>
concept DatastoreValueInitializer = std::is_base_of<IDatastoreInitializer, T>::value;

/**
* @brief Datastore applier concept for determining a valid datastore applier.
*/
template <typename T>
concept DatastoreValueApplier = std::is_base_of<IDatastoreApplier, T>::value;
Expand Down
14 changes: 12 additions & 2 deletions cpp/src/srpcpp/module-registry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,22 @@ template <PluginContext PluginContextType> class ModuleRegistry
/**
* Register a module.
*/
template <PluginModule<PluginContextType> ModuleType> size_t registerModule(PluginContextType &plugin_ctx)
template <PluginModule<PluginContextType> ModuleType> size_t registerModule(PluginContextType &plugin_ctx, const std::string &module_name)
{
m_modules.push_back(std::make_unique<ModuleType>(plugin_ctx));
m_modules.push_back(std::make_unique<ModuleType>(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.
*/
Expand Down
40 changes: 21 additions & 19 deletions cpp/src/srpcpp/module.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,6 @@ template <PluginContext PluginContextType> class IModule
return m_pluginContext;
}

/**
* Return the operational context from the module.
*/
virtual std::shared_ptr<IModuleContext> getOperationalContext() = 0;

/**
* Return the module changes context from the module.
*/
virtual std::shared_ptr<IModuleContext> getModuleChangesContext() = 0;

/**
* Return the RPC context from the module.
*/
virtual std::shared_ptr<IModuleContext> getRpcContext() = 0;

/**
* Get all operational callbacks which the module should use.
*/
Expand All @@ -67,6 +52,14 @@ template <PluginContext PluginContextType> class IModule
*/
virtual std::list<RpcCallback> getRpcCallbacks() = 0;

/**
* Get all datastore initializers that this module provides.
*/
std::list<std::shared_ptr<IDatastoreInitializer>> getDatastoreInitializers()
{
return m_datastore_initializers;
}

/**
* Get all datastore value checkers that this module provides.
*/
Expand Down Expand Up @@ -96,23 +89,32 @@ template <PluginContext PluginContextType> class IModule
}

protected:
/**
* @brief Add a datastore initializer to the module.
*/
template <DatastoreValueInitializer InitializerType> void addDatastoreInitializer(std::shared_ptr<InitializerType>& initializer)
{
m_datastore_initializers.push_back(initializer);
}

/**
* @brief Add a value checker to the module.
*/
template <DatastoreValueChecker CheckerType> void addValueChecker()
template <DatastoreValueChecker CheckerType> void addValueChecker(std::shared_ptr<CheckerType>& checker)
{
m_checkers.push_back(std::make_shared<CheckerType>());
m_checkers.push_back(checker);
}

/**
* @brief Add a value applier to the module.
*/
template <DatastoreValueApplier ApplierType> void addValueApplier()
template <DatastoreValueApplier ApplierType> void addValueApplier(std::shared_ptr<ApplierType>& applier)
{
m_appliers.push_back(std::make_shared<ApplierType>());
m_appliers.push_back(applier);
}

private:
std::list<std::shared_ptr<IDatastoreInitializer>> m_datastore_initializers; ///< Plugin datastore initializers.
std::list<std::shared_ptr<IDatastoreChecker>> m_checkers; ///< Plugin data checkers.
std::list<std::shared_ptr<IDatastoreApplier>> m_appliers; ///< Plugin datastore data appliers.
PluginContextType &m_pluginContext; ///< Plugin context used to share data between different parts of the module.
Expand Down