Added count() and random_choice() functions
This commit is contained in:
		
							
								
								
									
										166
									
								
								plugin.hpp
									
									
									
									
									
								
							
							
						
						
									
										166
									
								
								plugin.hpp
									
									
									
									
									
								
							@@ -14,6 +14,7 @@
 | 
			
		||||
#include <map>
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <random>
 | 
			
		||||
#include <dlfcn.h>
 | 
			
		||||
#include <dirent.h>
 | 
			
		||||
#include <libscerror.hpp>
 | 
			
		||||
@@ -22,102 +23,109 @@ 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};
 | 
			
		||||
						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<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) {
 | 
			
		||||
			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;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		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() {
 | 
			
		||||
				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<T> operator()() const {
 | 
			
		||||
			std::unique_ptr<T> 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<std::string, plugin<T>> plugins;
 | 
			
		||||
			std::string path() const { return _path; }
 | 
			
		||||
 | 
			
		||||
		std::string _path;
 | 
			
		||||
		void* _plugin {nullptr};
 | 
			
		||||
		using factory = T*(*)();
 | 
			
		||||
		factory _factory {nullptr};
 | 
			
		||||
			std::unique_ptr<T> operator()() const {
 | 
			
		||||
				std::unique_ptr<T> obj;
 | 
			
		||||
				if (_factory) {
 | 
			
		||||
					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>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user