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