summaryrefslogtreecommitdiff
path: root/src/plugins.cpp
blob: a702e399ac827f25cc15fa920a37afdcb164f2aa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

#include "plugins.hpp"

#include "pk.h"

#include <cassert>
#include <cstdio>
#include <cstring>

#ifdef WIN32
	// TODO
#else
	#include <dlfcn.h>
#endif

pk_arr_t<PKEPluginInterface> LoadedPkePlugins{};
pk_arr_t<PkeCallback> pkePluginCallbacks{};
pk_arr_t<CallbackSignature> sortedSignatures{};

void PkePlugin_Load(const char *path) {
	if (path == nullptr || path == CAFE_BABE(const char)) {
		return;
	}
	void *extension = dlopen(path, RTLD_NOW);
	char *err = dlerror();
	if (!extension) {
		fprintf(stderr, "Given plugin library (%s) failed to load: %s\n", path, err);
		return;
	}
	PKEPluginInterface *interface = reinterpret_cast<PKEPluginInterface *>(dlsym(extension, "pkePluginInterface"));
	err = dlerror();
	if (err != NULL) {
		fprintf(stderr, "Given plugin library (%s) did not contain 'pkePluginInterface': %s\n", path, err);
		dlclose(extension);
		return;
	}
	interface->pluginHandle = extension;
	pk_arr_append(&LoadedPkePlugins, interface);
}

PkeCallback *PkePlugin_FindSignature(const CallbackSignature &sig) {
	for (long i = 0; i < pkePluginCallbacks.next; ++i) {
		if (strncmp(sig, pkePluginCallbacks[i].name, 16) == 0) {
			return &pkePluginCallbacks[i];
		}
	}
	return nullptr;
}

void PkePlugin_SetSignatureFunc(PkeCallback *sig) {
	assert(sig != nullptr);
	if (sig->name[0] == '\0') {
		return;
	}
	auto *registeredSig = PkePlugin_FindSignature(sig->name);
	if (registeredSig == nullptr) {
		fprintf(stdout, "[WARN] [PkePlugin_SetSignatureFunc] Failed to find configured signature: '%s'\n", sig->name);
		return;
	}
	sig->func = registeredSig->func;
}

int pstrncmp(const void* a, const void* b)
{
	return strncmp(static_cast<const CallbackSignature *>(a)[0], static_cast<const CallbackSignature *>(b)[0], 16);
}
CallbackSignature *PkePlugin_GetSortedSignatures(long &count) {
	if (sortedSignatures.next != pkePluginCallbacks.next) {
		while (sortedSignatures.next != pkePluginCallbacks.next) {
			pk_arr_append(&sortedSignatures, pkePluginCallbacks[sortedSignatures.next].name);
		}
		qsort(sortedSignatures.data, sortedSignatures.next, sizeof(CallbackSignature), pstrncmp);
	}
	count = sortedSignatures.next;
	return reinterpret_cast<CallbackSignature*>(sortedSignatures.data);
}
void PkePlugin_Teardown() {
	pk_arr_reset(&sortedSignatures);
	pk_arr_reset(&pkePluginCallbacks);
	pk_arr_reset(&LoadedPkePlugins);
}