66 lines
1.4 KiB
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);
|
|
}
|
|
}
|