From 0f657e6d8316869fba3bd6218fd6910c84fee3f5 Mon Sep 17 00:00:00 2001
From: Kubat <mael.martin31@gmail.com>
Date: Sun, 23 May 2021 15:18:42 +0200
Subject: [PATCH] CMD: Add the 'exec from trie' function, to use functions
 registered inside it

---
 src/net/listen.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 74 insertions(+), 2 deletions(-)

diff --git a/src/net/listen.c b/src/net/listen.c
index dbbd5853..229055fa 100644
--- a/src/net/listen.c
+++ b/src/net/listen.c
@@ -43,6 +43,10 @@ struct cmd_trie_node {
     struct cmd_trie_node *children[CHARS_MAX]; /* Childrens, a byte is 256 possible values  */
 };
 
+/* The cmd_trie root for all the liblektor, it's OK because we have only one
+ * list of possible commands. */
+static struct cmd_trie_node *cmd_trie_root = NULL;
+
 PRIVATE_FUNCTION struct cmd_trie_node *
 cmd_trie_new(void)
 {
@@ -92,6 +96,76 @@ cmd_trie_insert(struct cmd_trie_node *root, const char *signed_cmd_name,
     }
 }
 
+PRIVATE_FUNCTION struct cmd_trie_node *
+cmd_trie_find(struct cmd_trie_node *root, const char *signed_cmd_name)
+{
+    FAIL_UNLESS(root, "Passing an empty trie root");
+    unsigned const char *cmd_name = (unsigned const char *)signed_cmd_name;
+    size_t cmd_name_index         = 0;
+    size_t current_char           = cmd_name[cmd_name_index];
+
+    while (current_char) {
+        /* No node for the command */
+        if (root->children[current_char] == NULL) {
+            LOG_WARN("CMD_TRIE", "Failed to find the command: %s", signed_cmd_name);
+            return NULL;
+        }
+
+        cmd_name_index += 1;
+        root         = root->children[current_char];
+        current_char = cmd_name[cmd_name_index];
+    }
+
+    if (root->type == LKT_COMMAND_NULL) {
+        LOG_WARN("CMD_TRIE", "Failed to find the command: %s", signed_cmd_name);
+        return NULL;
+    }
+
+    LOG_INFO("CMD_TRIE", "Found command: %s", signed_cmd_name);
+    return root;
+}
+
+PRIVATE_FUNCTION bool
+cmd_trie_exec(struct cmd_trie_node *root, const char *signed_cmd_name, va_list *args_list)
+{
+    FAIL_UNLESS(root, "Passing an empty trie root");
+    struct cmd_trie_node *node = cmd_trie_find(root, signed_cmd_name);
+    if (node == NULL)
+        return false;
+
+    /* Possibly used variables */
+    struct lkt_state *srv;
+    size_t c;
+    char **args;
+    int arg_int;
+
+    union {
+        void (*base)(void);
+        bool (*type_simple)(struct lkt_state *, size_t, char *[LKT_MESSAGE_ARGS_MAX]);
+        bool (*type_int)(struct lkt_state *, size_t, char *[LKT_MESSAGE_ARGS_MAX], int);
+    } cmd;
+
+    cmd.base = node->cmd_ptr;
+
+    switch (node->type) {
+    case LKT_COMMAND_SIMPLE:
+        srv  = (struct lkt_state *)va_arg(*args_list, struct lkt_state *);
+        c    = (size_t)va_arg(*args_list, size_t);
+        args = (char **)va_arg(*args_list, char *[LKT_MESSAGE_MAX]);
+        return cmd.type_simple(srv, c, args);
+
+    case LKT_COMMAND_INTEGER:
+        srv     = (struct lkt_state *)va_arg(*args_list, struct lkt_state *);
+        c       = (size_t)va_arg(*args_list, size_t);
+        args    = (char **)va_arg(*args_list, char *[LKT_MESSAGE_MAX]);
+        arg_int = (int)va_arg(*args_list, int);
+        return cmd.type_int(srv, c, args, arg_int);
+
+    case LKT_COMMAND_NULL:
+        return false;
+    }
+}
+
 PRIVATE_FUNCTION void
 ___cmd_trie_print(struct cmd_trie_node *root, char *old_prefix, const size_t length)
 {
@@ -127,8 +201,6 @@ cmd_trie_print(struct cmd_trie_node *root)
     ___cmd_trie_print(root, NULL, 0);
 }
 
-struct cmd_trie_node *cmd_trie_root = NULL;
-
 CONSTRUCTOR_FUNCTION
 ___cmd_trie_init(void)
 {
-- 
GitLab