X-Git-Url: https://gitweb.ps.run/iftint/blobdiff_plain/019601bd93d99698c528f57a6a356944b1e46517..4889cf922e51c34f714941498d25588ceb258e67:/main2.c diff --git a/main2.c b/main2.c index 47e11ee..86cc7b7 100644 --- a/main2.c +++ b/main2.c @@ -2,6 +2,11 @@ #include #include #include +#include + +/* TODO +- whitelist input on GetStr/GetInt +*/ // Memory @@ -9,11 +14,13 @@ #define NEWARR(TYPE, NUM) ((TYPE *)calloc(NUM, sizeof(TYPE))) -// getch() +// getch #ifdef _WIN32 +#include #include #else +#include #include #include #include @@ -25,21 +32,7 @@ int getch(void) int ch; tcgetattr( STDIN_FILENO, &oldattr ); newattr = oldattr; - newattr.c_lflag &= ~( ICANON | ECHO ); - tcsetattr( STDIN_FILENO, TCSANOW, &newattr ); - ch = getchar(); - tcsetattr( STDIN_FILENO, TCSANOW, &oldattr ); - return ch; -} - -/* reads from keypress, echoes */ -int getche(void) -{ - struct termios oldattr, newattr; - int ch; - tcgetattr( STDIN_FILENO, &oldattr ); - newattr = oldattr; - newattr.c_lflag &= ~( ICANON ); + newattr.c_lflag &= ~( ICANON | ECHO ); // no ECHO for echo(?) tcsetattr( STDIN_FILENO, TCSANOW, &newattr ); ch = getchar(); tcsetattr( STDIN_FILENO, TCSANOW, &oldattr ); @@ -85,14 +78,42 @@ void vt100CursorHome() { vt100Escape("[H"); } void vt100CursorPos(int v, int h) { vt100Escape("[%d;%dH", v, h); } void vt100SaveCursor() { vt100Escape("7"); } void vt100RestoreCursor() { vt100Escape("8"); } +// void vt100GetCursor(int * v, int * h) { +// *v = *h = 0; +// printf("\033[6n"); +// getch(); getch(); +// int c; +// while ((c = getch()) != ';') +// *v = (10*(*v)+(c-'0')); +// while ((c = getch()) != 'R') +// *h = (10*(*h)+(c-'0')); +// } +void vt100GetScreenSize(int * v, int * h) { +#ifdef _WIN32 + CONSOLE_SCREEN_BUFFER_INFO csbi; + GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi); + *h = csbi.srWindow.Right - csbi.srWindow.Left + 1; + *v = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; +#else + struct winsize w; + ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); + *h = w.ws_row; + *v = w.ws_col; +#endif +} +void vt100EnableAlternateBuffer() { vt100Escape("[?1049h"); } +void vt100DisableAlternateBuffer() { vt100Escape("[?1049l"); } // JSON typedef enum { JSONNodeKind_Nul, + JSONNodeKind_Int, JSONNodeKind_Str, JSONNodeKind_Obj, + JSONNodeKind_Arr, + JSONNodeKind_COUNT } JSONNodeKind; struct JSONNode; @@ -112,6 +133,16 @@ JSONNodeNew(JSONNodeKind kind, size_t data) { return result; } +JSONNode * +JSONNodeNewNul() { + return JSONNodeNew(JSONNodeKind_Nul, (size_t)NULL); +} + +JSONNode * +JSONNodeNewInt(int i) { + return JSONNodeNew(JSONNodeKind_Int, (size_t)i); +} + JSONNode * JSONNodeNewStr(const char * str) { return JSONNodeNew(JSONNodeKind_Str, (size_t)str); @@ -123,12 +154,12 @@ JSONNodeNewObj() { } JSONNode * -JSONNodeNewNul() { - return JSONNodeNew(JSONNodeKind_Nul, (size_t)NULL); +JSONNodeNewArr() { + return JSONNodeNew(JSONNodeKind_Arr, (size_t)NULL); } JSONNode * -JSONNodeAppend(JSONNode * this, JSONNode * that) { +JSONNodePush(JSONNode * this, JSONNode * that) { if (this->children == NULL) { this->children = that; } @@ -144,6 +175,26 @@ JSONNodeAppend(JSONNode * this, JSONNode * that) { return that; } +void +JSONNodePop(JSONNode * this) { + if (this != NULL) { + JSONNode * ptr = this->children; + + if (ptr == NULL) { // no children + JSONNodePop(this->parent); + } + else if (ptr->next == NULL) { // one child + this->children = NULL; + + } + else { // more than one child + while (ptr->next->next != NULL) + ptr = ptr->next; + ptr->next = NULL; + } + } +} + void Indent(int indent) { for (int i = 0; i < indent; i++) @@ -151,19 +202,24 @@ Indent(int indent) { } void -JSONNodePrint(JSONNode * node) { +JSONNodePrint(JSONNode * node, JSONNode * currNode) { if (node == NULL) return; static int indent; if (node->parent == NULL) indent = 0; - + switch (node->kind) { case JSONNodeKind_Nul: { printf("null"); break; } + case JSONNodeKind_Int: { + char * str = (char *)node->data; + printf("%s", (str == NULL || strlen(str) == 0) ? "0" : str); + break; + } case JSONNodeKind_Str: { char * str = (char *)node->data; printf("\"%s\"", str == NULL ? "" : str); @@ -174,11 +230,12 @@ JSONNodePrint(JSONNode * node) { JSONNode * ptr = node->children; indent++; while (ptr != NULL) { - char * key = (char *)ptr->data; + JSONNode * key = ptr; JSONNode * value = ptr->next; Indent(indent); - printf("\"%s\": ", key); - JSONNodePrint(value); + JSONNodePrint(key, currNode); + printf(": "); + JSONNodePrint(value, currNode); if (ptr->next != NULL) ptr = ptr->next->next; else @@ -190,117 +247,172 @@ JSONNodePrint(JSONNode * node) { printf("}"); break; } + case JSONNodeKind_Arr: { + printf("[ "); + JSONNode * ptr = node->children; + while (ptr != NULL) { + JSONNode * value = ptr; + JSONNodePrint(value, currNode); + ptr = ptr->next; + printf("%s", (ptr == NULL ? "" : ", ")); + } + printf(" ]"); + break; + } + } + + if (currNode == node) { + vt100SaveCursor(); } } // Input -JSONNode * g_Node; +JSONNode * g_DrawNode = NULL; +JSONNode * g_CurrNode = NULL; void -Draw(JSONNode * node, const char * str) { +Draw(void) { vt100ClearScreen(); vt100CursorHome(); - printf("> %s\n\n", str); + if (g_DrawNode != NULL) { + JSONNodePrint(g_DrawNode, g_CurrNode); + vt100RestoreCursor(); + } +} - if (node != NULL) - JSONNodePrint(node); +int +GetChar() { + Draw(); + int c = getch(); + return c; +} - vt100CursorPos(0, strlen(str) + 3); +int +PeekChar() { + Draw(); + int c = peekch(); + return c; } -char * -GetStr() { - char * str = NEWARR(char, 16); +typedef bool(*CharPredicateFunc)(char, int); + +bool predStr(char c, int i) { return c >= 'a' && c <= 'z'; } +bool predInt(char c, int i) { return c >= '0' && c <= '9'; } + +void +GetStr(JSONNode * node, CharPredicateFunc charPredicate) { + node->data = (size_t)NEWARR(char, 16); int strLen = 0; + + char * str = (char *)node->data; + int c; - while ((c = getch()), (c != '\r') && (c != '\n')) { - if (strLen < 16 - 1) { - str[strLen++] = c; + while ((c = GetChar()), (c != '\r') && (c != '\n')) { + if ((c == 8 || c == 127) && strLen > 0) { + strLen--; + str[strLen] = '\0'; + } + else if (strLen < 16 - 1 && charPredicate(c, strLen)) { + str[strLen] = c; + strLen++; str[strLen] = '\0'; - Draw(g_Node, str); } } - return str; } -JSONNode * -GetNode(JSONNode * parent) { - int c = getch(); +void +GetNode(JSONNode * parent, JSONNode * node) { + int c = GetChar(); + + g_CurrNode = node; - JSONNode * result = JSONNodeNewNul(); - if (parent == NULL) - g_Node = result; + g_DrawNode = node; - if (parent != NULL && result != NULL) - JSONNodeAppend(parent, result); + if (parent != NULL && node != NULL) + JSONNodePush(parent, node); switch (c) { + case 'i': { + node->kind = JSONNodeKind_Int; + GetStr(node, predInt); + break; + } case 's': { - result->kind = JSONNodeKind_Str; - Draw(g_Node, ""); - result->data = (size_t)GetStr(); - Draw(g_Node, ""); + node->kind = JSONNodeKind_Str; + GetStr(node, predStr); break; } case 'o': { - result->kind = JSONNodeKind_Obj; - Draw(g_Node, ""); - while ((c = peekch()), (c != '\r') && (c != '\n')) { - Draw(g_Node, ""); - - JSONNodeAppend(result, JSONNodeNewStr(GetStr())); - Draw(g_Node, ""); - - JSONNodeAppend(result, GetNode(result)); - Draw(g_Node, ""); + node->kind = JSONNodeKind_Obj; + while ((c = PeekChar()), (c != '\r') && (c != '\n')) { + JSONNode * newNode; + + newNode = JSONNodeNewStr(""); + g_CurrNode = newNode; + JSONNodePush(node, newNode); + GetStr(newNode, predStr); + + newNode = JSONNodeNewNul(); + JSONNodePush(node, newNode); + GetNode(node, newNode); } + g_CurrNode = node; getch(); + break; } + case 'a': { + node->kind = JSONNodeKind_Arr; + while ((c = PeekChar()), (c != '\r') && (c != '\n')) { + JSONNode * newNode; + + newNode = JSONNodeNewNul(); + //g_CurrNode = newNode; + JSONNodePush(node, newNode); + GetNode(node, newNode); + } + g_CurrNode = node; + getch(); + break; + } + /* + case 8: + case 127: + JSONNodePop(parent); + JSONNode * newNode = JSONNodeNewNul(); + GetNode(parent, newNode); + break; + */ + case 't': + node->kind = JSONNodeKind_Int; + node->data = (size_t)GetChar(); + break; } - - return result; } -JSONNode * -TestNode() { - JSONNode * n = JSONNodeNewObj(); - JSONNode * k1 = JSONNodeNewStr("key 1"); - JSONNode * v1 = JSONNodeNewObj(); - JSONNode * k11 = JSONNodeNewStr("key 11"); - JSONNode * v11 = JSONNodeNewStr("val 11"); - JSONNode * k12 = JSONNodeNewStr("key 12"); - JSONNode * v12 = JSONNodeNewStr("val 12"); - JSONNode * k2 = JSONNodeNewStr("key 2"); - JSONNode * v2 = JSONNodeNewStr("val 2"); - - JSONNodeAppend(n, k1); - JSONNodeAppend(n, v1); - JSONNodeAppend(n, k2); - JSONNodeAppend(n, v2); - - JSONNodeAppend(v1, k11); - JSONNodeAppend(v1, v11); - JSONNodeAppend(v1, k12); - JSONNodeAppend(v1, v12); - - return n; -} + + int main() { - Draw(NULL, ""); + vt100EnableAlternateBuffer(); + + Draw(); - JSONNode * n = GetNode(NULL); + JSONNode * n = JSONNodeNewNul(); + GetNode(NULL, n); //JSONNode * n = TestNode(); vt100ClearScreen(); vt100CursorHome(); - JSONNodePrint(n); + JSONNodePrint(n, NULL); + printf("\n"); // JSONFree(n); + + vt100DisableAlternateBuffer(); return 0; -} \ No newline at end of file +}