summaryrefslogtreecommitdiff
path: root/src/command.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/command.c')
-rw-r--r--src/command.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/src/command.c b/src/command.c
new file mode 100644
index 0000000..4b233b2
--- /dev/null
+++ b/src/command.c
@@ -0,0 +1,66 @@
+#include "command.h"
+
+#include <stdlib.h>
+
+struct commands command_list_create(uint32_t capacity) {
+ return (struct commands){
+ .commands = calloc(capacity, sizeof(struct hashed_command)),
+ .ncommands = 0,
+ .capacity = capacity,
+ };
+}
+
+void command_list_destroy(struct commands *commands) {
+ free(commands->commands);
+ commands->ncommands = 0;
+ commands->capacity = 0;
+}
+
+uint32_t hash_command_name(const char *name) {
+ unsigned long hash = 5381;
+ int c;
+
+ while ((c = *name++))
+ hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
+
+ return hash;
+}
+
+uint32_t register_command(struct commands *commands, struct command *command) {
+ if (commands->ncommands == commands->capacity) {
+ commands->capacity *= 2;
+ commands->commands = realloc(
+ commands->commands, sizeof(struct hashed_command) * commands->capacity);
+ }
+
+ uint32_t hash = hash_command_name(command->name);
+ commands->commands[commands->ncommands] =
+ (struct hashed_command){.command = command, .hash = hash};
+
+ ++commands->ncommands;
+ return hash;
+}
+
+void register_commands(struct commands *command_list, struct command *commands,
+ uint32_t ncommands) {
+ for (uint32_t ci = 0; ci < ncommands; ++ci) {
+ register_command(command_list, &commands[ci]);
+ }
+}
+
+struct command *lookup_command(struct commands *command_list,
+ const char *name) {
+ uint32_t needle = hash_command_name(name);
+ return lookup_command_by_hash(command_list, needle);
+}
+
+struct command *lookup_command_by_hash(struct commands *commands,
+ uint32_t hash) {
+ for (uint32_t ci = 0; ci < commands->ncommands; ++ci) {
+ if (commands->commands[ci].hash == hash) {
+ return commands->commands[ci].command;
+ }
+ }
+
+ return NULL;
+}