X-Git-Url: https://gitweb.ps.run/iftint/blobdiff_plain/8827b84eeea76b08632d0f7c52488f5af2f83092..4c67fbe5877ad07a0cfb613c161aa8526970ea7f:/main2.c diff --git a/main2.c b/main2.c index e462674..51c5ad4 100644 --- a/main2.c +++ b/main2.c @@ -1,17 +1,414 @@ -#include -#include - -#define ASCII_ESC 27 - -int main() { - int c; - printf("Hallo\n"); - c = getch(); - printf("%c[2J", ASCII_ESC); - printf("%c[H", ASCII_ESC); - printf("c: %c\n", c); - - c = getch(); - - return 0; -} \ No newline at end of file +#include +#include +#include +#include +#include + +/* TODO +- whitelist input on GetStr/GetInt +*/ + +// Memory + +#define NEW(TYPE) ((TYPE *)calloc(1, sizeof(TYPE))) +#define NEWARR(TYPE, NUM) ((TYPE *)calloc(NUM, sizeof(TYPE))) + + +// getch() + +#ifdef _WIN32 +#include +#else +#include +#include +#include + +/* reads from keypress, doesn't echo */ +int getch(void) +{ + struct termios oldattr, newattr; + 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 ); + tcsetattr( STDIN_FILENO, TCSANOW, &newattr ); + ch = getchar(); + tcsetattr( STDIN_FILENO, TCSANOW, &oldattr ); + return ch; +} + +/* ungets keypress */ +void ungetch(int ch) +{ + struct termios oldattr, newattr; + tcgetattr( STDIN_FILENO, &oldattr ); + newattr = oldattr; + newattr.c_lflag &= ~( ICANON | ECHO ); + tcsetattr( STDIN_FILENO, TCSANOW, &newattr ); + ungetc(ch, stdin); + tcsetattr( STDIN_FILENO, TCSANOW, &oldattr ); +} +#endif + +int +peekch() { + int c = getch(); + //ungetc(c, stdin); + ungetch(c); + return c; +} + + +// VT100 + +#define ASCII_ESC 27 + +void vt100Escape(const char * str, ...) { + va_list args; + va_start(args, str); + + printf("%c", ASCII_ESC); + vprintf(str, args); +} + +void vt100ClearScreen() { vt100Escape("[2J"); } +void vt100CursorHome() { vt100Escape("[H"); } +void vt100CursorPos(int v, int h) { vt100Escape("[%d;%dH", v, h); } +void vt100SaveCursor() { vt100Escape("7"); } +void vt100RestoreCursor() { vt100Escape("8"); } +void vt100GetScreenSize(int * v, int * h) { + *v = *h = 0; + vt100CursorPos(1000000, 1000000); + printf("\033[6n"); + getch(); getch(); + int c; + while ((c = getch()) != ';') + *v = (10*(*v)+(c-'0')); + while ((c = getch()) != 'R') + *h = (10*(*h)+(c-'0')); +} + + +// JSON + +typedef enum { + JSONNodeKind_Nul, + JSONNodeKind_Int, + JSONNodeKind_Str, + JSONNodeKind_Obj, + JSONNodeKind_Arr, +} JSONNodeKind; + +struct JSONNode; +typedef struct JSONNode { + JSONNodeKind kind; + size_t data; + struct JSONNode * parent; + struct JSONNode * children; + struct JSONNode * next; +} JSONNode; + +JSONNode * +JSONNodeNew(JSONNodeKind kind, size_t data) { + JSONNode * result = NEW(JSONNode); + result->kind = kind; + result->data = 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); +} + +JSONNode * +JSONNodeNewObj() { + return JSONNodeNew(JSONNodeKind_Obj, (size_t)NULL); +} + +JSONNode * +JSONNodeNewArr() { + return JSONNodeNew(JSONNodeKind_Arr, (size_t)NULL); +} + +JSONNode * +JSONNodePush(JSONNode * this, JSONNode * that) { + if (this->children == NULL) { + this->children = that; + } + else { + JSONNode * lastNode = this->children; + while (lastNode->next != NULL) + lastNode = lastNode->next; + lastNode->next = that; + } + that->parent = this; + that->next = NULL; + + 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++) + printf(" "); +} + +void +JSONNodePrint(JSONNode * node) { + 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: { + int i = (int)node->data; + printf("%d", i); + break; + } + case JSONNodeKind_Str: { + char * str = (char *)node->data; + printf("\"%s\"", str == NULL ? "" : str); + break; + } + case JSONNodeKind_Obj: { + printf("{\n"); + JSONNode * ptr = node->children; + indent++; + while (ptr != NULL) { + char * key = (char *)ptr->data; + JSONNode * value = ptr->next; + Indent(indent); + printf("\"%s\": ", key); + JSONNodePrint(value); + if (ptr->next != NULL) + ptr = ptr->next->next; + else + ptr = NULL; + printf("%s\n", (ptr == NULL ? "" : ",")); + } + indent--; + Indent(indent); + printf("}"); + break; + } + case JSONNodeKind_Arr: { + printf("[ "); + JSONNode * ptr = node->children; + while (ptr != NULL) { + JSONNode * value = ptr; + JSONNodePrint(value); + ptr = ptr->next; + printf("%s", (ptr == NULL ? "" : ", ")); + } + printf(" ]"); + break; + } + } +} + + +// Input + +JSONNode * g_DrawNode = NULL; +const char * g_DrawStr = ""; + +void +Draw(void) { + vt100ClearScreen(); + vt100CursorHome(); + + if (g_DrawNode != NULL) + JSONNodePrint(g_DrawNode); + + int v, h; + vt100GetScreenSize(&v, &h); + vt100CursorPos(v, 0); + printf("> %s", g_DrawStr); + + vt100CursorPos(v, strlen(g_DrawStr) + 3); +} + +int +GetChar() { + Draw(); + int c = getch(); + return c; +} + +int +PeekChar() { + int c = GetChar(); + ungetch(c); + return c; +} + +int +GetInt() { + static char intStr[16]; + intStr[0] = '\0'; + int intStrLen = 0; + int result = 0; + int c; + g_DrawStr = intStr; + while ((c = GetChar()), (c != '\r') && (c != '\n')) { + if ((c == 8 || c == 127) && intStrLen > 0) { + intStrLen--; + intStr[intStrLen] = '\0'; + result /= 10; + } + else if (intStrLen < 16 - 1 && (c >= '0' && c <= '9')) { + intStr[intStrLen++] = c; + intStr[intStrLen] = '\0'; + result *= 10; + result += c - '0'; + } + } + g_DrawStr = ""; + return result; +} + +char * +GetStr() { + char * str = NEWARR(char, 16); + int strLen = 0; + int c; + g_DrawStr = str; + while ((c = GetChar()), (c != '\r') && (c != '\n')) { + if ((c == 8 || c == 127) && strLen > 0) { + strLen--; + str[strLen] = '\0'; + } + else if (strLen < 16 - 1) { + str[strLen++] = c; + str[strLen] = '\0'; + } + } + g_DrawStr = ""; + return str; +} + +JSONNode * +GetNode(JSONNode * parent) { + int c = GetChar(); + + JSONNode * result = JSONNodeNewNul(); + + if (parent == NULL) + g_DrawNode = result; + + if (parent != NULL && result != NULL) + JSONNodePush(parent, result); + + switch (c) { + case 'i': { + result->kind = JSONNodeKind_Int; + result->data = (size_t)GetInt(); + break; + } + case 's': { + result->kind = JSONNodeKind_Str; + result->data = (size_t)GetStr(); + break; + } + case 'o': { + result->kind = JSONNodeKind_Obj; + while ((c = peekch()), (c != '\r') && (c != '\n')) { + JSONNodePush(result, JSONNodeNewStr(GetStr())); + + JSONNodePush(result, GetNode(result)); + } + getch(); + break; + } + case 'a': { + result->kind = JSONNodeKind_Arr; + while ((c = peekch()), (c != '\r') && (c != '\n')) { + JSONNodePush(result, GetNode(result)); + } + getch(); + break; + } + case 8: + case 127: + JSONNodePop(parent); + result = GetNode(parent); + break; + case 't': + result->kind = JSONNodeKind_Int; + result->data = (size_t)GetChar(); + break; + } + + return result; +} + + + + +int main() { + Draw(); + + JSONNode * n = GetNode(NULL); + //JSONNode * n = TestNode(); + + vt100ClearScreen(); + vt100CursorHome(); + JSONNodePrint(n); + printf("\n"); + + // JSONFree(n); + + return 0; +}