X-Git-Url: https://gitweb.ps.run/iftint/blobdiff_plain/8827b84eeea76b08632d0f7c52488f5af2f83092..4889cf922e51c34f714941498d25588ceb258e67:/main2.c diff --git a/main2.c b/main2.c index e462674..86cc7b7 100644 --- a/main2.c +++ b/main2.c @@ -1,17 +1,418 @@ -#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 +} +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; +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, 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); + break; + } + case JSONNodeKind_Obj: { + printf("{\n"); + JSONNode * ptr = node->children; + indent++; + while (ptr != NULL) { + JSONNode * key = ptr; + JSONNode * value = ptr->next; + Indent(indent); + JSONNodePrint(key, currNode); + printf(": "); + 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) { + vt100SaveCursor(); + } +} + + +// Input + +JSONNode * g_DrawNode = NULL; +JSONNode * g_CurrNode = NULL; + +void +Draw(void) { + vt100ClearScreen(); + vt100CursorHome(); + + if (g_DrawNode != NULL) { + JSONNodePrint(g_DrawNode, g_CurrNode); + vt100RestoreCursor(); + } +} + +int +GetChar() { + Draw(); + int c = getch(); + return c; +} + +int +PeekChar() { + Draw(); + int c = peekch(); + return c; +} + +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 = 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'; + } + } +} + +void +GetNode(JSONNode * parent, JSONNode * node) { + int c = GetChar(); + + g_CurrNode = node; + + if (parent == NULL) + g_DrawNode = node; + + if (parent != NULL && node != NULL) + JSONNodePush(parent, node); + + switch (c) { + case 'i': { + node->kind = JSONNodeKind_Int; + GetStr(node, predInt); + break; + } + case 's': { + node->kind = JSONNodeKind_Str; + GetStr(node, predStr); + break; + } + case 'o': { + 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; + } +} + + + + +int main() { + vt100EnableAlternateBuffer(); + + Draw(); + + JSONNode * n = JSONNodeNewNul(); + GetNode(NULL, n); + //JSONNode * n = TestNode(); + + vt100ClearScreen(); + vt100CursorHome(); + JSONNodePrint(n, NULL); + printf("\n"); + + // JSONFree(n); + + vt100DisableAlternateBuffer(); + + return 0; +}