]> gitweb.ps.run Git - iftint/blob - main2.c
thisnthat
[iftint] / main2.c
1 #include <stdio.h>
2 #include <stdarg.h>
3 #include <string.h>
4 #include <stdlib.h>
5
6 // Memory
7
8 #define NEW(TYPE) ((TYPE *)calloc(1, sizeof(TYPE)))
9 #define NEWARR(TYPE, NUM) ((TYPE *)calloc(NUM, sizeof(TYPE)))
10
11
12 // getch()
13
14 #ifdef _WIN32
15 #include <conio.h>
16 #else
17 #include <termios.h>
18 #include <unistd.h>
19 #include <stdio.h>
20
21 /* reads from keypress, doesn't echo */
22 int getch(void)
23 {
24     struct termios oldattr, newattr;
25     int ch;
26     tcgetattr( STDIN_FILENO, &oldattr );
27     newattr = oldattr;
28     newattr.c_lflag &= ~( ICANON | ECHO );
29     tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
30     ch = getchar();
31     tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
32     return ch;
33 }
34
35 /* reads from keypress, echoes */
36 int getche(void)
37 {
38     struct termios oldattr, newattr;
39     int ch;
40     tcgetattr( STDIN_FILENO, &oldattr );
41     newattr = oldattr;
42     newattr.c_lflag &= ~( ICANON );
43     tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
44     ch = getchar();
45     tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
46     return ch;
47 }
48
49 /* ungets keypress */
50 void ungetch(int ch)
51 {
52     struct termios oldattr, newattr;
53     tcgetattr( STDIN_FILENO, &oldattr );
54     newattr = oldattr;
55     newattr.c_lflag &= ~( ICANON | ECHO );
56     tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
57     ungetc(ch, stdin);
58     tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
59 }
60 #endif
61
62 int
63 peekch() {
64     int c = getch();
65     //ungetc(c, stdin);
66     ungetch(c);
67     return c;
68 }
69
70
71 // VT100
72
73 #define ASCII_ESC 27
74
75 void vt100Escape(const char * str, ...) {
76     va_list args;
77     va_start(args, str);
78
79     printf("%c", ASCII_ESC);
80     vprintf(str, args);
81 }
82
83 void vt100ClearScreen() { vt100Escape("[2J"); }
84 void vt100CursorHome() { vt100Escape("[H"); }
85 void vt100CursorPos(int v, int h) { vt100Escape("[%d;%dH", v, h); }
86 void vt100SaveCursor() { vt100Escape("7"); }
87 void vt100RestoreCursor() { vt100Escape("8"); }
88
89
90 // JSON
91
92 typedef enum {
93     JSONNodeKind_Nul,
94     JSONNodeKind_Str,
95     JSONNodeKind_Obj,
96 } JSONNodeKind;
97
98 struct JSONNode;
99 typedef struct JSONNode {
100     JSONNodeKind kind;
101     size_t data;
102     struct JSONNode * parent;
103     struct JSONNode * children;
104     struct JSONNode * next;
105 } JSONNode;
106
107 JSONNode *
108 JSONNodeNew(JSONNodeKind kind, size_t data) {
109     JSONNode * result = NEW(JSONNode);
110     result->kind = kind;
111     result->data = data;
112     return result;
113 }
114
115 JSONNode *
116 JSONNodeNewStr(const char * str) {
117     return JSONNodeNew(JSONNodeKind_Str, (size_t)str);
118 }
119
120 JSONNode *
121 JSONNodeNewObj() {
122     return JSONNodeNew(JSONNodeKind_Obj, (size_t)NULL);
123 }
124
125 JSONNode *
126 JSONNodeNewNul() {
127     return JSONNodeNew(JSONNodeKind_Nul, (size_t)NULL);
128 }
129
130 JSONNode *
131 JSONNodeAppend(JSONNode * this, JSONNode * that) {
132     if (this->children == NULL) {
133         this->children = that;
134     }
135     else {
136         JSONNode * lastNode = this->children;
137         while (lastNode->next != NULL)
138             lastNode = lastNode->next;
139         lastNode->next = that;
140     }
141     that->parent = this;
142     that->next = NULL;
143     
144     return that;
145 }
146
147 void
148 Indent(int indent) {
149     for (int i = 0; i < indent; i++)
150         printf("  ");
151 }
152
153 void
154 JSONNodePrint(JSONNode * node) {
155     if (node == NULL)
156         return;
157     
158     static int indent;
159     if (node->parent == NULL)
160         indent = 0;
161     
162     switch (node->kind) {
163     case JSONNodeKind_Nul: {
164         printf("null");
165         break;
166     }
167     case JSONNodeKind_Str: {
168         char * str = (char *)node->data;
169         printf("\"%s\"", str == NULL ? "" : str);
170         break;
171     }
172     case JSONNodeKind_Obj: {
173         printf("{\n");
174         JSONNode * ptr = node->children;
175         indent++;
176         while (ptr != NULL) {
177             char * key = (char *)ptr->data;
178             JSONNode * value = ptr->next;
179             Indent(indent);
180             printf("\"%s\": ", key);
181             JSONNodePrint(value);
182             if (ptr->next != NULL)
183                 ptr = ptr->next->next;
184             else
185                 ptr = NULL;
186             printf("%s\n", (ptr == NULL ? "" : ","));
187         }
188         indent--;
189         Indent(indent);
190         printf("}");
191         break;
192     }
193     }
194 }
195
196
197 // Input
198
199 JSONNode * g_Node;
200
201 void
202 Draw(JSONNode * node, const char * str) {
203     vt100ClearScreen();
204     vt100CursorHome();
205     
206     printf("> %s\n\n", str);
207
208     if (node != NULL)
209         JSONNodePrint(node);
210
211     vt100CursorPos(0, strlen(str) + 3);
212 }
213
214 char *
215 GetStr() {
216     char * str = NEWARR(char, 16);
217     int strLen = 0;
218     int c;
219     while ((c = getch()), (c != '\r') && (c != '\n')) {
220         if (strLen < 16 - 1) {
221             str[strLen++] = c;
222             str[strLen] = '\0';
223             Draw(g_Node, str);
224         }
225     }
226     return str;
227 }
228
229 JSONNode *
230 GetNode(JSONNode * parent) {
231     int c = getch();
232
233     JSONNode * result = JSONNodeNewNul();
234     
235     if (parent == NULL)
236         g_Node = result;
237
238     if (parent != NULL && result != NULL)
239         JSONNodeAppend(parent, result);
240
241     switch (c) {
242     case 's': {
243         result->kind = JSONNodeKind_Str;
244         Draw(g_Node, "");
245         result->data = (size_t)GetStr();
246         Draw(g_Node, "");
247         break;
248     }
249     case 'o': {
250         result->kind = JSONNodeKind_Obj;
251         Draw(g_Node, "");
252         while ((c = peekch()), (c != '\r') && (c != '\n')) {
253             Draw(g_Node, "");
254
255             JSONNodeAppend(result, JSONNodeNewStr(GetStr()));
256             Draw(g_Node, "");
257
258             JSONNodeAppend(result, GetNode(result));
259             Draw(g_Node, "");
260         }
261         getch();
262     }
263     }
264
265     return result;
266 }
267
268 JSONNode *
269 TestNode() {
270     JSONNode * n = JSONNodeNewObj();
271     JSONNode * k1 = JSONNodeNewStr("key 1");
272     JSONNode * v1 = JSONNodeNewObj();
273     JSONNode * k11 = JSONNodeNewStr("key 11");
274     JSONNode * v11 = JSONNodeNewStr("val 11");
275     JSONNode * k12 = JSONNodeNewStr("key 12");
276     JSONNode * v12 = JSONNodeNewStr("val 12");
277     JSONNode * k2 = JSONNodeNewStr("key 2");
278     JSONNode * v2 = JSONNodeNewStr("val 2");
279
280     JSONNodeAppend(n, k1);
281     JSONNodeAppend(n, v1);
282     JSONNodeAppend(n, k2);
283     JSONNodeAppend(n, v2);
284
285     JSONNodeAppend(v1, k11);
286     JSONNodeAppend(v1, v11);
287     JSONNodeAppend(v1, k12);
288     JSONNodeAppend(v1, v12);
289
290     return n;
291 }
292
293 int main() {
294     Draw(NULL, "");
295
296     JSONNode * n = GetNode(NULL);
297     //JSONNode * n = TestNode();
298
299     vt100ClearScreen();
300     vt100CursorHome();
301     JSONNodePrint(n);
302
303     // JSONFree(n);
304
305     return 0;
306 }