twinkle_stick/source/cmd.c

66 lines
1.4 KiB
C

#include "cmd.h"
#include <string.h>
#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);
}
}