#include "cmd.h" #include #define CMD_TABLE_SIZE 4 typedef struct { const char *name; cmd_fn_t fn; } cmd_entry_t; static cmd_entry_t table[CMD_TABLE_SIZE]; static cmd_write_fn write_fn; static uint32_t djb2(const char *str) { uint32_t hash = 5381; unsigned char c; while ((c = (unsigned char)*str++)) hash = ((hash << 5) + hash) + c; return hash; } void cmd_init(cmd_write_fn fn) { write_fn = fn; memset(table, 0, sizeof(table)); } void cmd_register(const char *name, cmd_fn_t fn) { uint32_t idx = djb2(name) & (CMD_TABLE_SIZE - 1); for (int i = 0; i < CMD_TABLE_SIZE; i++) { uint32_t slot = (idx + (uint32_t)i) & (CMD_TABLE_SIZE - 1); if (table[slot].name == NULL) { table[slot].name = name; table[slot].fn = fn; return; } } while (1) {} // table full } void cmd_dispatch(char *line) { char *argv[8]; int argc = 0; char *tok = strtok(line, " \t"); while (tok != NULL && argc < 8) { argv[argc++] = tok; tok = strtok(NULL, " \t"); } if (argc == 0) return; uint32_t idx = djb2(argv[0]) & (CMD_TABLE_SIZE - 1); for (int i = 0; i < CMD_TABLE_SIZE; i++) { uint32_t slot = (idx + (uint32_t)i) & (CMD_TABLE_SIZE - 1); if (table[slot].name == NULL) break; if (strcmp(table[slot].name, argv[0]) == 0) { table[slot].fn(argc, argv); return; } } if (write_fn) { write_fn((const uint8_t *)"unknown command\r\n", 17); } }