summaryrefslogtreecommitdiff
path: root/src/uci/command.c
blob: 02d6e0f78a792f947167e5d402967eb3ea256af8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#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 <stdbool.h>
#include <string.h>

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