]> gitweb.ps.run Git - iftint/blob - main2.c
127 backspace
[iftint] / main2.c
1 #include <stdio.h>
2 #include <stdarg.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include <stdbool.h>
6
7 /* TODO
8 - whitelist input on GetStr/GetInt
9 */
10
11 // Memory
12
13 #define NEW(TYPE) ((TYPE *)calloc(1, sizeof(TYPE)))
14 #define NEWARR(TYPE, NUM) ((TYPE *)calloc(NUM, sizeof(TYPE)))
15
16
17 // getch()
18
19 #ifdef _WIN32
20 #include <conio.h>
21 #else
22 #include <termios.h>
23 #include <unistd.h>
24 #include <stdio.h>
25
26 /* reads from keypress, doesn't echo */
27 int getch(void)
28 {
29     struct termios oldattr, newattr;
30     int ch;
31     tcgetattr( STDIN_FILENO, &oldattr );
32     newattr = oldattr;
33     newattr.c_lflag &= ~( ICANON | ECHO );
34     tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
35     ch = getchar();
36     tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
37     return ch;
38 }
39
40 /* reads from keypress, echoes */
41 int getche(void)
42 {
43     struct termios oldattr, newattr;
44     int ch;
45     tcgetattr( STDIN_FILENO, &oldattr );
46     newattr = oldattr;
47     newattr.c_lflag &= ~( ICANON );
48     tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
49     ch = getchar();
50     tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
51     return ch;
52 }
53
54 /* ungets keypress */
55 void ungetch(int ch)
56 {
57     struct termios oldattr, newattr;
58     tcgetattr( STDIN_FILENO, &oldattr );
59     newattr = oldattr;
60     newattr.c_lflag &= ~( ICANON | ECHO );
61     tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
62     ungetc(ch, stdin);
63     tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
64 }
65 #endif
66
67 int
68 peekch() {
69     int c = getch();
70     //ungetc(c, stdin);
71     ungetch(c);
72     return c;
73 }
74
75
76 // VT100
77
78 #define ASCII_ESC 27
79
80 void vt100Escape(const char * str, ...) {
81     va_list args;
82     va_start(args, str);
83
84     printf("%c", ASCII_ESC);
85     vprintf(str, args);
86 }
87
88 void vt100ClearScreen() { vt100Escape("[2J"); }
89 void vt100CursorHome() { vt100Escape("[H"); }
90 void vt100CursorPos(int v, int h) { vt100Escape("[%d;%dH", v, h); }
91 void vt100SaveCursor() { vt100Escape("7"); }
92 void vt100RestoreCursor() { vt100Escape("8"); }
93
94
95 // JSON
96
97 typedef enum {
98     JSONNodeKind_Nul,
99     JSONNodeKind_Int,
100     JSONNodeKind_Str,
101     JSONNodeKind_Obj,
102     JSONNodeKind_Arr,
103 } JSONNodeKind;
104
105 struct JSONNode;
106 typedef struct JSONNode {
107     JSONNodeKind kind;
108     size_t data;
109     struct JSONNode * parent;
110     struct JSONNode * children;
111     struct JSONNode * next;
112 } JSONNode;
113
114 JSONNode *
115 JSONNodeNew(JSONNodeKind kind, size_t data) {
116     JSONNode * result = NEW(JSONNode);
117     result->kind = kind;
118     result->data = data;
119     return result;
120 }
121
122 JSONNode *
123 JSONNodeNewNul() {
124     return JSONNodeNew(JSONNodeKind_Nul, (size_t)NULL);
125 }
126
127 JSONNode *
128 JSONNodeNewInt(int i) {
129     return JSONNodeNew(JSONNodeKind_Int, (size_t)i);
130 }
131
132 JSONNode *
133 JSONNodeNewStr(const char * str) {
134     return JSONNodeNew(JSONNodeKind_Str, (size_t)str);
135 }
136
137 JSONNode *
138 JSONNodeNewObj() {
139     return JSONNodeNew(JSONNodeKind_Obj, (size_t)NULL);
140 }
141
142 JSONNode *
143 JSONNodeNewArr() {
144     return JSONNodeNew(JSONNodeKind_Arr, (size_t)NULL);
145 }
146
147 JSONNode *
148 JSONNodePush(JSONNode * this, JSONNode * that) {
149     if (this->children == NULL) {
150         this->children = that;
151     }
152     else {
153         JSONNode * lastNode = this->children;
154         while (lastNode->next != NULL)
155             lastNode = lastNode->next;
156         lastNode->next = that;
157     }
158     that->parent = this;
159     that->next = NULL;
160     
161     return that;
162 }
163
164 void
165 JSONNodePop(JSONNode * this) {
166     if (this != NULL) {
167         JSONNode * ptr = this->children;
168
169         if (ptr == NULL) { // no children
170             JSONNodePop(this->parent);
171         }
172         else if (ptr->next == NULL) { // one child
173             this->children = NULL;
174             
175         }
176         else { // more than one child
177             while (ptr->next->next != NULL)
178                 ptr = ptr->next;
179             ptr->next = NULL;
180         }
181     }
182 }
183
184 void
185 Indent(int indent) {
186     for (int i = 0; i < indent; i++)
187         printf("  ");
188 }
189
190 void
191 JSONNodePrint(JSONNode * node) {
192     if (node == NULL)
193         return;
194     
195     static int indent;
196     if (node->parent == NULL)
197         indent = 0;
198     
199     switch (node->kind) {
200     case JSONNodeKind_Nul: {
201         printf("null");
202         break;
203     }
204     case JSONNodeKind_Int: {
205         int i = (int)node->data;
206         printf("%d", i);
207         break;
208     }
209     case JSONNodeKind_Str: {
210         char * str = (char *)node->data;
211         printf("\"%s\"", str == NULL ? "" : str);
212         break;
213     }
214     case JSONNodeKind_Obj: {
215         printf("{\n");
216         JSONNode * ptr = node->children;
217         indent++;
218         while (ptr != NULL) {
219             char * key = (char *)ptr->data;
220             JSONNode * value = ptr->next;
221             Indent(indent);
222             printf("\"%s\": ", key);
223             JSONNodePrint(value);
224             if (ptr->next != NULL)
225                 ptr = ptr->next->next;
226             else
227                 ptr = NULL;
228             printf("%s\n", (ptr == NULL ? "" : ","));
229         }
230         indent--;
231         Indent(indent);
232         printf("}");
233         break;
234     }
235     case JSONNodeKind_Arr: {
236         printf("[ ");
237         JSONNode * ptr = node->children;
238         while (ptr != NULL) {
239             JSONNode * value = ptr;
240             JSONNodePrint(value);
241             ptr = ptr->next;
242             printf("%s", (ptr == NULL ? "" : ", "));
243         }
244         printf(" ]");
245         break;
246     }
247     }
248 }
249
250
251 // Input
252
253 JSONNode * g_Node;
254
255 void
256 Draw(JSONNode * node, const char * str) {
257     vt100ClearScreen();
258     vt100CursorHome();
259     
260     printf("> %s\n\n", str);
261
262     if (node != NULL)
263         JSONNodePrint(node);
264
265     vt100CursorPos(0, strlen(str) + 3);
266 }
267
268 int
269 GetInt() {
270     static char intStr[16];
271     int intStrLen = 0;
272     int result = 0;
273     int c;
274     while ((c = getch()), (c != '\r') && (c != '\n')) {
275         if ((c == 8 || c == 127) && intStrLen > 0) {
276             intStrLen--;
277             intStr[intStrLen] = '\0';
278             result /= 10;
279             Draw(g_Node, intStr);
280         }
281         else if (intStrLen < 16 - 1 && (c >= '0' && c <= '9')) {
282             intStr[intStrLen++] = c;
283             intStr[intStrLen] = '\0';
284             result *= 10;
285             result += c - '0';
286             Draw(g_Node, intStr);
287         }
288     }
289     return result;
290 }
291
292 char *
293 GetStr() {
294     char * str = NEWARR(char, 16);
295     int strLen = 0;
296     int c;
297     while ((c = getch()), (c != '\r') && (c != '\n')) {
298         if ((c == 8 || c == 127) && strLen > 0) {
299             strLen--;
300             str[strLen] = '\0';
301             Draw(g_Node, str);
302         }
303         else if (strLen < 16 - 1) {
304             str[strLen++] = c;
305             str[strLen] = '\0';
306             Draw(g_Node, str);
307         }
308     }
309     return str;
310 }
311
312 JSONNode *
313 GetNode(JSONNode * parent) {
314     int c = getch();
315
316     JSONNode * result = JSONNodeNewNul();
317     
318     if (parent == NULL)
319         g_Node = result;
320
321     if (parent != NULL && result != NULL)
322         JSONNodePush(parent, result);
323
324     switch (c) {
325     case 'i': {
326         result->kind = JSONNodeKind_Int;
327         Draw(g_Node, "");
328         result->data = (size_t)GetInt();
329         Draw(g_Node, "");
330         break;
331     }
332     case 's': {
333         result->kind = JSONNodeKind_Str;
334         Draw(g_Node, "");
335         result->data = (size_t)GetStr();
336         Draw(g_Node, "");
337         break;
338     }
339     case 'o': {
340         result->kind = JSONNodeKind_Obj;
341         Draw(g_Node, "");
342         while ((c = peekch()), (c != '\r') && (c != '\n')) {
343             Draw(g_Node, "");
344
345             JSONNodePush(result, JSONNodeNewStr(GetStr()));
346             Draw(g_Node, "");
347
348             JSONNodePush(result, GetNode(result));
349             Draw(g_Node, "");
350         }
351         getch();
352         break;
353     }
354     case 'a': {
355         result->kind = JSONNodeKind_Arr;
356         Draw(g_Node, "");
357         while ((c = peekch()), (c != '\r') && (c != '\n')) {
358             Draw(g_Node, "");
359
360             JSONNodePush(result, GetNode(result));
361             Draw(g_Node, "");
362         }
363         getch();
364         break;
365     }
366     case 8:
367     case 127:
368         JSONNodePop(parent);
369         Draw(g_Node, "");
370         result = GetNode(parent);
371         break;
372     case 't':
373         result->kind = JSONNodeKind_Int;
374         result->data = (size_t)getch();
375         break;
376     }
377
378     return result;
379 }
380
381 JSONNode *
382 TestNode() {
383     JSONNode * n = JSONNodeNewObj();
384     JSONNode * k1 = JSONNodeNewStr("key 1");
385     JSONNode * v1 = JSONNodeNewObj();
386     JSONNode * k11 = JSONNodeNewStr("key 11");
387     JSONNode * v11 = JSONNodeNewStr("val 11");
388     JSONNode * k12 = JSONNodeNewStr("key 12");
389     JSONNode * v12 = JSONNodeNewStr("val 12");
390     JSONNode * k2 = JSONNodeNewStr("key 2");
391     JSONNode * v2 = JSONNodeNewStr("val 2");
392
393     JSONNodePush(n, k1);
394     JSONNodePush(n, v1);
395     JSONNodePush(n, k2);
396     JSONNodePush(n, v2);
397
398     JSONNodePush(v1, k11);
399     JSONNodePush(v1, v11);
400     JSONNodePush(v1, k12);
401     JSONNodePush(v1, v12);
402
403     return n;
404 }
405
406 int main() {
407     Draw(NULL, "");
408
409     JSONNode * n = GetNode(NULL);
410     //JSONNode * n = TestNode();
411
412     vt100ClearScreen();
413     vt100CursorHome();
414     JSONNodePrint(n);
415     printf("\n");
416
417     // JSONFree(n);
418
419     return 0;
420 }