X-Git-Url: https://gitweb.ps.run/iftint/blobdiff_plain/8827b84eeea76b08632d0f7c52488f5af2f83092..befbc85923ae0762e14ea44a805c0931d971ff1d:/main2.c diff --git a/main2.c b/main2.c index e462674..d8f2581 100644 --- a/main2.c +++ b/main2.c @@ -1,17 +1,438 @@ -#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 +#include +#else +#include +#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 ); // no ECHO for echo(?) + 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 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 +} + + +// JSON + +typedef enum { + JSONNodeKind_Nul, + JSONNodeKind_Int, + JSONNodeKind_Str, + JSONNodeKind_Obj, + JSONNodeKind_Arr, + JSONNodeKind_COUNT +} 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(" "); +} + +static int currV = 0; +static int currH = 0; + +void +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: { + 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, currNode); + 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, currNode); + ptr = ptr->next; + printf("%s", (ptr == NULL ? "" : ", ")); + } + printf(" ]"); + break; + } + } + + if (currNode == node) { + int currOffsets[JSONNodeKind_COUNT]; + currOffsets[JSONNodeKind_Nul] = 0; + currOffsets[JSONNodeKind_Int] = 0; + currOffsets[JSONNodeKind_Str] = 1; + currOffsets[JSONNodeKind_Obj] = 1; + currOffsets[JSONNodeKind_Arr] = 2; + vt100GetCursor(&currV, &currH); + currH -= currOffsets[node->kind]; + } +} + + +// Input + +JSONNode * g_DrawNode = NULL; +JSONNode * g_CurrNode = NULL; + +void +Draw(void) { + vt100ClearScreen(); + vt100CursorHome(); + + if (g_DrawNode != NULL) { + JSONNodePrint(g_DrawNode, g_CurrNode); + vt100CursorPos(currV, currH); + } +} + +int +GetChar() { + Draw(); + int c = getch(); + return c; +} + +int +PeekChar() { + Draw(); + int c = peekch(); + return c; +} + +void +GetInt(JSONNode * node) { + char intStr[16] = ""; + int intStrLen = 0; + + size_t * i = &node->data; + + int c; + while ((c = GetChar()), (c != '\r') && (c != '\n')) { + if ((c == 8 || c == 127) && intStrLen > 0) { + intStrLen--; + intStr[intStrLen] = '\0'; + *i /= 10; + } + else if (intStrLen < 16 - 1 && (c >= '0' && c <= '9')) { + intStr[intStrLen++] = c; + intStr[intStrLen] = '\0'; + *i *= 10; + *i += c - '0'; + } + } +} + +void +GetStr(JSONNode * node) { + node->data = (size_t)NEWARR(char, 16); + int strLen = 0; + + char * str = (char *)node->data; + + int c; + 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; + strLen++; + str[strLen] = '\0'; + } + } +} + +void +GetNode(JSONNode * parent, JSONNode * node) { + int c = GetChar(); + + JSONNode * result = node; + g_CurrNode = node; + + if (parent == NULL) + g_DrawNode = result; + + if (parent != NULL && result != NULL) + JSONNodePush(parent, result); + + switch (c) { + case 'i': { + result->kind = JSONNodeKind_Int; + GetInt(result); + break; + } + case 's': { + result->kind = JSONNodeKind_Str; + GetStr(result); + break; + } + case 'o': { + result->kind = JSONNodeKind_Obj; + while ((c = PeekChar()), (c != '\r') && (c != '\n')) { + JSONNode * newNode; + + newNode = JSONNodeNewStr(""); + g_CurrNode = newNode; + JSONNodePush(result, newNode); + GetStr(newNode); + + newNode = JSONNodeNewNul(); + JSONNodePush(result, newNode); + GetNode(result, newNode); + } + g_CurrNode = result; + GetChar(); + break; + } + case 'a': { + result->kind = JSONNodeKind_Arr; + while ((c = PeekChar()), (c != '\r') && (c != '\n')) { + JSONNode * newNode = JSONNodeNewNul(); + g_CurrNode = newNode; + JSONNodePush(result, newNode); + GetNode(result, newNode); + } + g_CurrNode = result; + GetChar(); + break; + } + /* + case 8: + case 127: + JSONNodePop(parent); + JSONNode * newNode = JSONNodeNewNul(); + GetNode(parent, newNode); + break; + */ + case 't': + result->kind = JSONNodeKind_Int; + result->data = (size_t)GetChar(); + break; + } +} + + + + +int main() { + Draw(); + + JSONNode * n = JSONNodeNewNul(); + GetNode(NULL, n); + //JSONNode * n = TestNode(); + + vt100ClearScreen(); + vt100CursorHome(); + JSONNodePrint(n, NULL); + printf("\n"); + + // JSONFree(n); + + return 0; +}