Added count() and random_choice() functions
This commit is contained in:
parent
f1095f294a
commit
b576c1cfe6
166
plugin.hpp
166
plugin.hpp
@ -14,6 +14,7 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <random>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <libscerror.hpp>
|
#include <libscerror.hpp>
|
||||||
@ -22,102 +23,109 @@ namespace sc {
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class plugin {
|
class plugin {
|
||||||
public:
|
public:
|
||||||
static void scan_plugins(const std::string& dir, const std::string& ext) {
|
static void scan_plugins(const std::string& dir, const std::string& ext) {
|
||||||
DIR* plugins_dir = ::opendir(dir.c_str());
|
DIR* plugins_dir = ::opendir(dir.c_str());
|
||||||
throw_if_null_msg(plugins_dir, (dir + " could not be opened").c_str());
|
throw_if_null_msg(plugins_dir, (dir + " could not be opened").c_str());
|
||||||
struct dirent* info;
|
struct dirent* info;
|
||||||
while ((info = ::readdir(plugins_dir)) != nullptr) {
|
while ((info = ::readdir(plugins_dir)) != nullptr) {
|
||||||
if (info->d_name[0] != '.') {
|
if (info->d_name[0] != '.') {
|
||||||
std::string plugname {info->d_name};
|
std::string plugname {info->d_name};
|
||||||
std::string::size_type lastdot = plugname.rfind(".");
|
std::string::size_type lastdot = plugname.rfind(".");
|
||||||
if (plugname.substr(lastdot + 1) == ext) {
|
if (plugname.substr(lastdot + 1) == ext) {
|
||||||
plugin plugin {dir + '/' + plugname};
|
plugin plugin {dir + '/' + plugname};
|
||||||
plugins.emplace(plugname.substr(0, lastdot), std::move(plugin));
|
plugins.emplace(plugname.substr(0, lastdot), std::move(plugin));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw_if_min1(::closedir(plugins_dir));
|
||||||
|
}
|
||||||
|
|
||||||
|
using processor = std::function<void(const plugin&)>;
|
||||||
|
static void foreach(processor proc) {
|
||||||
|
for (const auto& elem : plugins) {
|
||||||
|
proc(elem.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static plugin& get(const std::string& name) {
|
||||||
|
return plugins.at(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<std::string> names() {
|
||||||
|
std::vector<std::string> result;
|
||||||
|
for (const auto& elem : plugins) {
|
||||||
|
result.emplace_back(elem.first);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t count() { return plugins.size(); }
|
||||||
|
|
||||||
|
static plugin& random_choice() {
|
||||||
|
static std::random_device rdev {};
|
||||||
|
static std::default_random_engine reng {rdev()};
|
||||||
|
std::uniform_int_distribution<int> dist {0, count() - 1};
|
||||||
|
return get(names()[dist(reng)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
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';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw_if_min1(::closedir(plugins_dir));
|
|
||||||
}
|
|
||||||
|
|
||||||
using processor = std::function<void(const plugin&)>;
|
|
||||||
static void foreach(processor proc) {
|
|
||||||
for (const auto& elem : plugins) {
|
|
||||||
proc(elem.second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static plugin& get(const std::string& name) {
|
~plugin() {
|
||||||
return plugins.at(name);
|
if (_plugin) {
|
||||||
}
|
::dlclose(_plugin);
|
||||||
|
_plugin = nullptr;
|
||||||
static std::vector<std::string> names() {
|
|
||||||
std::vector<std::string> result;
|
|
||||||
for (const auto& elem : plugins) {
|
|
||||||
result.emplace_back(elem.first);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
plugin(const std::string& path) : _path {path} {
|
|
||||||
_plugin = ::dlopen(path.c_str(), RTLD_LAZY);
|
|
||||||
|
|
||||||
//std::cerr << path << (_plugin ? "" : " not") << " opened\n";
|
|
||||||
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';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
~plugin() {
|
plugin(const plugin&) = delete;
|
||||||
if (_plugin) {
|
plugin& operator=(const plugin&) = delete;
|
||||||
::dlclose(_plugin);
|
|
||||||
_plugin = nullptr;
|
|
||||||
//std::cerr << _path << " closed\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
plugin(const plugin&) = delete;
|
plugin(plugin&& other) {
|
||||||
plugin& operator=(const plugin&) = delete;
|
|
||||||
|
|
||||||
plugin(plugin&& other) {
|
|
||||||
_path = other._path;
|
|
||||||
_plugin = other._plugin;
|
|
||||||
_factory = other._factory;
|
|
||||||
other._plugin = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
plugin& operator=(plugin&& other) {
|
|
||||||
if (this != &other) {
|
|
||||||
_path = other._path;
|
_path = other._path;
|
||||||
_plugin = other._plugin;
|
_plugin = other._plugin;
|
||||||
_factory = other._factory;
|
_factory = other._factory;
|
||||||
other._plugin = nullptr;
|
other._plugin = nullptr;
|
||||||
}
|
}
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string path() const { return _path; }
|
plugin& operator=(plugin&& other) {
|
||||||
|
if (this != &other) {
|
||||||
std::unique_ptr<T> operator()() const {
|
_path = other._path;
|
||||||
std::unique_ptr<T> obj;
|
_plugin = other._plugin;
|
||||||
if (_factory) {
|
_factory = other._factory;
|
||||||
obj.reset(_factory());
|
other._plugin = nullptr;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
std::string path() const { return _path; }
|
||||||
static std::map<std::string, plugin<T>> plugins;
|
|
||||||
|
|
||||||
std::string _path;
|
std::unique_ptr<T> operator()() const {
|
||||||
void* _plugin {nullptr};
|
std::unique_ptr<T> obj;
|
||||||
using factory = T*(*)();
|
if (_factory) {
|
||||||
factory _factory {nullptr};
|
obj.reset(_factory());
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::map<std::string, plugin<T>> plugins;
|
||||||
|
|
||||||
|
std::string _path;
|
||||||
|
void* _plugin {nullptr};
|
||||||
|
using factory = T*(*)();
|
||||||
|
factory _factory {nullptr};
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user