Skip to content
Extraits de code Groupes Projets
Vérifiée Valider 44ea9ada rédigé par Kubat's avatar Kubat
Parcourir les fichiers

CMD: Basic trie to store commands, only support insert for now

parent 90cbacec
Aucune branche associée trouvée
Aucune étiquette associée trouvée
1 requête de fusion!162Add a trie structure to get all the commands + various fixes
...@@ -18,6 +18,132 @@ ...@@ -18,6 +18,132 @@
#include <sys/un.h> #include <sys/un.h>
#include <sys/socket.h> #include <sys/socket.h>
/* Server commands, stored in a trie for a bit more efficient lookups.
* Commands have ascii names, but use the size of a char to not bother with
* bounds. If the `type` is not LKT_COMMAND_NULL, then the node is a terminal
* node, otherwise you need to reinterpret the `cmd_ptr` to the right function
* pointer type. */
#define CHARS_MAX (sizeof(char) * 256)
typedef enum {
/* Not a terminal node, so no commands */
LKT_COMMAND_NULL,
/* Some common types of commands */
LKT_COMMAND_SIMPLE, /* srv, c, args */
LKT_COMMAND_INTEGER, /* srv, c, args, int */
/* Some specialized types... */
} LKT_COMMAND_TYPE;
struct cmd_trie_node {
LKT_COMMAND_TYPE type; /* The type of the command, to reinterpret the function pointer */
void (*cmd_ptr)(void); /* The function pointer of the command */
struct cmd_trie_node *children[CHARS_MAX]; /* Childrens, a byte is 256 possible values */
};
PRIVATE_FUNCTION struct cmd_trie_node *
cmd_trie_new(void)
{
struct cmd_trie_node *ret = safe_malloc(sizeof(struct cmd_trie_node));
for (size_t i = 0; i < CHARS_MAX; ++i) {
ret->children[i] = NULL;
}
/* cmd_ptr == NULL && type == NULL => invalid node, for empty tries. */
ret->cmd_ptr = NULL;
ret->type = LKT_COMMAND_NULL;
return ret;
}
PRIVATE_FUNCTION void
cmd_trie_insert(struct cmd_trie_node *root, const char *signed_cmd_name,
void (*cmd_ptr)(void), LKT_COMMAND_TYPE cmd_type)
{
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) {
/* Create the node if it doesn't exist */
if (root->children[current_char] == NULL) {
root->children[current_char] = cmd_trie_new();
}
/* curr = curr->next */
cmd_name_index += 1;
root = root->children[current_char];
current_char = cmd_name[cmd_name_index];
}
/* Insert the new command */
if (root->type == LKT_COMMAND_NULL) {
root->type = cmd_type;
root->cmd_ptr = cmd_ptr;
}
/* The command was already inserted */
else {
LOG_FATAL("The command '%s' was already present in the cmd_trie", signed_cmd_name);
}
}
PRIVATE_FUNCTION void
___cmd_trie_print(struct cmd_trie_node *root, char *old_prefix, const size_t length)
{
char prefix[length + 2]; /* Old + new_char + \0 */
memcpy(prefix, old_prefix, sizeof(char) * length);
prefix[length + 1] = '\0';
switch (root->type) {
/* Not a terminal node */
case LKT_COMMAND_NULL:
break;
/* A terminal node */
case LKT_COMMAND_SIMPLE:
case LKT_COMMAND_INTEGER:
LKT_OUTPUT("CMD_TRIE", "Got function in trie: %s (type: %d)", prefix, root->type);
break;
}
for (size_t i = 0; i < CHARS_MAX; ++i) {
/* Rec-call with new children */
if (root->children[i] != NULL) {
prefix[length] = i;
___cmd_trie_print(root->children[i], prefix, length + 1);
}
}
}
PRIVATE_FUNCTION void
cmd_trie_print(struct cmd_trie_node *root)
{
FAIL_UNLESS(root, "Passing an empty trie root");
___cmd_trie_print(root, NULL, 0);
}
struct cmd_trie_node *cmd_trie_root = NULL;
CONSTRUCTOR_FUNCTION
___cmd_trie_init(void)
{
cmd_trie_root = cmd_trie_new();
cmd_trie_insert(cmd_trie_root, "next", FUNCTION_POINTER(command_next), LKT_COMMAND_SIMPLE);
cmd_trie_print(cmd_trie_root);
}
DESTRUCTOR_FUNCTION
___cmd_trie_deinit(void)
{
}
/* Client structure */
typedef enum { typedef enum {
LKT_COMMAND_LIST_OFF, LKT_COMMAND_LIST_OFF,
LKT_COMMAND_LIST_ON, LKT_COMMAND_LIST_ON,
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Veuillez vous inscrire ou vous pour commenter