#include #include #include #include "command.h" ucicmd ucicmd_init() { ucicmd output = {0}; output.empty = true; output.args_capacity = 32; output.args = calloc(sizeof(char) * MAX_TOKEN_SIZE, output.args_capacity); return output; } bool is_valid_cmd(const char *token) { return (strcmp(token, "uci") == 0) || (strcmp(token, "debug") == 0) || (strcmp(token, "isready") == 0) || (strcmp(token, "setoption") == 0) || (strcmp(token, "register") == 0) || (strcmp(token, "ucinewgame") == 0) || (strcmp(token, "position") == 0) || (strcmp(token, "go") == 0) || (strcmp(token, "stop") == 0) || (strcmp(token, "ponderhit") == 0) || (strcmp(token, "quit") == 0) || (strcmp(token, "id") == 0) || (strcmp(token, "uciok") == 0) || (strcmp(token, "readyok") == 0) || (strcmp(token, "bestmove") == 0) || (strcmp(token, "copyprotection") == 0) || (strcmp(token, "registration") == 0) || (strcmp(token, "info") == 0) || (strcmp(token, "option") == 0); } void ucicmd_add(ucicmd* cmd, const char* token) { if (!cmd->empty) { ucicmd_append_arg(cmd, token); return; } if (is_valid_cmd(token) == 0) return; ucicmd_set_root(cmd, token); } void ucicmd_set_root(ucicmd* cmd, const char* token) { cmd->empty = false; int i = 0; for (; token[i] != 0; i++) { assert(i < MAX_TOKEN_SIZE); cmd->root[i] = token[i]; } if (i < MAX_TOKEN_SIZE) cmd->root[i] = 0; } void ucicmd_append_arg(ucicmd* cmd, const char* token) { if (cmd->args_count + 1 > cmd->args_capacity) { cmd->args_capacity += 32; // does realloc set all zeros, like calloc??? // NO: https://stackoverflow.com/questions/61237721/does-a-realloc-after-a-calloc-zero-out-bytes cmd->args = realloc( cmd->args, sizeof(char) * MAX_TOKEN_SIZE * cmd->args_capacity ); memset( ucicmd_get_arg(*cmd, cmd->args_capacity - 32), 0, 32 * MAX_TOKEN_SIZE ); } int shift = cmd->args_count++ * sizeof(char) * MAX_TOKEN_SIZE; int i = 0; for (; token[i] != 0; i++) { assert(i < MAX_TOKEN_SIZE); cmd->args[shift + i] = token[i]; } if (i < MAX_TOKEN_SIZE) cmd->args[shift + i] = 0; } char* ucicmd_get_arg(ucicmd cmd, int i) { return cmd.args + i * MAX_TOKEN_SIZE; } void ucicmd_deinit(ucicmd cmd) { free(cmd.args); } #ifdef TEST_MOD #include #include bool test_ucicmd() { ucicmd cmd = ucicmd_init(); ucicmd_set_root(&cmd, "root"); ucicmd_append_arg(&cmd, "arg1"); ucicmd_append_arg(&cmd, "arg2"); ucicmd_append_arg(&cmd, "arg3"); if (strncmp(cmd.root, "root", MAX_TOKEN_SIZE) != 0) return false; if (strncmp(ucicmd_get_arg(cmd, 0), "arg1", MAX_TOKEN_SIZE) != 0) return false; if (strncmp(ucicmd_get_arg(cmd, 1), "arg2", MAX_TOKEN_SIZE) != 0) return false; if (strncmp(ucicmd_get_arg(cmd, 2), "arg3", MAX_TOKEN_SIZE) != 0) return false; return true; } bool test_invalid_cmd_ucicmd() { ucicmd cmd = ucicmd_init(); ucicmd_add(&cmd, "john"); ucicmd_add(&cmd, "debug"); ucicmd_add(&cmd, "on"); if (strncmp(cmd.root, "debug", MAX_TOKEN_SIZE) != 0) return false; if (strncmp(ucicmd_get_arg(cmd, 0), "on", MAX_TOKEN_SIZE) != 0) return false; return true; } #endif