static alias_Vector(struct engine_Command *) _command_all = ALIAS_VECTOR_INIT;
static alias_Vector(uint32_t) _command_by_name = ALIAS_VECTOR_INIT;
static int _command_by_name_compare(const void *ap, const void *bp, void *ud) {
uint32_t a = *(uint32_t *)ap;
uint32_t b = *(uint32_t *)bp;
return strcmp(_command_all.data[a]->name, _command_all.data[b]->name);
}
static struct engine_Command ** _command_find(const char * name) {
if(_command_all.length == 0) {
return NULL;
}
struct engine_Command _search_command = {.name = name};
uint32_t key = _command_all.length;
_command_all.data[key] = &_search_command;
uint32_t *found = bsearch(&key, _command_by_name.data, _command_by_name.length, sizeof(*_command_by_name.data), _command_by_name_compare, NULL);
if(found == NULL) {
return NULL;
}
return &_command_all.data[*found];
}
static void _command_insert(struct engine_Command *cmd) {
uint32_t index = _command_all.length;
alias_Vector_space_for(&_command_all, NULL, 2);
alias_Vector_space_for(&_command_by_name, NULL, 2);
*alias_Vector_push(&_command_all) = cmd;
*alias_Vector_push(&_command_by_name) = index;
qsort(_command_by_name.data, _command_by_name.length, sizeof(*_command_by_name.data), _command_by_name_compare, NULL);
}
void engine_command_register(struct engine_Command * cmd) {
struct engine_Command **cmd_ptr = _command_find(cmd->name);
if(cmd_ptr != NULL) {
engine_error("attempting to register multiple commands with the same name: %s", cmd->name);
return;
}
_command_insert(cmd);
}
static void _command_execute(int argc, char const * const * argv) {
struct engine_Command **cmd_ptr = _command_find(argv[0]);
if(cmd_ptr == NULL) {
engine_error("unknown command %s", argv[0]);
return;
}
(*cmd_ptr)->f(argc, argv);
}