#include #include #include #include "denc_registry.h" namespace fs = std::filesystem; class DencoderPlugin { using dencoders_t = std::vector>; public: DencoderPlugin(const fs::path& path) { mod = dlopen(path.c_str(), RTLD_NOW); if (mod == nullptr) { std::cerr << "failed to dlopen(" << path << "): " << dlerror() << std::endl; } } DencoderPlugin(DencoderPlugin&& other) : mod{other.mod}, dencoders{std::move(other.dencoders)} { other.mod = nullptr; other.dencoders.clear(); } ~DencoderPlugin() { #if !defined(__FreeBSD__) if (mod) { dlclose(mod); } #endif } const dencoders_t& register_dencoders() { static constexpr std::string_view REGISTER_DENCODERS_FUNCTION = "register_dencoders\0"; assert(mod); using register_dencoders_t = void (*)(DencoderPlugin*); const auto do_register = reinterpret_cast(dlsym(mod, REGISTER_DENCODERS_FUNCTION.data())); if (do_register == nullptr) { std::cerr << "failed to dlsym(" << REGISTER_DENCODERS_FUNCTION << "): " << dlerror() << std::endl; return dencoders; } do_register(this); return dencoders; } bool good() const { return mod != nullptr; } void unregister_dencoders() { while (!dencoders.empty()) { delete dencoders.back().second; dencoders.pop_back(); } } template void emplace(const char* name, Args&&...args) { dencoders.emplace_back(name, new DencoderT(std::forward(args)...)); } private: void *mod = nullptr; dencoders_t dencoders; }; #define TYPE(t) plugin->emplace>(#t, false, false); #define TYPE_STRAYDATA(t) plugin->emplace>(#t, true, false); #define TYPE_NONDETERMINISTIC(t) plugin->emplace>(#t, false, true); #define TYPE_FEATUREFUL(t) plugin->emplace>(#t, false, false); #define TYPE_FEATUREFUL_STRAYDATA(t) plugin->emplace>(#t, true, false); #define TYPE_FEATUREFUL_NONDETERMINISTIC(t) plugin->emplace>(#t, false, true); #define TYPE_FEATUREFUL_NOCOPY(t) plugin->emplace>(#t, false, false); #define TYPE_NOCOPY(t) plugin->emplace>(#t, false, false); #define MESSAGE(t) plugin->emplace>(#t); #define DENC_API extern "C" [[gnu::visibility("default")]]