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;
324 InputState_Primitive,
329 InputState inputState;
331 bool editingNode = false;
340 if (node == NULL || node->parent == NULL)
343 if (node->parent->kind == JSONNodeKind_Obj) // editing obj key
344 g_CurrNode = node = node->firstChild;
345 else if (node->parent->kind == JSONNodeKind_Str) // editing obj value
346 g_CurrNode = node = node->parent->parent;
348 g_CurrNode = node = node->parent;
350 editingNode = JSONNodeEditable(node);
355 if (JSONNodeEditable(node) && editingNode) {
356 if (node->data == (size_t)NULL) {
357 node->data = (size_t)NEWARR(char, 16);
360 char * str = (char *)node->data;
362 if (isBackspace(c)) {
363 str[strLen-1] = '\0';
366 else if (strLen < 16 - 1) {
368 str[strLen+1] = '\0';
373 JSONNode * old = node;
375 /**/ if (c == 'i') { node = JSONNodeNew(JSONNodeKind_Int); editingNode = true; }
376 else if (c == 's') { node = JSONNodeNew(JSONNodeKind_Str); editingNode = true; }
377 else if (c == 'o') { node = JSONNodeNew(JSONNodeKind_Obj); }
378 else if (c == 'a') { node = JSONNodeNew(JSONNodeKind_Arr); }
379 else if (c == 'h') { if (node->prev != NULL) g_CurrNode = node = node->prev; continue; }
380 else if (c == 'l') { if (node->next != NULL) g_CurrNode = node = node->next; continue; }
381 else if (c == 'k') { if (node->parent != NULL) g_CurrNode = node = node->parent; continue; }
382 else if (c == 'j') { if (node->firstChild != NULL) g_CurrNode = node = node->firstChild; continue; }
383 else if (c == ' ') { if (JSONNodeEditable(node)) editingNode = true; continue; }
384 else if (isBackspace(c) && node != NULL) { g_CurrNode = node = JSONNodeRemove(node); continue; }
388 // new node was added to an object
389 if (old->kind == JSONNodeKind_Obj) {
390 JSONNode * keyNode = JSONNodeNew(JSONNodeKind_Str);
391 JSONNodePush(keyNode, node);
395 JSONNodePush(old, node);
398 g_DrawNode = result = node;
412 vt100EnableAlternateBuffer();
414 JSONNode * n = GetNode();
416 vt100DisableAlternateBuffer();
418 JSONNodePrint(n, NULL);