Added count() and random_choice() functions

This commit is contained in:
Bob Polis 2021-10-05 14:25:04 +02:00
parent f1095f294a
commit b576c1cfe6

View File

@ -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>