libscheaders/plugin.hpp

127 lines
2.9 KiB
C++
Raw Normal View History

2020-03-16 15:11:40 +01:00
#ifndef _plugin_H_
#define _plugin_H_
#include <memory>
#include <string>
#include <map>
#include <functional>
#include <iostream>
#include <random>
2020-03-16 15:11:40 +01:00
#include <dlfcn.h>
#include <dirent.h>
#include <libscerror.hpp>
2020-03-16 15:11:40 +01:00
namespace sc {
template <typename T>
class plugin {
public:
static void scan_plugins(const std::string& dir, const std::string& ext) {
DIR* plugins_dir = opendir(dir.c_str());
throw_if_null_msg(plugins_dir, (dir + " could not be opened").c_str());
struct dirent* info;
while ((info = readdir(plugins_dir)) != nullptr) {
if (info->d_name[0] != '.') {
std::string plugname {info->d_name};
std::string::size_type lastdot = plugname.rfind(".");
if (plugname.substr(lastdot + 1) == ext) {
plugin plugin {dir + '/' + plugname};
2021-10-06 14:12:38 +02:00
plugin.name(plugname.substr(0, lastdot));
plugins.emplace(plugin.name(), std::move(plugin));
}
2020-03-16 15:11:40 +01:00
}
}
throw_if_min1(closedir(plugins_dir));
2020-03-16 15:11:40 +01:00
}
using processor = std::function<void(const plugin&)>;
static void foreach(processor proc) {
for (const auto& elem : plugins) {
proc(elem.second);
}
}
2020-03-16 15:11:40 +01:00
static plugin& get(const std::string& name) {
return plugins.at(name);
2020-03-16 15:11:40 +01:00
}
static std::vector<std::string> names() {
std::vector<std::string> result;
for (const auto& elem : plugins) {
result.emplace_back(elem.first);
2020-03-16 15:11:40 +01:00
}
return result;
2020-03-16 15:11:40 +01:00
}
static size_t count() { return plugins.size(); }
plugin(const std::string& path) : _path {path} {
_plugin = dlopen(path.c_str(), RTLD_LAZY);
const char* err {dlerror()};
if (err) std::cerr << err << '\n';
if (_plugin) {
_factory = reinterpret_cast<factory>(dlsym(_plugin, "create_instance"));
if (!_factory) {
std::cerr << "create_instance() function not found in " << path << '\n';
}
}
2020-03-16 15:11:40 +01:00
}
~plugin() {
if (_plugin) {
dlclose(_plugin);
_plugin = nullptr;
}
}
2020-03-16 15:11:40 +01:00
plugin(const plugin&) = delete;
plugin& operator=(const plugin&) = delete;
2020-03-16 15:11:40 +01:00
plugin(plugin&& other) {
2020-03-16 15:11:40 +01:00
_path = other._path;
_plugin = other._plugin;
_factory = other._factory;
other._plugin = nullptr;
}
plugin& operator=(plugin&& other) {
if (this != &other) {
_path = other._path;
_plugin = other._plugin;
_factory = other._factory;
other._plugin = nullptr;
}
return *this;
}
2020-03-16 15:11:40 +01:00
2021-10-06 14:12:38 +02:00
const std::string& path() const { return _path; }
const std::string& name() const { return _name; }
void name(const std::string& nm) { _name = nm; }
std::unique_ptr<T> operator()() const {
std::unique_ptr<T> obj;
if (_factory) {
obj.reset(_factory());
}
return obj;
2020-03-16 15:11:40 +01:00
}
private:
static std::map<std::string, plugin<T>> plugins;
2020-03-16 15:11:40 +01:00
std::string _path;
2021-10-06 14:12:38 +02:00
std::string _name;
void* _plugin {nullptr};
using factory = T*(*)();
factory _factory {nullptr};
2020-03-16 15:11:40 +01:00
};
template <typename T>
std::map<std::string, plugin<T>> plugin<T>::plugins;
}
#endif // _plugin_H_