From 245563ec8b165b03bdf733f6bbf5519bab4d3c71 Mon Sep 17 00:00:00 2001 From: Vftdan Date: Thu, 15 Aug 2024 20:57:17 +0200 Subject: [PATCH] Make the program unaware in compile time of the node types Using "constructor" attribute --- Makefile | 2 +- defs.h | 2 ++ main.c | 19 +++---------------- module_registry.c | 43 +++++++++++++++++++++++++++++++++++++++++++ module_registry.h | 10 ++++++++++ nodes/evdev.c | 6 ++++++ nodes/getchar.c | 6 ++++++ nodes/print.c | 6 ++++++ 8 files changed, 77 insertions(+), 17 deletions(-) create mode 100644 module_registry.c create mode 100644 module_registry.h diff --git a/Makefile b/Makefile index 4abfe67..7c7e4df 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ CPPFLAGS += $(shell pkg-config --cflags $(DEPS)) LDLIBS += $(shell pkg-config --libs $(DEPS)) INTERP ?= MAIN = main -OBJS = main.o events.o processing.o graph.o config.o hash_table.o nodes/getchar.o nodes/print.o nodes/evdev.o +OBJS = main.o events.o processing.o graph.o config.o hash_table.o module_registry.o nodes/getchar.o nodes/print.o nodes/evdev.o all: $(MAIN) diff --git a/defs.h b/defs.h index 4a32a87..ab7e382 100644 --- a/defs.h +++ b/defs.h @@ -15,6 +15,8 @@ #define IMPLICIT_CAST(dsttype, srctype, ptr) (((union { typeof(srctype) *src; typeof(dsttype) *dst; }){.src = ptr}).dst) #define T_ALLOC(count, T) ((T*)calloc(count, sizeof(T))) +#define MODULE_CONSTRUCTOR(name) __attribute__((constructor)) static void name(void) + #define DEBUG_PRINT_VALUE(x, fmt) fprintf(stderr, #x " = " fmt "\n", x); fflush(stderr) #endif /* end of include guard: DEFS_H_ */ diff --git a/main.c b/main.c index 258e025..914a1db 100644 --- a/main.c +++ b/main.c @@ -1,14 +1,6 @@ #include "processing.h" #include "hash_table.h" -#include "nodes/print.h" -#include "nodes/getchar.h" -#include "nodes/evdev.h" - -GraphNodeSpecification *node_specifications[] = { - &nodespec_getchar, - &nodespec_print, - &nodespec_evdev, -}; +#include "module_registry.h" int main(int argc, char ** argv) @@ -42,13 +34,7 @@ main(int argc, char ** argv) fprintf(stderr, "No node type for node %ld \"%s\"\n", i, loaded_config.nodes.items[i].name); exit(1); } - GraphNodeSpecification *spec = NULL; - for (size_t j = 0; j < lengthof(node_specifications); ++j) { - if (strcmp(type_name, node_specifications[j]->name) == 0) { - spec = node_specifications[j]; - break; - } - } + GraphNodeSpecification *spec = lookup_graph_node_specification(type_name); if (!spec) { fprintf(stderr, "Unknown node type \"%s\" for node %ld \"%s\"\n", type_name, i, loaded_config.nodes.items[i].name); exit(1); @@ -103,5 +89,6 @@ main(int argc, char ** argv) io_subscription_list_deinit(&state.wait_output); io_subscription_list_deinit(&state.wait_input); + destroy_graph_node_specification_registry(); return 0; } diff --git a/module_registry.c b/module_registry.c new file mode 100644 index 0000000..10bedce --- /dev/null +++ b/module_registry.c @@ -0,0 +1,43 @@ +#include "module_registry.h" +#include "hash_table.h" + +static TYPED_HASH_TABLE(GraphNodeSpecification*) registry; +static bool initialized = false; + +static void +ensure_initialized() +{ + if (!initialized) { + hash_table_init(®istry, NULL); + initialized = true; + } +} + +void +register_graph_node_specification(GraphNodeSpecification * spec) +{ + ensure_initialized(); + if (!spec->name) { + return; + } + hash_table_insert(®istry, hash_table_key_from_cstr(spec->name), &spec); +} + +GraphNodeSpecification * +lookup_graph_node_specification(const char * name) +{ + ensure_initialized(); + HashTableIndex idx = hash_table_find(®istry, hash_table_key_from_cstr(name)); + if (idx < 0) { + return NULL; + } + return registry.value_array[idx]; +} + +void +destroy_graph_node_specification_registry() +{ + ensure_initialized(); + hash_table_deinit(®istry); + initialized = false; +} diff --git a/module_registry.h b/module_registry.h new file mode 100644 index 0000000..4b21062 --- /dev/null +++ b/module_registry.h @@ -0,0 +1,10 @@ +#ifndef MODULE_REGISTRY_H_ +#define MODULE_REGISTRY_H_ + +#include "graph.h" + +void register_graph_node_specification(GraphNodeSpecification * spec); +GraphNodeSpecification * lookup_graph_node_specification(const char * name); +void destroy_graph_node_specification_registry(); + +#endif /* end of include guard: MODULE_REGISTRY_H_ */ diff --git a/nodes/evdev.c b/nodes/evdev.c index 849addc..c8f9e47 100644 --- a/nodes/evdev.c +++ b/nodes/evdev.c @@ -7,6 +7,7 @@ #include #include "evdev.h" #include "../processing.h" +#include "../module_registry.h" typedef struct { GraphNode as_GraphNode; @@ -139,3 +140,8 @@ GraphNodeSpecification nodespec_evdev = (GraphNodeSpecification) { .register_io = ®ister_io, .name = "evdev", }; + +MODULE_CONSTRUCTOR(init) +{ + register_graph_node_specification(&nodespec_evdev); +} diff --git a/nodes/getchar.c b/nodes/getchar.c index 3b3b7c8..7e84ae9 100644 --- a/nodes/getchar.c +++ b/nodes/getchar.c @@ -2,6 +2,7 @@ #include #include "getchar.h" #include "../processing.h" +#include "../module_registry.h" typedef struct { GraphNode as_GraphNode; @@ -98,3 +99,8 @@ GraphNodeSpecification nodespec_getchar = (GraphNodeSpecification) { .register_io = ®ister_io, .name = "getchar", }; + +MODULE_CONSTRUCTOR(init) +{ + register_graph_node_specification(&nodespec_getchar); +} diff --git a/nodes/print.c b/nodes/print.c index 693f8f3..543de2e 100644 --- a/nodes/print.c +++ b/nodes/print.c @@ -1,5 +1,6 @@ #include #include "print.h" +#include "../module_registry.h" static bool handle_event(EventPositionBase * self, EventNode * event) @@ -59,3 +60,8 @@ GraphNodeSpecification nodespec_print = (GraphNodeSpecification) { .register_io = NULL, .name = "print", }; + +MODULE_CONSTRUCTOR(init) +{ + register_graph_node_specification(&nodespec_print); +}