io_moves.h (2436B)
1 STATIC uint8_t readmove(char); 2 STATIC int64_t readmoves(const char *, size_t n, uint8_t [n]); 3 STATIC int64_t countmoves(const char *); 4 STATIC uint8_t readmodifier(char); 5 STATIC int64_t writemoves(size_t n, const uint8_t [n], size_t m, char [m]); 6 7 #define FOREACH_READMOVE(ARG_BUF, ARG_MOVE, ARG_C, ARG_MAX, \ 8 RET_ERROR, ARG_ACTION) \ 9 const char *VAR_B; \ 10 uint8_t VAR_MOVE_NOMOD, VAR_MOD; \ 11 for (VAR_B = ARG_BUF, ARG_C = 0; *VAR_B != '\0'; VAR_B++, ARG_C++) { \ 12 while (*VAR_B == ' ' || *VAR_B == '\t' || *VAR_B == '\n') \ 13 VAR_B++; \ 14 if (*VAR_B == '\0' || ARG_C == ARG_MAX) \ 15 break; \ 16 if ((VAR_MOVE_NOMOD = readmove(*VAR_B)) == UINT8_ERROR) { \ 17 LOG("Error: unknown move '%c'\n", *VAR_B); \ 18 return RET_ERROR; \ 19 } \ 20 if ((VAR_MOD = readmodifier(*(VAR_B+1))) != 0) \ 21 VAR_B++; \ 22 ARG_MOVE = VAR_MOVE_NOMOD + VAR_MOD; \ 23 ARG_ACTION \ 24 } 25 26 STATIC uint8_t 27 readmove(char c) 28 { 29 switch (c) { 30 case 'U': 31 return MOVE_U; 32 case 'D': 33 return MOVE_D; 34 case 'R': 35 return MOVE_R; 36 case 'L': 37 return MOVE_L; 38 case 'F': 39 return MOVE_F; 40 case 'B': 41 return MOVE_B; 42 default: 43 return UINT8_ERROR; 44 } 45 } 46 47 STATIC uint8_t 48 readmodifier(char c) 49 { 50 switch (c) { 51 case '1': /* Fallthrough */ 52 case '2': /* Fallthrough */ 53 case '3': 54 return c - '0' - 1; 55 case '\'': 56 return 2; 57 default: 58 return 0; 59 } 60 } 61 62 STATIC int64_t 63 readmoves(const char *buf, size_t n, uint8_t ret[n]) 64 { 65 uint8_t m; 66 uint64_t c; 67 68 FOREACH_READMOVE(buf, m, c, n, NISSY_ERROR_INVALID_MOVES, 69 ret[c] = m; 70 ) 71 72 return (int64_t)c; 73 } 74 75 STATIC int64_t 76 countmoves(const char *buf) 77 { 78 uint8_t m; 79 uint64_t c; 80 81 FOREACH_READMOVE(buf, m, c, INT_MAX, NISSY_ERROR_INVALID_MOVES, 82 {} 83 ) 84 85 (void)m; /* Ignore "variable set but not used" warning */ 86 87 return (int64_t)c; 88 } 89 90 STATIC int64_t 91 writemoves( 92 size_t nmoves, 93 const uint8_t m[nmoves], 94 size_t buf_size, 95 char buf[buf_size] 96 ) 97 { 98 size_t i, len, w; 99 const char *s; 100 101 if (buf_size == 0) { 102 LOG("Error: cannot write moves to buffer of size 0.\n"); 103 return NISSY_ERROR_BUFFER_SIZE; 104 } 105 106 for (i = 0, w = 0; i < nmoves; i++, w++) { 107 s = movestr[m[i]]; 108 len = strlen(s); 109 if (len + w >= buf_size) { 110 LOG("Error: the given buffer is too small for " 111 "writing the given moves.\n"); 112 goto writemoves_error; 113 } 114 memcpy(buf+w, s, len); 115 w += len; 116 buf[w] = ' '; 117 } 118 119 if (w > 0) w--; /* Remove last space */ 120 buf[w] = '\0'; 121 122 return (int64_t)w; 123 124 writemoves_error: 125 *buf = '\0'; 126 return NISSY_ERROR_BUFFER_SIZE; 127 }