aboutsummaryrefslogtreecommitdiff
path: root/src/core/io_formats.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/io_formats.h')
-rw-r--r--src/core/io_formats.h403
1 files changed, 0 insertions, 403 deletions
diff --git a/src/core/io_formats.h b/src/core/io_formats.h
deleted file mode 100644
index f5668d4..0000000
--- a/src/core/io_formats.h
+++ /dev/null
@@ -1,403 +0,0 @@
1STATIC cube_t readcube(const char *, const char *);
2STATIC int64_t writecube(const char *, cube_t, size_t n, char [n]);
3STATIC void log_available_formats(void);
4STATIC uint8_t readco(const char *);
5STATIC uint8_t readcp(const char *);
6STATIC uint8_t readeo(const char *);
7STATIC uint8_t readep(const char *);
8STATIC cube_t readcube_B32(const char *);
9STATIC cube_t readcube_H48(const char *);
10STATIC uint8_t readpiece_LST(const char **);
11STATIC cube_t readcube_LST(const char *);
12
13STATIC int64_t writepiece_LST(uint8_t, size_t n, char [n]);
14STATIC int64_t writecube_B32(cube_t, size_t n, char [n]);
15STATIC int64_t writecube_H48(cube_t, size_t n, char [n]);
16STATIC int64_t writecube_LST(cube_t, size_t n, char [n]);
17
18STATIC uint8_t b32toedge(char);
19STATIC uint8_t b32tocorner(char);
20STATIC char edgetob32(uint8_t);
21STATIC char cornertob32(uint8_t);
22
23STATIC struct {
24 const char *name;
25 cube_t (*read)(const char *);
26 int64_t (*write)(cube_t, size_t n, char [n]);
27} ioformat[] =
28{
29 { .name = "B32", .read = readcube_B32, .write = writecube_B32 },
30 { .name = "LST", .read = readcube_LST, .write = writecube_LST },
31 { .name = "H48", .read = readcube_H48, .write = writecube_H48 },
32 { .name = "NONE", .read = NULL, .write = NULL },
33};
34
35STATIC cube_t
36readcube(const char *format, const char *buf)
37{
38 int i;
39
40 for (i = 0; ioformat[i].read != NULL; i++)
41 if (!strcmp(format, ioformat[i].name))
42 return ioformat[i].read(buf);
43
44 LOG("Cannot read cube: unknown format '%s'\n", format);
45 log_available_formats();
46 return ZERO_CUBE;
47}
48
49STATIC int64_t
50writecube(const char *format, cube_t cube, size_t buf_size, char buf[buf_size])
51{
52 int i;
53
54 for (i = 0; ioformat[i].write != NULL; i++)
55 if (!strcmp(format, ioformat[i].name))
56 return ioformat[i].write(cube, buf_size, buf);
57
58 LOG("Cannot write cube: unknown format '%s'\n", format);
59 log_available_formats();
60 return NISSY_ERROR_INVALID_FORMAT;
61}
62
63STATIC void
64log_available_formats(void)
65{
66 int i;
67
68 LOG("Available formats: ");
69 for (i = 0; ioformat[i].read != NULL; i++)
70 LOG("'%s' ", ioformat[i].name);
71 LOG("\n");
72}
73
74STATIC uint8_t
75readco(const char *str)
76{
77 if (*str == '0')
78 return 0;
79 if (*str == '1')
80 return CTWIST_CW;
81 if (*str == '2')
82 return CTWIST_CCW;
83
84 LOG("Error reading CO\n");
85 return UINT8_ERROR;
86}
87
88STATIC uint8_t
89readcp(const char *str)
90{
91 uint8_t c;
92
93 for (c = 0; c < 8; c++)
94 if (!strncmp(str, cornerstr[c], 3) ||
95 !strncmp(str, cornerstralt[c], 3))
96 return c;
97
98 LOG("Error reading CP\n");
99 return UINT8_ERROR;
100}
101
102STATIC uint8_t
103readeo(const char *str)
104{
105 if (*str == '0')
106 return 0;
107 if (*str == '1')
108 return EFLIP;
109
110 LOG("Error reading EO\n");
111 return UINT8_ERROR;
112}
113
114STATIC uint8_t
115readep(const char *str)
116{
117 uint8_t e;
118
119 for (e = 0; e < 12; e++)
120 if (!strncmp(str, edgestr[e], 2))
121 return e;
122
123 LOG("Error reading EP\n");
124 return UINT8_ERROR;
125}
126
127STATIC cube_t
128readcube_B32(const char *buf)
129{
130 int i;
131 uint8_t c[8], e[12];
132
133 for (i = 0; i < 8; i++) {
134 c[i] = b32tocorner(buf[i]);
135 if (c[i] == UINT8_ERROR) {
136 LOG("Error reading B32 corner %d ", i);
137 if (buf[i] == 0) {
138 LOG("(string terminated early)\n");
139 } else {
140 LOG("(char '%c')\n", buf[i]);
141 }
142 return ZERO_CUBE;
143 }
144 }
145
146 if (buf[8] != '=') {
147 LOG("Error reading B32 separator: a single '=' "
148 "must be used to separate edges and corners\n");
149 return ZERO_CUBE;
150 }
151
152 for (i = 0; i < 12; i++) {
153 e[i] = b32toedge(buf[i+9]);
154 if (e[i] == UINT8_ERROR) {
155 LOG("Error reading B32 edge %d ", i);
156 if (buf[i+9] == 0) {
157 LOG("(string terminated early)\n");
158 } else {
159 LOG("(char '%c')\n", buf[i+9]);
160 }
161 return ZERO_CUBE;
162 }
163 }
164
165 return cubefromarray(c, e);
166}
167
168STATIC cube_t
169readcube_H48(const char *buf)
170{
171 int i;
172 uint8_t piece, orient, c[8], e[12];
173 const char *b;
174
175 b = buf;
176
177 for (i = 0; i < 12; i++) {
178 while (*b == ' ' || *b == '\t' || *b == '\n')
179 b++;
180 if ((piece = readep(b)) == UINT8_ERROR)
181 return ZERO_CUBE;
182 b += 2;
183 if ((orient = readeo(b)) == UINT8_ERROR)
184 return ZERO_CUBE;
185 b++;
186 e[i] = piece | orient;
187 }
188 for (i = 0; i < 8; i++) {
189 while (*b == ' ' || *b == '\t' || *b == '\n')
190 b++;
191 if ((piece = readcp(b)) == UINT8_ERROR)
192 return ZERO_CUBE;
193 b += 3;
194 if ((orient = readco(b)) == UINT8_ERROR)
195 return ZERO_CUBE;
196 b++;
197 c[i] = piece | orient;
198 }
199
200 return cubefromarray(c, e);
201}
202
203STATIC uint8_t
204readpiece_LST(const char **b)
205{
206 uint8_t ret;
207 bool read;
208
209 while (**b == ',' || **b == ' ' || **b == '\t' || **b == '\n')
210 (*b)++;
211
212 for (ret = 0, read = false; **b >= '0' && **b <= '9'; (*b)++) {
213 read = true;
214 ret = ret * 10 + (**b) - '0';
215 }
216
217 return read ? ret : UINT8_ERROR;
218}
219
220STATIC cube_t
221readcube_LST(const char *buf)
222{
223 int i;
224 uint8_t c[8], e[12];
225
226 for (i = 0; i < 8; i++)
227 c[i] = readpiece_LST(&buf);
228
229 for (i = 0; i < 12; i++)
230 e[i] = readpiece_LST(&buf);
231
232 return cubefromarray(c, e);
233}
234
235STATIC int64_t
236writepiece_LST(uint8_t piece, size_t buf_size, char buf[buf_size])
237{
238 char digits[3];
239 size_t i, len;
240
241 if (piece > 99 || buf_size < 3)
242 return 0;
243
244 len = 0;
245 while (piece != 0) {
246 digits[len++] = (piece % 10) + '0';
247 piece /= 10;
248 }
249
250 if (buf_size < len+2)
251 return 0;
252
253 if (len == 0)
254 digits[len++] = '0';
255
256 for (i = 0; i < len; i++)
257 buf[i] = digits[len-i-1];
258
259 buf[len] = ',';
260 buf[len+1] = ' ';
261
262 return len+2;
263}
264
265STATIC int64_t
266writecube_B32(cube_t cube, size_t buf_size, char buf[buf_size])
267{
268 int i;
269 uint8_t corner[8], edge[12];
270
271 if (buf_size < NISSY_SIZE_B32) {
272 LOG("Cannot write cube in B32 format: buffer size must be at "
273 "least %u bytes, but the provided one is %zu bytes.\n",
274 NISSY_SIZE_B32, buf_size);
275 return NISSY_ERROR_BUFFER_SIZE;
276 }
277
278 pieces(&cube, corner, edge);
279
280 for (i = 0; i < 8; i++)
281 buf[i] = cornertob32(corner[i]);
282
283 buf[8] = '=';
284
285 for (i = 0; i < 12; i++)
286 buf[i+9] = edgetob32(edge[i]);
287
288 buf[21] = '\0';
289
290 return NISSY_OK;
291}
292
293STATIC int64_t
294writecube_H48(cube_t cube, size_t buf_size, char buf[buf_size])
295{
296 uint8_t piece, perm, orient, corner[8], edge[12];
297 int i;
298
299 if (buf_size < NISSY_SIZE_H48) {
300 LOG("Cannot write cube in H48 format: buffer size must be "
301 "at least %u bytes, but the provided one is %zu bytes.\n",
302 NISSY_SIZE_H48, buf_size);
303 return NISSY_ERROR_BUFFER_SIZE;
304 }
305
306 pieces(&cube, corner, edge);
307
308 for (i = 0; i < 12; i++) {
309 piece = edge[i];
310 perm = piece & PBITS;
311 orient = (piece & EOBIT) >> EOSHIFT;
312 buf[4*i ] = edgestr[perm][0];
313 buf[4*i + 1] = edgestr[perm][1];
314 buf[4*i + 2] = orient + '0';
315 buf[4*i + 3] = ' ';
316 }
317 for (i = 0; i < 8; i++) {
318 piece = corner[i];
319 perm = piece & PBITS;
320 orient = (piece & COBITS) >> COSHIFT;
321 buf[48 + 5*i ] = cornerstr[perm][0];
322 buf[48 + 5*i + 1] = cornerstr[perm][1];
323 buf[48 + 5*i + 2] = cornerstr[perm][2];
324 buf[48 + 5*i + 3] = orient + '0';
325 buf[48 + 5*i + 4] = ' ';
326 }
327
328 buf[48+39] = '\0';
329
330 return NISSY_OK;
331}
332
333STATIC int64_t
334writecube_LST(cube_t cube, size_t buf_size, char buf[buf_size])
335{
336 int i;
337 uint64_t ptr;
338 uint8_t piece, corner[8], edge[12];
339
340 ptr = 0;
341 pieces(&cube, corner, edge);
342
343 for (i = 0; i < 8; i++) {
344 piece = corner[i];
345 ptr += writepiece_LST(piece, buf_size - ptr, buf + ptr);
346 if (ptr == 0)
347 goto writecube_LST_error;
348 }
349
350 for (i = 0; i < 12; i++) {
351 piece = edge[i];
352 ptr += writepiece_LST(piece, buf_size - ptr, buf + ptr);
353 if (ptr == 0)
354 goto writecube_LST_error;
355 }
356
357 *(buf+ptr-2) = '\0';
358
359 return NISSY_OK;
360
361writecube_LST_error:
362 LOG("Cannot write cube in LST: buffer is too small (%" PRIu64
363 " bytes given). The LST format has a variable size, try a "
364 "larger buffer.\n", buf_size);
365 return NISSY_ERROR_BUFFER_SIZE;
366}
367
368STATIC uint8_t
369b32toedge(char c)
370{
371 if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'f')))
372 return UINT8_ERROR;
373
374 return c <= 'Z' ? (uint8_t)(c - 'A') : (uint8_t)(c - 'a') + 26;
375}
376
377STATIC uint8_t
378b32tocorner(char c) {
379 uint8_t val;
380
381 if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'f')))
382 return UINT8_ERROR;
383
384 val = c <= 'Z' ? (uint8_t)(c - 'A') : (uint8_t)(c - 'a') + 26;
385
386 return (val & 7) | ((val & 24) << 2);
387}
388
389STATIC char
390edgetob32(uint8_t edge)
391{
392 return edge < 26 ? 'A' + (char)edge : 'a' + (char)(edge - 26);
393}
394
395STATIC char
396cornertob32(uint8_t corner)
397{
398 uint8_t val;
399
400 val = (corner & 7) | ((corner & 96) >> 2);
401
402 return val < 26 ? 'A' + (char)val : 'a' + (char)(val - 26);
403}

Generated with cgit - Back to sebastiano.tronto.net