#include #include #include #include // 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"); } // JSON typedef enum { JSONNodeKind_Nul, JSONNodeKind_Str, JSONNodeKind_Obj, } 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 * JSONNodeNewStr(const char * str) { return JSONNodeNew(JSONNodeKind_Str, (size_t)str); } JSONNode * JSONNodeNewObj() { return JSONNodeNew(JSONNodeKind_Obj, (size_t)NULL); } JSONNode * JSONNodeNewNul() { return JSONNodeNew(JSONNodeKind_Nul, (size_t)NULL); } JSONNode * JSONNodeAppend(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 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_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; } } } // Input JSONNode * g_Node; void Draw(JSONNode * node, const char * str) { vt100ClearScreen(); vt100CursorHome(); printf("> %s\n\n", str); if (node != NULL) JSONNodePrint(node); vt100CursorPos(0, strlen(str) + 3); } char * GetStr() { char * str = NEWARR(char, 16); int strLen = 0; int c; while ((c = getch()), (c != '\r') && (c != '\n')) { if (strLen < 16 - 1) { str[strLen++] = c; str[strLen] = '\0'; Draw(g_Node, str); } } return str; } JSONNode * GetNode(JSONNode * parent) { int c = getch(); JSONNode * result = JSONNodeNewNul(); if (parent == NULL) g_Node = result; if (parent != NULL && result != NULL) JSONNodeAppend(parent, result); switch (c) { case 's': { result->kind = JSONNodeKind_Str; Draw(g_Node, ""); result->data = (size_t)GetStr(); Draw(g_Node, ""); 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, ""); } getch(); } } 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, ""); JSONNode * n = GetNode(NULL); //JSONNode * n = TestNode(); vt100ClearScreen(); vt100CursorHome(); JSONNodePrint(n); // JSONFree(n); return 0; }