aboutsummaryrefslogtreecommitdiffstats
path: root/7_2/src/input.c
diff options
context:
space:
mode:
Diffstat (limited to '7_2/src/input.c')
-rw-r--r--7_2/src/input.c116
1 files changed, 116 insertions, 0 deletions
diff --git a/7_2/src/input.c b/7_2/src/input.c
new file mode 100644
index 0000000..d2dca7c
--- /dev/null
+++ b/7_2/src/input.c
@@ -0,0 +1,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;
+}
+