]> gitweb.ps.run Git - iftint/blob - main2.c
PeekChar -> peeckh (?)
[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 void vt100GetScreenSize(int * v, int * h) {
94     *v = *h = 0;
95     vt100CursorPos(1000000, 1000000);
96     printf("\033[6n");
97     getch(); getch();
98     int c;
99     while ((c = getch()) != ';')
100         *v = (10*(*v)+(c-'0'));
101     while ((c = getch()) != 'R')
102         *h = (10*(*h)+(c-'0'));
103 }
104
105
106 // JSON
107
108 typedef enum {
109     JSONNodeKind_Nul,
110     JSONNodeKind_Int,
111     JSONNodeKind_Str,
112     JSONNodeKind_Obj,
113     JSONNodeKind_Arr,
114 } JSONNodeKind;
115
116 struct JSONNode;
117 typedef struct JSONNode {
118     JSONNodeKind kind;
119     size_t data;
120     struct JSONNode * parent;
121     struct JSONNode * children;
122     struct JSONNode * next;
123 } JSONNode;
124
125 JSONNode *
126 JSONNodeNew(JSONNodeKind kind, size_t data) {
127     JSONNode * result = NEW(JSONNode);
128     result->kind = kind;
129     result->data = data;
130     return result;
131 }
132
133 JSONNode *
134 JSONNodeNewNul() {
135     return JSONNodeNew(JSONNodeKind_Nul, (size_t)NULL);
136 }
137
138 JSONNode *
139 JSONNodeNewInt(int i) {
140     return JSONNodeNew(JSONNodeKind_Int, (size_t)i);
141 }
142
143 JSONNode *
144 JSONNodeNewStr(const char * str) {
145     return JSONNodeNew(JSONNodeKind_Str, (size_t)str);
146 }
147
148 JSONNode *
149 JSONNodeNewObj() {
150     return JSONNodeNew(JSONNodeKind_Obj, (size_t)NULL);
151 }
152
153 JSONNode *
154 JSONNodeNewArr() {
155     return JSONNodeNew(JSONNodeKind_Arr, (size_t)NULL);
156 }
157
158 JSONNode *
159 JSONNodePush(JSONNode * this, JSONNode * that) {
160     if (this->children == NULL) {
161         this->children = that;
162     }
163     else {
164         JSONNode * lastNode = this->children;
165         while (lastNode->next != NULL)
166             lastNode = lastNode->next;
167         lastNode->next = that;
168     }
169     that->parent = this;
170     that->next = NULL;
171     
172     return that;
173 }
174
175 void
176 JSONNodePop(JSONNode * this) {
177     if (this != NULL) {
178         JSONNode * ptr = this->children;
179
180         if (ptr == NULL) { // no children
181             JSONNodePop(this->parent);
182         }
183         else if (ptr->next == NULL) { // one child
184             this->children = NULL;
185             
186         }
187         else { // more than one child
188             while (ptr->next->next != NULL)
189                 ptr = ptr->next;
190             ptr->next = NULL;
191         }
192     }
193 }
194
195 void
196 Indent(int indent) {
197     for (int i = 0; i < indent; i++)
198         printf("  ");
199 }
200
201 void
202 JSONNodePrint(JSONNode * node) {
203     if (node == NULL)
204         return;
205     
206     static int indent;
207     if (node->parent == NULL)
208         indent = 0;
209     
210     switch (node->kind) {
211     case JSONNodeKind_Nul: {
212         printf("null");
213         break;
214     }
215     case JSONNodeKind_Int: {
216         int i = (int)node->data;
217         printf("%d", i);
218         break;
219     }
220     case JSONNodeKind_Str: {
221         char * str = (char *)node->data;
222         printf("\"%s\"", str == NULL ? "" : str);
223         break;
224     }
225     case JSONNodeKind_Obj: {
226         printf("{\n");
227         JSONNode * ptr = node->children;
228         indent++;
229         while (ptr != NULL) {
230             char * key = (char *)ptr->data;
231             JSONNode * value = ptr->next;
232             Indent(indent);
233             printf("\"%s\": ", key);
234             JSONNodePrint(value);
235             if (ptr->next != NULL)
236                 ptr = ptr->next->next;
237             else
238                 ptr = NULL;
239             printf("%s\n", (ptr == NULL ? "" : ","));
240         }
241         indent--;
242         Indent(indent);
243         printf("}");
244         break;
245     }
246     case JSONNodeKind_Arr: {
247         printf("[ ");
248         JSONNode * ptr = node->children;
249         while (ptr != NULL) {
250             JSONNode * value = ptr;
251             JSONNodePrint(value);
252             ptr = ptr->next;
253             printf("%s", (ptr == NULL ? "" : ", "));
254         }
255         printf(" ]");
256         break;
257     }
258     }
259 }
260
261
262 // Input
263
264 JSONNode * g_DrawNode = NULL;
265 const char * g_DrawStr = "";
266
267 void
268 Draw(void) {
269     vt100ClearScreen();
270     vt100CursorHome();
271     
272     if (g_DrawNode != NULL)
273         JSONNodePrint(g_DrawNode);
274
275     int v, h;
276     vt100GetScreenSize(&v, &h);
277     vt100CursorPos(v, 0);
278     printf("> %s", g_DrawStr);
279
280     vt100CursorPos(v, strlen(g_DrawStr) + 3);
281 }
282
283 int
284 GetChar() {
285     Draw();
286     int c = getch();
287     return c;
288 }
289
290 int
291 PeekChar() {
292     int c = GetChar();
293     ungetch(c);
294     return c;
295 }
296
297 int
298 GetInt() {
299     static char intStr[16];
300     intStr[0] = '\0';
301     int intStrLen = 0;
302     int result = 0;
303     int c;
304     g_DrawStr = intStr;
305     while ((c = GetChar()), (c != '\r') && (c != '\n')) {
306         if ((c == 8 || c == 127) && intStrLen > 0) {
307             intStrLen--;
308             intStr[intStrLen] = '\0';
309             result /= 10;
310         }
311         else if (intStrLen < 16 - 1 && (c >= '0' && c <= '9')) {
312             intStr[intStrLen++] = c;
313             intStr[intStrLen] = '\0';
314             result *= 10;
315             result += c - '0';
316         }
317     }
318     g_DrawStr = "";
319     return result;
320 }
321
322 char *
323 GetStr() {
324     char * str = NEWARR(char, 16);
325     int strLen = 0;
326     int c;
327     g_DrawStr = str;
328     while ((c = GetChar()), (c != '\r') && (c != '\n')) {
329         if ((c == 8 || c == 127) && strLen > 0) {
330             strLen--;
331             str[strLen] = '\0';
332         }
333         else if (strLen < 16 - 1) {
334             str[strLen++] = c;
335             str[strLen] = '\0';
336         }
337     }
338     g_DrawStr = "";
339     return str;
340 }
341
342 JSONNode *
343 GetNode(JSONNode * parent) {
344     int c = GetChar();
345
346     JSONNode * result = JSONNodeNewNul();
347     
348     if (parent == NULL)
349         g_DrawNode = result;
350
351     if (parent != NULL && result != NULL)
352         JSONNodePush(parent, result);
353
354     switch (c) {
355     case 'i': {
356         result->kind = JSONNodeKind_Int;
357         result->data = (size_t)GetInt();
358         break;
359     }
360     case 's': {
361         result->kind = JSONNodeKind_Str;
362         result->data = (size_t)GetStr();
363         break;
364     }
365     case 'o': {
366         result->kind = JSONNodeKind_Obj;
367         while ((c = peekch()), (c != '\r') && (c != '\n')) {
368             JSONNodePush(result, JSONNodeNewStr(GetStr()));
369
370             JSONNodePush(result, GetNode(result));
371         }
372         getch();
373         break;
374     }
375     case 'a': {
376         result->kind = JSONNodeKind_Arr;
377         while ((c = peekch()), (c != '\r') && (c != '\n')) {
378             JSONNodePush(result, GetNode(result));
379         }
380         getch();
381         break;
382     }
383     case 8:
384     case 127:
385         JSONNodePop(parent);
386         result = GetNode(parent);
387         break;
388     case 't':
389         result->kind = JSONNodeKind_Int;
390         result->data = (size_t)GetChar();
391         break;
392     }
393
394     return result;
395 }
396
397
398
399
400 int main() {
401     Draw();
402
403     JSONNode * n = GetNode(NULL);
404     //JSONNode * n = TestNode();
405
406     vt100ClearScreen();
407     vt100CursorHome();
408     JSONNodePrint(n);
409     printf("\n");
410
411     // JSONFree(n);
412
413     return 0;
414 }