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