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"); }
147 typedef struct JSONNode {
150 struct JSONNode * parent;
151 struct JSONNode * firstChild;
153 struct JSONNode * prev;
154 struct JSONNode * next;
158 JSONNodeNew(JSONNodeKind kind) {
159 JSONNode * result = NEW(JSONNode);
165 JSONNodePush(JSONNode * this, JSONNode * that) {
166 if (this->firstChild == NULL) {
167 this->firstChild = that;
170 JSONNode * lastNode = this->firstChild;
171 while (lastNode->next != NULL)
172 lastNode = lastNode->next;
173 lastNode->next = that;
174 that->prev = lastNode;
183 JSONNodeRemove(JSONNode * node) {
184 if (node->prev == NULL) { // first child
185 node->parent->firstChild = node->next;
186 if (node->next != NULL)
187 node->next->prev = NULL;
190 else { // second child
191 node->prev->next = node->next;
192 if (node->next != NULL)
193 node->next->prev = node->prev;
199 JSONNodeEditable(JSONNode * node) {
200 if (node == NULL) return false;
201 else if (node->kind == JSONNodeKind_Int) return true;
202 else if (node->kind == JSONNodeKind_Str) return true;
208 for (int i = 0; i < indent; i++)
213 JSONNodePrint(JSONNode * node, JSONNode * currNode) {
218 if (node->parent == NULL)
221 if (currNode == node) {
225 switch (node->kind) {
226 case JSONNodeKind_Nul: {
230 case JSONNodeKind_Int: {
231 char * str = (char *)node->data;
232 printf("%s", (str == NULL || strlen(str) == 0) ? "0" : str);
235 case JSONNodeKind_Str: {
236 char * str = (char *)node->data;
237 printf("\"%s\"", str == NULL ? "" : str);
240 case JSONNodeKind_Obj: {
242 JSONNode * ptr = node->firstChild;
244 while (ptr != NULL) {
246 JSONNodePrint(ptr, currNode);
248 JSONNodePrint(ptr->firstChild, currNode);
249 if (ptr->next != NULL)
259 case JSONNodeKind_Arr: {
261 JSONNode * ptr = node->firstChild;
263 while (ptr != NULL) {
265 JSONNodePrint(ptr, currNode);
266 if (ptr->next != NULL)
282 JSONNode * g_DrawNode = NULL;
283 JSONNode * g_CurrNode = NULL;
290 if (g_DrawNode != NULL) {
291 JSONNodePrint(g_DrawNode, g_CurrNode);
292 vt100RestoreCursor();
310 typedef bool(*CharPredicateFunc)(char, int);
312 bool predStr(char c, int i) { return c >= 'a' && c <= 'z'; }
313 bool predInt(char c, int i) { return c >= '0' && c <= '9'; }
317 JSONNode * result = NULL;
318 JSONNode * node = NULL;
322 bool editingNode = false;
331 if (node->data == (size_t)NULL) {
332 node->data = (size_t)NEWARR(char, 16);
339 char * str = (char *)node->data;
341 if (isBackspace(c)) {
342 str[strLen-1] = '\0';
345 else if (strLen < 16 - 1) {
347 str[strLen+1] = '\0';
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); }
357 else if (c == 'a') { node = JSONNodeNew(JSONNodeKind_Arr); }
358 g_DrawNode = g_CurrNode = result = node;
360 else if (node->kind == JSONNodeKind_Int) {
361 /**/ if (c == 'h') { if (node->prev != NULL) g_CurrNode = node = node->prev; }
362 else if (c == 'l') { if (node->next != NULL) g_CurrNode = node = node->next; }
363 else if (c == 'k') { if (node->parent != NULL) g_CurrNode = node = node->parent; }
364 else if (c == 'j') { if (node->firstChild != NULL) g_CurrNode = node = node->firstChild; }
365 else if (c == ' ') { if (JSONNodeEditable(node)) editingNode = true; }
366 else if (isBackspace(c)) { g_CurrNode = node = JSONNodeRemove(node); }
368 else if (node->kind == JSONNodeKind_Str) {
369 /**/ 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 == ' ') { if (JSONNodeEditable(node)) editingNode = true; }
374 else if (isBackspace(c)) { g_CurrNode = node = JSONNodeRemove(node); }
376 else if (node->kind == JSONNodeKind_Obj) {
377 /**/ if (c == 'i') { node = JSONNodePush(node, JSONNodePush(JSONNodeNew(JSONNodeKind_Str), JSONNodeNew(JSONNodeKind_Int))->parent); editingNode = true; }
378 else if (c == 's') { node = JSONNodePush(node, JSONNodePush(JSONNodeNew(JSONNodeKind_Str), JSONNodeNew(JSONNodeKind_Str))->parent); editingNode = true; }
379 else if (c == 'o') { node = JSONNodePush(node, JSONNodePush(JSONNodeNew(JSONNodeKind_Str), JSONNodeNew(JSONNodeKind_Obj))->parent); editingNode = true; }
380 else if (c == 'a') { node = JSONNodePush(node, JSONNodePush(JSONNodeNew(JSONNodeKind_Str), JSONNodeNew(JSONNodeKind_Arr))->parent); editingNode = true; }
382 else if (c == 'h') { if (node->prev != NULL) g_CurrNode = node = node->prev; }
383 else if (c == 'l') { if (node->next != NULL) g_CurrNode = node = node->next; }
384 else if (c == 'k') { if (node->parent != NULL) g_CurrNode = node = node->parent; }
385 else if (c == 'j') { if (node->firstChild != NULL) g_CurrNode = node = node->firstChild; }
386 else if (isBackspace(c)) { node = JSONNodeRemove(node); }
390 else if (node->kind == JSONNodeKind_Arr) {
391 /**/ if (c == 'i') { node = JSONNodePush(node, JSONNodeNew(JSONNodeKind_Int)); editingNode = true; }
392 else if (c == 's') { node = JSONNodePush(node, JSONNodeNew(JSONNodeKind_Str)); editingNode = true; }
393 else if (c == 'o') { node = JSONNodePush(node, JSONNodeNew(JSONNodeKind_Obj)); }
394 else if (c == 'a') { node = JSONNodePush(node, JSONNodeNew(JSONNodeKind_Arr)); }
396 else if (c == 'h') { if (node->prev != NULL) g_CurrNode = node = node->prev; }
397 else if (c == 'l') { if (node->next != NULL) g_CurrNode = node = node->next; }
398 else if (c == 'k') { if (node->parent != NULL) g_CurrNode = node = node->parent; }
399 else if (c == 'j') { if (node->firstChild != NULL) g_CurrNode = node = node->firstChild; }
400 else if (isBackspace(c)) { node = JSONNodeRemove(node); }
414 vt100EnableAlternateBuffer();
416 JSONNode * n = GetNode();
418 vt100DisableAlternateBuffer();
420 JSONNodePrint(n, NULL);