/* * Copyright (C) 2016 Charybdis Development Team * Copyright (C) 2016 Jason Volk * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice is present in all copies. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #pragma once #define HAVE_IRCD_MODS_H /// Modules system namespace ircd::mods { IRCD_EXCEPTION(ircd::error, error) IRCD_EXCEPTION(error, filesystem_error) IRCD_EXCEPTION(error, invalid_export) IRCD_EXCEPTION(error, expired_symbol) IRCD_EXCEPTION(error, undefined_symbol) IRCD_EXCEPTION(error, demangle_error) IRCD_EXCEPTION(demangle_error, not_mangled) struct mod; struct module; struct sym_ptr; template struct import; template struct import_shared; struct paths extern paths; // Platform (.so|.dll) postfixing std::string postfixed(const std::string &name); std::string unpostfixed(const std::string &name); // Section & Symbol utilites std::vector sections(const std::string &fullpath); std::vector symbols(const std::string &fullpath, const std::string §ion); std::vector symbols(const std::string &fullpath); std::unordered_map mangles(const std::vector &); std::unordered_map mangles(const std::string &fullpath, const std::string §ion); std::unordered_map mangles(const std::string &fullpath); // Find module names where symbol resides bool has_symbol(const std::string &name, const std::string &symbol); std::vector find_symbol(const std::string &symbol); // returns dir/name of first dir containing 'name' (and this will be a loadable module) // Unlike libltdl, the reason each individual candidate failed is presented in a vector. std::string search(const std::string &name, std::vector &why); std::string search(const std::string &name); // Potential modules available to load std::forward_list available(); bool available(const std::string &name); bool loaded(const std::string &name); } // Bring struct module into main ircd:: namespace ircd { using mods::module; using mods::import; using mods::import_shared; } struct ircd::mods::paths :std::vector { bool added(const std::string &dir) const; bool del(const std::string &dir); bool add(const std::string &dir, std::nothrow_t); bool add(const std::string &dir); paths(); }; struct ircd::mods::module :std::shared_ptr { const std::string &name() const; const std::string &path() const; const std::string &mangle(const std::string &) const; bool has(const std::string &name) const; template const T *ptr(const std::string &name) const; template T *ptr(const std::string &name); template const T &get(const std::string &name) const; template T &get(const std::string &name); module(std::shared_ptr ptr = {}) :std::shared_ptr{std::move(ptr)} {} module(const std::string &name); ~module() noexcept; }; namespace ircd::mods { template<> const uint8_t *module::ptr(const std::string &name) const; template<> uint8_t *module::ptr(const std::string &name); } template T & ircd::mods::module::get(const std::string &name) { return *ptr(name); } template const T & ircd::mods::module::get(const std::string &name) const { return *ptr(name); } template T * ircd::mods::module::ptr(const std::string &name) { return reinterpret_cast(ptr(name)); } template const T * ircd::mods::module::ptr(const std::string &name) const { return reinterpret_cast(ptr(name)); } /// Representation of a symbol in a loaded library (non-template; low level). /// class ircd::mods::sym_ptr :std::weak_ptr { void *ptr; public: operator bool() const { return !expired(); } bool operator!() const { return expired(); } template const T *get() const; template const T *operator->() const; template const T &operator*() const; template auto operator()(args&&... a) const; template T *get(); template T *operator->(); template T &operator*(); sym_ptr(const std::string &modname, const std::string &symname); ~sym_ptr() noexcept; }; template T & ircd::mods::sym_ptr::operator*() { if(unlikely(expired())) throw expired_symbol("The reference to a symbol in another module is no longer valid"); return *get(); } template T * ircd::mods::sym_ptr::operator->() { return get(); } template T * ircd::mods::sym_ptr::get() { return reinterpret_cast(ptr); } template auto ircd::mods::sym_ptr::operator()(args&&... a) const { return (*get())(std::forward(a)...); } template const T & ircd::mods::sym_ptr::operator*() const { if(unlikely(expired())) throw expired_symbol("The const reference to a symbol in another module is no longer valid"); return *get(); } template const T * ircd::mods::sym_ptr::operator->() const { return get(); } template const T * ircd::mods::sym_ptr::get() const { return reinterpret_cast(ptr); } /// Representation of a symbol in a loaded shared library /// template struct ircd::mods::import :sym_ptr { template auto operator()(args&&... a) const { return sym_ptr::operator()(std::forward(a)...); } const T *operator->() const { return sym_ptr::operator->(); } const T &operator*() const { return sym_ptr::operator*(); } operator const T &() const { return sym_ptr::operator*(); } T *operator->() { return sym_ptr::operator->(); } T &operator*() { return sym_ptr::operator*(); } operator T &() { return sym_ptr::operator*(); } using sym_ptr::sym_ptr; }; /// Convenience for importing an std::shared_ptr from a loaded lib /// template struct ircd::mods::import_shared :import> ,std::shared_ptr { using std::shared_ptr::get; using std::shared_ptr::operator bool; using std::shared_ptr::operator->; using std::shared_ptr::operator*; operator const T &() const { return std::shared_ptr::operator*(); } operator T &() { return std::shared_ptr::operator*(); } import_shared(const std::string &modname, const std::string &symname); }; template ircd::mods::import_shared::import_shared(const std::string &modname, const std::string &symname) :import> { modname, symname } ,std::shared_ptr { import>::operator*() }{}