io_cube.h (6497B)
1 STATIC uint8_t readco(const char *); 2 STATIC uint8_t readcp(const char *); 3 STATIC uint8_t readeo(const char *); 4 STATIC uint8_t readep(const char *); 5 STATIC cube_t readcube_B32(const char *); 6 STATIC cube_t readcube_H48(const char *); 7 STATIC uint8_t readpiece_LST(const char **); 8 STATIC cube_t readcube_LST(const char *); 9 10 STATIC int writepiece_LST(uint8_t, char *); 11 STATIC void writecube_B32(cube_t, char *); 12 STATIC void writecube_H48(cube_t, char *); 13 STATIC void writecube_LST(cube_t, char *); 14 15 STATIC uint8_t b32toedge(char); 16 STATIC uint8_t b32tocorner(char); 17 STATIC char edgetob32(uint8_t); 18 STATIC char cornertob32(uint8_t); 19 20 STATIC struct { 21 const char *name; 22 cube_t (*read)(const char *); 23 void (*write)(cube_t, char *); 24 } ioformat[] = 25 { 26 { .name = "B32", .read = readcube_B32, .write = writecube_B32 }, 27 { .name = "LST", .read = readcube_LST, .write = writecube_LST }, 28 { .name = "H48", .read = readcube_H48, .write = writecube_H48 }, 29 { .name = "NONE", .read = NULL, .write = NULL }, 30 }; 31 32 cube_t 33 readcube(const char *format, const char *buf) 34 { 35 int i; 36 37 for (i = 0; ioformat[i].read != NULL; i++) 38 if (!strcmp(format, ioformat[i].name)) 39 return ioformat[i].read(buf); 40 41 LOG("Cannot read cube in the given format\n"); 42 return ZERO_CUBE; 43 } 44 45 void 46 writecube(const char *format, cube_t cube, char *buf) 47 { 48 char *errormsg; 49 size_t len; 50 51 if (!isconsistent(cube)) { 52 errormsg = "ERROR: inconsistent"; 53 goto writecube_error; 54 } 55 56 int i; 57 58 for (i = 0; ioformat[i].write != NULL; i++) { 59 if (!strcmp(format, ioformat[i].name)) { 60 ioformat[i].write(cube, buf); 61 return; 62 } 63 } 64 65 errormsg = "ERROR: format"; 66 67 writecube_error: 68 LOG("writecube error, see stdout for details\n"); 69 len = strlen(errormsg); 70 memcpy(buf, errormsg, len); 71 buf[len] = '\n'; 72 buf[len+1] = '\0'; 73 } 74 75 STATIC uint8_t 76 readco(const char *str) 77 { 78 if (*str == '0') 79 return 0; 80 if (*str == '1') 81 return CTWIST_CW; 82 if (*str == '2') 83 return CTWIST_CCW; 84 85 LOG("Error reading CO\n"); 86 return UINT8_ERROR; 87 } 88 89 STATIC uint8_t 90 readcp(const char *str) 91 { 92 uint8_t c; 93 94 for (c = 0; c < 8; c++) 95 if (!strncmp(str, cornerstr[c], 3) || 96 !strncmp(str, cornerstralt[c], 3)) 97 return c; 98 99 LOG("Error reading CP\n"); 100 return UINT8_ERROR; 101 } 102 103 STATIC uint8_t 104 readeo(const char *str) 105 { 106 if (*str == '0') 107 return 0; 108 if (*str == '1') 109 return EFLIP; 110 111 LOG("Error reading EO\n"); 112 return UINT8_ERROR; 113 } 114 115 STATIC uint8_t 116 readep(const char *str) 117 { 118 uint8_t e; 119 120 for (e = 0; e < 12; e++) 121 if (!strncmp(str, edgestr[e], 2)) 122 return e; 123 124 LOG("Error reading EP\n"); 125 return UINT8_ERROR; 126 } 127 128 STATIC cube_t 129 readcube_B32(const char *buf) 130 { 131 int i; 132 uint8_t c[8], e[12]; 133 134 for (i = 0; i < 8; i++) { 135 c[i] = b32tocorner(buf[i]); 136 DBG_ASSERT(c[i] < 255, ZERO_CUBE, 137 "Error reading B32 corner %d (char %d)\n", i, i); 138 } 139 140 for (i = 0; i < 12; i++) { 141 e[i] = b32toedge(buf[i+9]); 142 DBG_ASSERT(e[i] < 255, ZERO_CUBE, 143 "Error reading B32 edge %d (char %d)\n", i, i+9); 144 } 145 146 return cubefromarray(c, e); 147 } 148 149 STATIC cube_t 150 readcube_H48(const char *buf) 151 { 152 int i; 153 uint8_t piece, orient, c[8], e[12]; 154 const char *b; 155 156 b = buf; 157 158 for (i = 0; i < 12; i++) { 159 while (*b == ' ' || *b == '\t' || *b == '\n') 160 b++; 161 if ((piece = readep(b)) == UINT8_ERROR) 162 return ZERO_CUBE; 163 b += 2; 164 if ((orient = readeo(b)) == UINT8_ERROR) 165 return ZERO_CUBE; 166 b++; 167 e[i] = piece | orient; 168 } 169 for (i = 0; i < 8; i++) { 170 while (*b == ' ' || *b == '\t' || *b == '\n') 171 b++; 172 if ((piece = readcp(b)) == UINT8_ERROR) 173 return ZERO_CUBE; 174 b += 3; 175 if ((orient = readco(b)) == UINT8_ERROR) 176 return ZERO_CUBE; 177 b++; 178 c[i] = piece | orient; 179 } 180 181 return cubefromarray(c, e); 182 } 183 184 STATIC uint8_t 185 readpiece_LST(const char **b) 186 { 187 uint8_t ret; 188 bool read; 189 190 while (**b == ',' || **b == ' ' || **b == '\t' || **b == '\n') 191 (*b)++; 192 193 for (ret = 0, read = false; **b >= '0' && **b <= '9'; (*b)++) { 194 read = true; 195 ret = ret * 10 + (**b) - '0'; 196 } 197 198 return read ? ret : UINT8_ERROR; 199 } 200 201 STATIC cube_t 202 readcube_LST(const char *buf) 203 { 204 int i; 205 uint8_t c[8], e[12]; 206 207 for (i = 0; i < 8; i++) 208 c[i] = readpiece_LST(&buf); 209 210 for (i = 0; i < 12; i++) 211 e[i] = readpiece_LST(&buf); 212 213 return cubefromarray(c, e); 214 } 215 216 STATIC int 217 writepiece_LST(uint8_t piece, char *buf) 218 { 219 char digits[3]; 220 int i, len; 221 222 len = 0; 223 while (piece != 0) { 224 digits[len++] = (piece % 10) + '0'; 225 piece /= 10; 226 } 227 228 if (len == 0) 229 digits[len++] = '0'; 230 231 for (i = 0; i < len; i++) 232 buf[i] = digits[len-i-1]; 233 234 buf[len] = ','; 235 buf[len+1] = ' '; 236 237 return len+2; 238 } 239 240 STATIC void 241 writecube_B32(cube_t cube, char *buf) 242 { 243 int i; 244 uint8_t corner[8], edge[12]; 245 246 pieces(&cube, corner, edge); 247 248 for (i = 0; i < 8; i++) 249 buf[i] = cornertob32(corner[i]); 250 251 buf[8] = '='; 252 253 for (i = 0; i < 12; i++) 254 buf[i+9] = edgetob32(edge[i]); 255 256 buf[21] = '\0'; 257 } 258 259 STATIC void 260 writecube_H48(cube_t cube, char *buf) 261 { 262 uint8_t piece, perm, orient, corner[8], edge[12]; 263 int i; 264 265 pieces(&cube, corner, edge); 266 267 for (i = 0; i < 12; i++) { 268 piece = edge[i]; 269 perm = piece & PBITS; 270 orient = (piece & EOBIT) >> EOSHIFT; 271 buf[4*i ] = edgestr[perm][0]; 272 buf[4*i + 1] = edgestr[perm][1]; 273 buf[4*i + 2] = orient + '0'; 274 buf[4*i + 3] = ' '; 275 } 276 for (i = 0; i < 8; i++) { 277 piece = corner[i]; 278 perm = piece & PBITS; 279 orient = (piece & COBITS) >> COSHIFT; 280 buf[48 + 5*i ] = cornerstr[perm][0]; 281 buf[48 + 5*i + 1] = cornerstr[perm][1]; 282 buf[48 + 5*i + 2] = cornerstr[perm][2]; 283 buf[48 + 5*i + 3] = orient + '0'; 284 buf[48 + 5*i + 4] = ' '; 285 } 286 287 buf[48+39] = '\0'; 288 } 289 290 STATIC void 291 writecube_LST(cube_t cube, char *buf) 292 { 293 int i; 294 size_t ptr; 295 uint8_t piece, corner[8], edge[12]; 296 297 ptr = 0; 298 pieces(&cube, corner, edge); 299 300 for (i = 0; i < 8; i++) { 301 piece = corner[i]; 302 ptr += writepiece_LST(piece, buf + ptr); 303 } 304 305 for (i = 0; i < 12; i++) { 306 piece = edge[i]; 307 ptr += writepiece_LST(piece, buf + ptr); 308 } 309 310 *(buf+ptr-2) = 0; 311 } 312 313 STATIC uint8_t 314 b32toedge(char c) 315 { 316 if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'f'))) 317 return 255; 318 319 return c <= 'Z' ? (uint8_t)(c - 'A') : (uint8_t)(c - 'a') + 26; 320 } 321 322 STATIC uint8_t 323 b32tocorner(char c) { 324 uint8_t val; 325 326 if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'f'))) 327 return 255; 328 329 val = c <= 'Z' ? (uint8_t)(c - 'A') : (uint8_t)(c - 'a') + 26; 330 331 return (val & 7) | ((val & 24) << 2); 332 } 333 334 STATIC char 335 edgetob32(uint8_t edge) 336 { 337 return edge < 26 ? 'A' + (char)edge : 'a' + (char)(edge - 26); 338 } 339 340 STATIC char 341 cornertob32(uint8_t corner) 342 { 343 uint8_t val; 344 345 val = (corner & 7) | ((corner & 96) >> 2); 346 347 return val < 26 ? 'A' + (char)val : 'a' + (char)(val - 26); 348 }