8 - whitelist input on GetStr/GetInt
13 #define NEW(TYPE) ((TYPE *)calloc(1, sizeof(TYPE)))
14 #define NEWARR(TYPE, NUM) ((TYPE *)calloc(NUM, sizeof(TYPE)))
20 charInString(char c, const char * str) {
21 for (int i = 0; i < strlen(str); i++)
29 return c == '\n' || c == '\r';
33 return c == 8 || c == 127;
40 #define KEY_BACKSPACE1 8
41 #define KEY_BACKSPACE2 127
50 #include <sys/ioctl.h>
55 /* reads from keypress, doesn't echo */
58 struct termios oldattr, newattr;
60 tcgetattr( STDIN_FILENO, &oldattr );
62 newattr.c_lflag &= ~( ICANON | ECHO ); // no ECHO for echo(?)
63 tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
65 tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
72 struct termios oldattr, newattr;
73 tcgetattr( STDIN_FILENO, &oldattr );
75 newattr.c_lflag &= ~( ICANON | ECHO );
76 tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
78 tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
95 void vt100Escape(const char * str, ...) {
99 printf("%c", ASCII_ESC);
103 void vt100ClearScreen() { vt100Escape("[2J"); }
104 void vt100CursorHome() { vt100Escape("[H"); }
105 void vt100CursorPos(int v, int h) { vt100Escape("[%d;%dH", v, h); }
106 void vt100SaveCursor() { vt100Escape("7"); }
107 void vt100RestoreCursor() { vt100Escape("8"); }
108 // void vt100GetCursor(int * v, int * h) {
110 // printf("\033[6n");
113 // while ((c = getch()) != ';')
114 // *v = (10*(*v)+(c-'0'));
115 // while ((c = getch()) != 'R')
116 // *h = (10*(*h)+(c-'0'));
118 void vt100GetScreenSize(int * v, int * h) {
120 CONSOLE_SCREEN_BUFFER_INFO csbi;
121 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
122 *h = csbi.srWindow.Right - csbi.srWindow.Left + 1;
123 *v = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
126 ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
131 void vt100EnableAlternateBuffer() { vt100Escape("[?1049h"); }
132 void vt100DisableAlternateBuffer() { vt100Escape("[?1049l"); }
148 typedef struct JSONNode {
151 struct JSONNode * parent;
152 struct JSONNode * firstChild;
154 struct JSONNode * prev;
155 struct JSONNode * next;
159 JSONNodeNew(JSONNodeKind kind) {
160 JSONNode * result = NEW(JSONNode);
166 JSONNodePush(JSONNode * this, JSONNode * that) {
167 if (this->firstChild == NULL) {
168 this->firstChild = that;
171 JSONNode * lastNode = this->firstChild;
172 while (lastNode->next != NULL)
173 lastNode = lastNode->next;
174 lastNode->next = that;
175 that->prev = lastNode;
184 JSONNodeRemove(JSONNode * node) {
185 if (node->prev == NULL) { // first child
186 node->parent->firstChild = node->next;
187 if (node->next != NULL)
188 node->next->prev = NULL;
191 else { // second child
192 node->prev->next = node->next;
193 if (node->next != NULL)
194 node->next->prev = node->prev;
200 JSONNodeEditable(JSONNode * node) {
201 if (node == NULL) return false;
202 else if (node->kind == JSONNodeKind_Int) return true;
203 else if (node->kind == JSONNodeKind_Str) return true;
209 for (int i = 0; i < indent; i++)
214 JSONNodePrint(JSONNode * node, JSONNode * currNode) {
219 if (node->parent == NULL)
222 if (currNode == node) {
226 switch (node->kind) {
227 case JSONNodeKind_Nul: {
231 case JSONNodeKind_Int: {
232 char * str = (char *)node->data;
233 printf("%s", (str == NULL || strlen(str) == 0) ? "0" : str);
236 case JSONNodeKind_Str: {
237 char * str = (char *)node->data;
238 printf("\"%s\"", str == NULL ? "" : str);
241 case JSONNodeKind_Obj: {
243 JSONNode * ptr = node->firstChild;
245 while (ptr != NULL) {
247 JSONNodePrint(ptr, currNode);
248 JSONNodePrint(ptr->firstChild, currNode);
249 if (ptr->next != NULL)
259 case JSONNodeKind_Key: {
260 char * str = (char *)node->data;
261 printf("\"%s\": ", str == NULL ? "" : str);
264 case JSONNodeKind_Arr: {
266 JSONNode * ptr = node->firstChild;
268 while (ptr != NULL) {
270 JSONNodePrint(ptr, currNode);
271 if (ptr->next != NULL)
287 JSONNode * g_DrawNode = NULL;
288 JSONNode * g_CurrNode = NULL;
295 if (g_DrawNode != NULL) {
296 JSONNodePrint(g_DrawNode, g_CurrNode);
297 vt100RestoreCursor();
315 typedef bool(*CharPredicateFunc)(char, int);
317 bool predStr(char c, int i) { return c >= 'a' && c <= 'z'; }
318 bool predInt(char c, int i) { return c >= '0' && c <= '9'; }
321 GetInput(JSONNode * node, char c) {
322 if (node->data == (size_t)NULL) {
323 node->data = (size_t)NEWARR(char, 16);
326 char * str = (char *)node->data;
327 int strLen = strlen(str);
329 if (isBackspace(c)) {
330 str[strLen-1] = '\0';
332 else if (strLen < 16 - 1) {
334 str[strLen+1] = '\0';
340 JSONNode * result = NULL;
341 JSONNode * node = NULL;
344 bool editingNode = false;
354 /**/ if (c == 'i') { node = JSONNodeNew(JSONNodeKind_Int); editingNode = true; }
355 else if (c == 's') { node = JSONNodeNew(JSONNodeKind_Str); editingNode = true; }
356 else if (c == 'o') { node = JSONNodeNew(JSONNodeKind_Obj); editingNode = true; }
357 else if (c == 'a') { node = JSONNodeNew(JSONNodeKind_Arr); editingNode = true; }
358 g_DrawNode = g_CurrNode = result = node;
360 else if (node->kind ==JSONNodeKind_Int) {
365 /**/ if (c == 'i' && node->parent != NULL) { node = JSONNodePush(node->parent, JSONNodeNew(JSONNodeKind_Int)); editingNode = true; }
366 else if (c == 's' && node->parent != NULL) { node = JSONNodePush(node->parent, JSONNodeNew(JSONNodeKind_Str)); editingNode = true; }
367 else if (c == 'o' && node->parent != NULL) { node = JSONNodePush(node->parent, JSONNodeNew(JSONNodeKind_Obj)); editingNode = true; }
368 else if (c == 'a' && node->parent != NULL) { node = JSONNodePush(node->parent, JSONNodeNew(JSONNodeKind_Arr)); editingNode = true; }
369 else if (c == 'h') { if (node->prev != NULL) g_CurrNode = node = node->prev; }
370 else if (c == 'l') { if (node->next != NULL) g_CurrNode = node = node->next; }
371 else if (c == 'k') { if (node->parent != NULL) g_CurrNode = node = node->parent; }
372 else if (c == 'j') { if (node->firstChild != NULL) g_CurrNode = node = node->firstChild; }
373 else if (c == ' ') { editingNode = true; }
374 else if (isBackspace(c)) { g_CurrNode = node = JSONNodeRemove(node); }
379 else if (node->kind ==JSONNodeKind_Str) {
384 /**/ if (c == 'i' && node->parent != NULL) { node = JSONNodePush(node->parent, JSONNodeNew(JSONNodeKind_Int)); editingNode = true; }
385 else if (c == 's' && node->parent != NULL) { node = JSONNodePush(node->parent, JSONNodeNew(JSONNodeKind_Str)); editingNode = true; }
386 else if (c == 'o' && node->parent != NULL) { node = JSONNodePush(node->parent, JSONNodeNew(JSONNodeKind_Obj)); editingNode = true; }
387 else if (c == 'a' && node->parent != NULL) { node = JSONNodePush(node->parent, JSONNodeNew(JSONNodeKind_Arr)); editingNode = true; }
388 else if (c == 'h') { if (node->prev != NULL) g_CurrNode = node = node->prev; }
389 else if (c == 'l') { if (node->next != NULL) g_CurrNode = node = node->next; }
390 else if (c == 'k') { if (node->parent != NULL) g_CurrNode = node = node->parent; }
391 else if (c == 'j') { if (node->firstChild != NULL) g_CurrNode = node = node->firstChild; }
392 else if (c == ' ') { editingNode = true; }
393 else if (isBackspace(c)) { g_CurrNode = node = JSONNodeRemove(node); }
398 else if (node->kind ==JSONNodeKind_Obj) {
403 /**/ if (c == 'i' && node->parent != NULL) { node = JSONNodePush(node->parent, JSONNodeNew(JSONNodeKind_Int)); editingNode = true; }
404 else if (c == 's' && node->parent != NULL) { node = JSONNodePush(node->parent, JSONNodeNew(JSONNodeKind_Str)); editingNode = true; }
405 else if (c == 'o' && node->parent != NULL) { node = JSONNodePush(node->parent, JSONNodeNew(JSONNodeKind_Obj)); editingNode = true; }
406 else if (c == 'a' && node->parent != NULL) { node = JSONNodePush(node->parent, JSONNodeNew(JSONNodeKind_Arr)); editingNode = true; }
407 else if (c == 'h') { if (node->prev != NULL) g_CurrNode = node = node->prev; }
408 else if (c == 'l') { if (node->next != NULL) g_CurrNode = node = node->next; }
409 else if (c == 'k') { if (node->parent != NULL) g_CurrNode = node = node->parent; }
410 else if (c == 'j') { if (node->firstChild != NULL) g_CurrNode = node = node->firstChild; }
411 else if (c == ' ') { editingNode = true; }
412 else if (isBackspace(c)) { g_CurrNode = node = JSONNodeRemove(node); }
417 else if (node->kind ==JSONNodeKind_Key) {
422 /**/ if (c == 'i' && node->parent != NULL) { node = JSONNodePush(node->parent, JSONNodeNew(JSONNodeKind_Int)); editingNode = true; }
423 else if (c == 's' && node->parent != NULL) { node = JSONNodePush(node->parent, JSONNodeNew(JSONNodeKind_Str)); editingNode = true; }
424 else if (c == 'o' && node->parent != NULL) { node = JSONNodePush(node->parent, JSONNodeNew(JSONNodeKind_Obj)); editingNode = true; }
425 else if (c == 'a' && node->parent != NULL) { node = JSONNodePush(node->parent, JSONNodeNew(JSONNodeKind_Arr)); editingNode = true; }
426 else if (c == 'h') { if (node->prev != NULL) g_CurrNode = node = node->prev; }
427 else if (c == 'l') { if (node->next != NULL) g_CurrNode = node = node->next; }
428 else if (c == 'k') { if (node->parent != NULL) g_CurrNode = node = node->parent; }
429 else if (c == 'j') { if (node->firstChild != NULL) g_CurrNode = node = node->firstChild; }
430 else if (c == ' ') { editingNode = true; }
431 else if (isBackspace(c)) { g_CurrNode = node = JSONNodeRemove(node); }
436 else if (node->kind ==JSONNodeKind_Arr) {
441 /**/ if (c == 'i' && node->parent != NULL) { node = JSONNodePush(node->parent, JSONNodeNew(JSONNodeKind_Int)); editingNode = true; }
442 else if (c == 's' && node->parent != NULL) { node = JSONNodePush(node->parent, JSONNodeNew(JSONNodeKind_Str)); editingNode = true; }
443 else if (c == 'o' && node->parent != NULL) { node = JSONNodePush(node->parent, JSONNodeNew(JSONNodeKind_Obj)); editingNode = true; }
444 else if (c == 'a' && node->parent != NULL) { node = JSONNodePush(node->parent, JSONNodeNew(JSONNodeKind_Arr)); editingNode = true; }
445 else if (c == 'h') { if (node->prev != NULL) g_CurrNode = node = node->prev; }
446 else if (c == 'l') { if (node->next != NULL) g_CurrNode = node = node->next; }
447 else if (c == 'k') { if (node->parent != NULL) g_CurrNode = node = node->parent; }
448 else if (c == 'j') { if (node->firstChild != NULL) g_CurrNode = node = node->firstChild; }
449 else if (c == ' ') { editingNode = true; }
450 else if (isBackspace(c)) { g_CurrNode = node = JSONNodeRemove(node); }
464 vt100EnableAlternateBuffer();
466 JSONNode * n = GetNode();
468 vt100DisableAlternateBuffer();
470 JSONNodePrint(n, NULL);