From b576c1cfe6105a4f392ea9acfd770297d3972888 Mon Sep 17 00:00:00 2001 From: Bob Polis Date: Tue, 5 Oct 2021 14:25:04 +0200 Subject: [PATCH] Added count() and random_choice() functions --- plugin.hpp | 166 ++++++++++++++++++++++++++++------------------------- 1 file changed, 87 insertions(+), 79 deletions(-) diff --git a/plugin.hpp b/plugin.hpp index 0c56cf6..e6b4281 100644 --- a/plugin.hpp +++ b/plugin.hpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -22,102 +23,109 @@ namespace sc { template 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}; - plugins.emplace(plugname.substr(0, lastdot), std::move(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}; + plugins.emplace(plugname.substr(0, lastdot), std::move(plugin)); + } + } + } + throw_if_min1(::closedir(plugins_dir)); + } + + using processor = std::function; + 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 names() { + std::vector 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 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(::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; - 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 names() { - std::vector 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(::dlsym(_plugin, "create_instance")); - if (!_factory) { - std::cerr << "create_instance() function not found in " << path << '\n'; + ~plugin() { + if (_plugin) { + ::dlclose(_plugin); + _plugin = nullptr; } } - } - ~plugin() { - if (_plugin) { - ::dlclose(_plugin); - _plugin = nullptr; - //std::cerr << _path << " closed\n"; - } - } + plugin(const plugin&) = delete; + plugin& operator=(const plugin&) = delete; - plugin(const plugin&) = delete; - 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) { + plugin(plugin&& other) { _path = other._path; _plugin = other._plugin; _factory = other._factory; other._plugin = nullptr; } - return *this; - } - std::string path() const { return _path; } - - std::unique_ptr operator()() const { - std::unique_ptr obj; - if (_factory) { - obj.reset(_factory()); + plugin& operator=(plugin&& other) { + if (this != &other) { + _path = other._path; + _plugin = other._plugin; + _factory = other._factory; + other._plugin = nullptr; + } + return *this; } - return obj; - } - private: - static std::map> plugins; + std::string path() const { return _path; } - std::string _path; - void* _plugin {nullptr}; - using factory = T*(*)(); - factory _factory {nullptr}; + std::unique_ptr operator()() const { + std::unique_ptr obj; + if (_factory) { + obj.reset(_factory()); + } + return obj; + } + + private: + static std::map> plugins; + + std::string _path; + void* _plugin {nullptr}; + using factory = T*(*)(); + factory _factory {nullptr}; }; template