]>
Commit | Line | Data |
---|---|---|
20effc67 TL |
1 | #include <dlfcn.h> |
2 | #include <filesystem> | |
3 | #include <vector> | |
4 | ||
5 | #include "denc_registry.h" | |
6 | ||
7 | namespace fs = std::filesystem; | |
8 | ||
9 | class DencoderPlugin { | |
10 | using dencoders_t = std::vector<std::pair<std::string, Dencoder*>>; | |
11 | public: | |
12 | DencoderPlugin(const fs::path& path) { | |
13 | mod = dlopen(path.c_str(), RTLD_NOW); | |
14 | if (mod == nullptr) { | |
15 | std::cerr << "failed to dlopen(" << path << "): " << dlerror() << std::endl; | |
16 | } | |
17 | } | |
18 | DencoderPlugin(DencoderPlugin&& other) | |
19 | : mod{other.mod}, | |
20 | dencoders{std::move(other.dencoders)} | |
21 | { | |
22 | other.mod = nullptr; | |
23 | other.dencoders.clear(); | |
24 | } | |
25 | ~DencoderPlugin() { | |
26 | #if !defined(__FreeBSD__) | |
27 | if (mod) { | |
28 | dlclose(mod); | |
29 | } | |
30 | #endif | |
31 | } | |
32 | const dencoders_t& register_dencoders() { | |
33 | static constexpr std::string_view REGISTER_DENCODERS_FUNCTION = "register_dencoders\0"; | |
34 | ||
35 | assert(mod); | |
36 | using register_dencoders_t = void (*)(DencoderPlugin*); | |
37 | const auto do_register = | |
38 | reinterpret_cast<register_dencoders_t>(dlsym(mod, REGISTER_DENCODERS_FUNCTION.data())); | |
39 | if (do_register == nullptr) { | |
40 | std::cerr << "failed to dlsym(" << REGISTER_DENCODERS_FUNCTION << "): " | |
41 | << dlerror() << std::endl; | |
42 | return dencoders; | |
43 | } | |
44 | do_register(this); | |
45 | return dencoders; | |
46 | } | |
47 | ||
48 | bool good() const { | |
49 | return mod != nullptr; | |
50 | } | |
51 | ||
52 | void unregister_dencoders() { | |
53 | while (!dencoders.empty()) { | |
54 | delete dencoders.back().second; | |
55 | dencoders.pop_back(); | |
56 | } | |
57 | } | |
58 | template<typename DencoderT, typename...Args> | |
59 | void emplace(const char* name, Args&&...args) { | |
60 | dencoders.emplace_back(name, new DencoderT(std::forward<Args>(args)...)); | |
61 | } | |
62 | ||
63 | private: | |
64 | void *mod = nullptr; | |
65 | dencoders_t dencoders; | |
66 | }; | |
67 | ||
68 | #define TYPE(t) plugin->emplace<DencoderImplNoFeature<t>>(#t, false, false); | |
69 | #define TYPE_STRAYDATA(t) plugin->emplace<DencoderImplNoFeature<t>>(#t, true, false); | |
70 | #define TYPE_NONDETERMINISTIC(t) plugin->emplace<DencoderImplNoFeature<t>>(#t, false, true); | |
71 | #define TYPE_FEATUREFUL(t) plugin->emplace<DencoderImplFeatureful<t>>(#t, false, false); | |
72 | #define TYPE_FEATUREFUL_STRAYDATA(t) plugin->emplace<DencoderImplFeatureful<t>>(#t, true, false); | |
73 | #define TYPE_FEATUREFUL_NONDETERMINISTIC(t) plugin->emplace<DencoderImplFeatureful<t>>(#t, false, true); | |
74 | #define TYPE_FEATUREFUL_NOCOPY(t) plugin->emplace<DencoderImplFeaturefulNoCopy<t>>(#t, false, false); | |
75 | #define TYPE_NOCOPY(t) plugin->emplace<DencoderImplNoFeatureNoCopy<t>>(#t, false, false); | |
76 | #define MESSAGE(t) plugin->emplace<MessageDencoderImpl<t>>(#t); | |
77 | ||
78 | #define DENC_API extern "C" [[gnu::visibility("default")]] |