#include #include #include #include "uci/internals/command.h" uci_cmd_t uci_cmd_init() { uci_cmd_t 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 uci_cmd_add(uci_cmd_t* cmd, const char* token) { if (!cmd->empty) { uci_cmd_append_arg(cmd, token); return; } if (is_valid_cmd(token) == 0) return; uci_cmd_set_root(cmd, token); } void uci_cmd_set_root(uci_cmd_t* 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 uci_cmd_append_arg(uci_cmd_t* 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( uci_cmd_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* uci_cmd_get_arg(uci_cmd_t cmd, int i) { return cmd.args + i * MAX_TOKEN_SIZE; } void uci_cmd_deinit(uci_cmd_t cmd) { free(cmd.args); } #ifdef TEST_MOD #include #include bool test_uci_cmd_t() { uci_cmd_t cmd = uci_cmd_init(); uci_cmd_set_root(&cmd, "root"); uci_cmd_append_arg(&cmd, "arg1"); uci_cmd_append_arg(&cmd, "arg2"); uci_cmd_append_arg(&cmd, "arg3"); if (strncmp(cmd.root, "root", MAX_TOKEN_SIZE) != 0) { uci_cmd_deinit(cmd); return false; } if (strncmp(uci_cmd_get_arg(cmd, 0), "arg1", MAX_TOKEN_SIZE) != 0) { uci_cmd_deinit(cmd); return false; } if (strncmp(uci_cmd_get_arg(cmd, 1), "arg2", MAX_TOKEN_SIZE) != 0) { uci_cmd_deinit(cmd); return false; } if (strncmp(uci_cmd_get_arg(cmd, 2), "arg3", MAX_TOKEN_SIZE) != 0) { uci_cmd_deinit(cmd); return false; } uci_cmd_deinit(cmd); return true; } bool test_invalid_cmd_uci_cmd_t() { uci_cmd_t cmd = uci_cmd_init(); uci_cmd_add(&cmd, "john"); uci_cmd_add(&cmd, "debug"); uci_cmd_add(&cmd, "on"); if (strncmp(cmd.root, "debug", MAX_TOKEN_SIZE) != 0) { uci_cmd_deinit(cmd); return false; } if (strncmp(uci_cmd_get_arg(cmd, 0), "on", MAX_TOKEN_SIZE) != 0) { uci_cmd_deinit(cmd); return false; } uci_cmd_deinit(cmd); return true; } #endif