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
|
#include "input.h"
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
const char *const unexpchtok = "Unexpected token: %c\n";
const char *const invalidint = "Invalid integer: %s\n";
#define error(fmt, ...) do { \
fprintf(stderr, fmt, __VA_ARGS__); \
return 0; \
} while(0)
#define maybe_realloc(size, cap, pointer, type) do { \
if (size >= cap) { \
cap <<= 1; \
pointer = realloc(pointer, cap * sizeof (type));\
} \
} while(0)
void(*settings_handler)(const char*) = NULL;
void skipw(char const **s) { while(isspace(**s)) ++*s; }
void skipd(char const **s) { while(isdigit(**s)) ++*s; }
char chktok(char const **str, char tok) {
skipw(str);
long tmp = atol(*str);
if (**str != tok) error(unexpchtok, **str);
++*str;
return 1;
}
char parsel(char const **str, long *l) {
skipw(str);
long tmp = atoi(*str);
if (tmp == 0 && **str != '0') error(invalidint, *str);
*l = tmp;
skipd(str);
return 1;
}
char parsev(char const **str, vector2 *v) {
long x, y;
// я ща кончу на этот код
char suc = chktok(str, '{')
&& parsel(str, &x)
&& chktok(str, ',')
&& parsel(str, &y)
&& chktok(str, '}');
if (suc) {
v->x = x;
v->y = y;
return 1;
} else return 0;
}
struct figure read_figure(const char *str) {
struct figure ret = {.type = F_NONE};
const char *strp = str;
skipw(&strp);
++strp;
switch(strp[-1]) {
case '.': {
if (settings_handler != NULL) settings_handler(strp);
} break;
case 'p': {
if (parsev(&strp, &ret.point.coords)
&& chktok(&strp, ';')) ret.type = F_POINT;
} break;
case 'r': {
if (parsev(&strp, &ret.rect.upleft)
&& parsev(&strp, &ret.rect.downright)
&& chktok(&strp, ';')) ret.type = F_RECT;
} break;
case 'l': {
if (parsev(&strp, &ret.line.start)
&& parsev(&strp, &ret.line.end)
&& chktok(&strp, ';')) ret.type = F_LINE;
} break;
case 'c': {
if (parsev(&strp, &ret.circle.center)
&& parsel(&strp, &ret.circle.rad)
&& chktok(&strp, ';')) ret.type = F_CIRCLE;
} break;
default:;
}
ret.draw = draw_lookup[ret.type];
return ret;
}
struct figure *read_file(const char *path) {
FILE *f = fopen(path, "r");
if (!f) return NULL;
size_t bs = 1024;
size_t fs = -1, fcap = 16;
char *buf = malloc(fcap * sizeof(struct figure));
struct figure *figures = malloc(fcap * sizeof (struct figure));
while (!feof(f)) {
if (getdelim(&buf, &bs, ';', f) < 0) break;
struct figure f = read_figure(buf);
if (f.type == F_NONE) continue;
++fs;
maybe_realloc(fs, fcap, figures, struct figure);
memcpy(figures + fs, &f, sizeof (struct figure));
}
++fs;
maybe_realloc(fs, fcap, figures, struct figure);
struct figure END = {.type = F_NONE, 0};
memcpy(figures + fs, &END, sizeof (struct figure));
free(buf);
return figures;
}
|