/
superterminator
/
JsonParse
Обзор
Документация
Войти
/
superterminator
/
JsonParse
Код
Запросы
0
Задачи
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/json_parse.c
520 строк
20 KB
superterminator
initial commit
15 сен 2024, 11:40
15 сен 2024, 11:40
f4b359b
Код
Авторство
О чём код?
#include "json_parse.h" #include <string.h> #include <stdlib.h> #include "stack.h" static int parse_json(struct JsonDocument* doc); static int deinit_nodes(struct JsonNode** node); static int deinit_tokens(struct JsonTokenList** tokens); EXPORT_IMPORT_TOOLS_PREFIX int init_json_document(struct JsonDocument** doc, char* text) { if (doc == 0 || text == 0 || *text == 0) return ERR_JSON_BAD_PARAMS; *doc = (struct JsonDocument*)malloc(sizeof(struct JsonDocument)); if (*doc == 0) return ERR_JSON_MEMORY; memset(*doc, 0, sizeof(struct JsonDocument)); (*doc)->text_length = 0; { const char* text1 = text; while (*text1++) (*doc)->text_length++; } (*doc)->text = (char*)malloc((*doc)->text_length + 1); memset((*doc)->text, 0, sizeof((*doc)->text_length + 1)); if (*doc == 0) { deinit_json_document(doc); return ERR_JSON_MEMORY; } memcpy((*doc)->text, text, (*doc)->text_length); return parse_json(*doc); } EXPORT_IMPORT_TOOLS_PREFIX void deinit_json_document(struct JsonDocument** ptr) { if(!ptr) return; if ((*ptr)->text) free((*ptr)->text); deinit_nodes(&((*ptr)->nodes)); deinit_tokens(&((*ptr)->tokens)); if(*ptr) free(*ptr); *ptr = 0; } int deinit_tokens(struct JsonTokenList** tokens) { int err = ERR_JSON_SUCCESS; //clear tokens list struct JsonTokenList* cur_token = *tokens; while (cur_token) { struct JsonTokenList* temp = cur_token; cur_token = cur_token->next; free(temp); } *tokens = 0; return err; } int deinit_nodes(struct JsonNode** nodes) { int err = ERR_JSON_SUCCESS; struct JsonNode* cur_node = *nodes; while (cur_node) { while (cur_node->next || cur_node->subnodes) { //find right most while (cur_node->next) cur_node = cur_node->next; //get subnodes if (cur_node->subnodes) cur_node = cur_node->subnodes; } //delete it struct JsonNode* temp_delete = cur_node; if (cur_node->prev) { cur_node = cur_node->prev; cur_node->next = 0; } else if (cur_node->parent) { cur_node = cur_node->parent; cur_node->subnodes = 0; } else cur_node = 0; free(temp_delete); } *nodes = 0; return err; } static int cur_char_finish_token(char symb) { return symb == ' ' || symb == '[' || symb == ']' || symb == '{' || symb == '}' || symb == ':' || symb == ',' || symb == '\r' || symb == '\n'; } static int get_tokens(const char* text, int text_length, struct JsonTokenList** tokens) { if (text == 0 || tokens == 0 || text_length == 0) return ERR_JSON_BAD_PARAMS; int text_pos = 0; const char* cur_char = text; struct JsonTokenList* tokens_tail = 0; struct JsonTokenList* cur_token = 0; int in_string = 0; int in_escape = 0; for (text_pos = 0, cur_char = text; text_pos < text_length; text_pos++, cur_char++) { if (!in_string && cur_char_finish_token(*cur_char)) { //nothing more to finish token cur_token = 0; cur_token = 0; } if (!in_string && !cur_token && (*cur_char == ' ' || *cur_char == '\r' || *cur_char == '\n')) continue; if (!in_string && !cur_token) { //new token start cur_token = (struct JsonTokenList*)malloc(sizeof(struct JsonTokenList)); memset(cur_token, 0, sizeof(struct JsonTokenList)); if (*tokens == 0) { *tokens = cur_token; tokens_tail = cur_token; } else { tokens_tail->next = cur_token; tokens_tail = cur_token; } cur_token->token.text = cur_char; cur_token->token.len = 1; switch (*cur_char) { case '{': cur_token->token.type = JsonTokenCurBracketL; cur_token = 0; break; case '}': cur_token->token.type = JsonTokenCurBracketR; cur_token = 0; break; case '[': cur_token->token.type = JsonTokenSqBracketL; cur_token = 0; break; case ']': cur_token->token.type = JsonTokenSqBracketR; cur_token = 0; break; case ':': cur_token->token.type = JsonTokenColon; cur_token = 0; break; case ',': cur_token->token.type = JsonTokenComma; cur_token = 0; break; case '\"': cur_token->token.type = JsonTokenString; in_string = 1; break; default: cur_token->token.type = JsonTokenValue; break; } } else if (in_string) { cur_token->token.len++; if (!in_escape && *cur_char == '\\') { in_escape = 1; continue; } if (in_escape) { in_escape = 0; continue; } if (*cur_char == '\"') { in_string = 0; continue; } } else if(cur_token) cur_token->token.len++; } //nothing more to finish current token cur_token = 0; return ERR_JSON_SUCCESS; } //******************************************* static int token_is_keyword(const struct JsonToken* token) { return token->type == JsonTokenColon || token->type == JsonTokenComma || token->type == JsonTokenSqBracketL || token->type == JsonTokenSqBracketR || token->type == JsonTokenCurBracketL || token->type == JsonTokenCurBracketR; } static void fold_3_nodes(struct JsonNode* fold_node, struct JsonNode* last_node0, struct JsonNode* last_node2, struct JsonNode** nodes_head) { //fold to new node, put on last_node2, take parent, prev, next point to last_node0->next fold_node->prev = last_node2->prev; if(last_node2->prev) last_node2->prev->next = fold_node; fold_node->parent = last_node2->parent; fold_node->next = last_node0->next; if (last_node0->next) last_node0->next->prev = fold_node; fold_node->subnodes = last_node2; last_node2->parent = fold_node; last_node2->prev = 0; last_node0->next = 0; //null parents last_node2->next->parent = 0; last_node0->parent = 0; if (!fold_node->parent && !fold_node->prev) *nodes_head = fold_node; } static void fold_append_2_nodes(struct JsonNode* fold_node, struct JsonNode* append_node0) { struct JsonNode* last_subnode = fold_node->subnodes; while (last_subnode->next) last_subnode = last_subnode->next; last_subnode->next = append_node0->prev; //null parents append_node0->parent = 0; append_node0->prev->parent = 0; append_node0->prev->prev = last_subnode; fold_node->next = append_node0->next; if (append_node0->next) append_node0->next->prev = fold_node; append_node0->next = 0; } static int fold_nodes(int all, struct JsonNode* nodes_tail, struct JsonNode** nodes_head, int* folded) { //TODO //fold previous: //named new node //JsonNodeKeyword|end - JsonNodeString:JsonNodeString|JsonNodeValue=JsonNodeField // JsonNodeString:JsonNodeObjectValue=JsonNodeObject // JsonNodeString:JsonNodeArrayValue=JsonNodeArray //object new node // JsonNodeKeyword({)JsonNodeCommaNamed|JsonNodeField|JsonNodeArray|JsonNodeObject(})JsonNodeKeyword=JsonNodeObjectValue // JsonNodeKeyword({)(})JsonNodeKeyword=JsonNodeObjectValue //array new node // JsonNodeKeyword([)JsonNodeValue|JsonNodeString|JsonNodeObjectValue|JsonNodeArrayValue|JsonNodeCommaFields|JsonNodeCommaObjects|JsonNodeCommaArrays(])JsonNodeKeyword=JsonNodeArrayValue // JsonNodeKeyword([)(])JsonNodeKeyword=JsonNodeArrayValue //comma array append, new node // JsonNodeCommaArrays|JsonNodeArrayValue (,)JsonNodeKeyword JsonNodeArrayValue=JsonNodeCommaArrays // JsonNodeCommaObjects|JsonNodeObjectValue (,)JsonNodeKeyword JsonNodeObjectValue=JsonNodeCommaObjects // JsonNodeCommaFields|JsonNodeString|JsonNodeValue (,)JsonNodeKeyword JsonNodeString|JsonNodeValue=JsonNodeCommaFields //comma object append, new node // JsonNodeField|JsonNodeObject|JsonNodeArray|JsonNodeCommaNamed (,)JsonNodeKeyword JsonNodeField|JsonNodeObject|JsonNodeArray=JsonNodeCommaNamed *folded = 0; struct JsonNode* last_node0 = all ? nodes_tail : nodes_tail->prev; if (last_node0 == 0) return ERR_JSON_SUCCESS;//nothing here yet struct JsonNode* last_node1 = last_node0->prev; if (last_node1 == 0) return ERR_JSON_SUCCESS;//cannot fold 1 node struct JsonNode* last_node2 = last_node1 ? last_node1->prev : 0; struct JsonNode* last_node3 = last_node2 ? last_node2->prev : 0; if (last_node0 && last_node1 && last_node2) { if ((last_node0->type == JsonNodeString || last_node0->type == JsonNodeValue || last_node0->type == JsonNodeObjectValue || last_node0->type == JsonNodeArrayValue) && last_node1->token && last_node1->token->type == JsonTokenColon && last_node2->type == JsonNodeString) { //fold to new node, put on last_node2, take parent, prev, next point to last_node0->next struct JsonNode* fold_node = (struct JsonNode*)malloc(sizeof(struct JsonNode)); if (!fold_node) return ERR_JSON_MEMORY; memset(fold_node, 0, sizeof(struct JsonNode)); if ((last_node0->type == JsonNodeString || last_node0->type == JsonNodeValue)) fold_node->type = JsonNodeField; else if ((last_node0->type == JsonNodeObjectValue || last_node0->type == JsonNodeValue)) fold_node->type = JsonNodeObject; else if ((last_node0->type == JsonNodeArrayValue || last_node0->type == JsonNodeValue)) fold_node->type = JsonNodeArray; fold_3_nodes(fold_node, last_node0, last_node2, nodes_head); *folded = 1; return ERR_JSON_SUCCESS; } //fold non empty object value if (last_node0->token && last_node0->token->type == JsonTokenCurBracketR && last_node2->token && last_node2->token->type == JsonTokenCurBracketL && (last_node1->type == JsonNodeCommaNamed || last_node1->type == JsonNodeField || last_node1->type == JsonNodeArray || last_node1->type == JsonNodeObject)) { struct JsonNode* fold_node = (struct JsonNode*)malloc(sizeof(struct JsonNode)); if (!fold_node) return ERR_JSON_MEMORY; memset(fold_node, 0, sizeof(struct JsonNode)); fold_node->type = JsonNodeObjectValue; fold_3_nodes(fold_node, last_node0, last_node2, nodes_head); *folded = 1; return ERR_JSON_SUCCESS; } //fold empty object value if (last_node0->token && last_node0->token->type == JsonTokenCurBracketR && last_node1->token && last_node1->token->type == JsonTokenCurBracketL) { struct JsonNode* fold_node = (struct JsonNode*)malloc(sizeof(struct JsonNode)); if (!fold_node) return ERR_JSON_MEMORY; memset(fold_node, 0, sizeof(struct JsonNode)); fold_node->type = JsonNodeObjectValue; fold_3_nodes(fold_node, last_node0, last_node1, nodes_head); *folded = 1; return ERR_JSON_SUCCESS; } //fold non empty array value if (last_node0->token && last_node0->token->type == JsonTokenSqBracketR && last_node2->token && last_node2->token->type == JsonTokenSqBracketL && (last_node1->type == JsonNodeValue || last_node1->type == JsonNodeString || last_node1->type == JsonNodeObjectValue || last_node1->type == JsonNodeArrayValue || last_node1->type == JsonNodeCommaFields || last_node1->type == JsonNodeCommaObjects || last_node1->type == JsonNodeCommaArrays)) { struct JsonNode* fold_node = (struct JsonNode*)malloc(sizeof(struct JsonNode)); if (!fold_node) return ERR_JSON_MEMORY; memset(fold_node, 0, sizeof(struct JsonNode)); fold_node->type = JsonNodeArrayValue; fold_3_nodes(fold_node, last_node0, last_node2, nodes_head); *folded = 1; return ERR_JSON_SUCCESS; } //fold like [] - empty array value if (last_node0->token && last_node0->token->type == JsonTokenSqBracketR && last_node1->token && last_node1->token->type == JsonTokenSqBracketL) { struct JsonNode* fold_node = (struct JsonNode*)malloc(sizeof(struct JsonNode)); if (!fold_node) return ERR_JSON_MEMORY; memset(fold_node, 0, sizeof(struct JsonNode)); fold_node->type = JsonNodeArrayValue; fold_3_nodes(fold_node, last_node0, last_node1, nodes_head); *folded = 1; return ERR_JSON_SUCCESS; } if (last_node0->type == JsonNodeArrayValue && last_node2->type == JsonNodeArrayValue && last_node1->token && last_node1->token->type == JsonTokenComma) { struct JsonNode* fold_node = (struct JsonNode*)malloc(sizeof(struct JsonNode)); if (!fold_node) return ERR_JSON_MEMORY; memset(fold_node, 0, sizeof(struct JsonNode)); fold_node->type = JsonNodeCommaArrays; fold_3_nodes(fold_node, last_node0, last_node2, nodes_head); *folded = 1; return ERR_JSON_SUCCESS; } if ((last_node0->type == JsonNodeString || last_node0->type == JsonNodeValue) && (last_node2->type == JsonNodeString || last_node2->type == JsonNodeValue) && last_node1->token && last_node1->token->type == JsonTokenComma) { struct JsonNode* fold_node = (struct JsonNode*)malloc(sizeof(struct JsonNode)); if (!fold_node) return ERR_JSON_MEMORY; memset(fold_node, 0, sizeof(struct JsonNode)); fold_node->type = JsonNodeCommaFields; fold_3_nodes(fold_node, last_node0, last_node2, nodes_head); *folded = 1; return ERR_JSON_SUCCESS; } if (last_node0->type == JsonNodeObjectValue && last_node2->type == JsonNodeObjectValue && last_node1->token && last_node1->token->type == JsonTokenComma) { struct JsonNode* fold_node = (struct JsonNode*)malloc(sizeof(struct JsonNode)); if (!fold_node) return ERR_JSON_MEMORY; memset(fold_node, 0, sizeof(struct JsonNode)); fold_node->type = JsonNodeCommaObjects; fold_3_nodes(fold_node, last_node0, last_node2, nodes_head); *folded = 1; return ERR_JSON_SUCCESS; } if ((last_node0->type == JsonNodeObject || last_node0->type == JsonNodeField || last_node0->type == JsonNodeArray) && last_node1->token && last_node1->token->type == JsonTokenComma && (last_node2->type == JsonNodeObject || last_node2->type == JsonNodeField || last_node2->type == JsonNodeArray)) { struct JsonNode* fold_node = (struct JsonNode*)malloc(sizeof(struct JsonNode)); if (!fold_node) return ERR_JSON_MEMORY; memset(fold_node, 0, sizeof(struct JsonNode)); fold_node->type = JsonNodeCommaNamed; fold_3_nodes(fold_node, last_node0, last_node2, nodes_head); *folded = 1; return ERR_JSON_SUCCESS; } //append //arrays if (last_node2->type == JsonNodeCommaFields && last_node1->token && last_node1->token->type == JsonTokenComma && (last_node0->type == JsonNodeString || last_node0->type == JsonNodeValue)) { fold_append_2_nodes(last_node2, last_node0); *folded = 1; return ERR_JSON_SUCCESS; } if (last_node2->type == JsonNodeCommaObjects && last_node1->token && last_node1->token->type == JsonTokenComma && last_node0->type == JsonNodeObjectValue) { fold_append_2_nodes(last_node2, last_node0); *folded = 1; return ERR_JSON_SUCCESS; } if (last_node2->type == JsonNodeCommaArrays && last_node1->token && last_node1->token->type == JsonTokenComma && last_node0->type == JsonNodeArrayValue) { fold_append_2_nodes(last_node2, last_node0); *folded = 1; return ERR_JSON_SUCCESS; } //object if (last_node2->type == JsonNodeCommaNamed && last_node1->token && last_node1->token->type == JsonTokenComma && (last_node0->type == JsonNodeField || last_node0->type == JsonNodeObject || last_node0->type == JsonNodeArray)) { fold_append_2_nodes(last_node2, last_node0); *folded = 1; return ERR_JSON_SUCCESS; } } return ERR_JSON_SUCCESS; } static int get_nodes(const struct JsonTokenList* tokens, struct JsonNode** nodes) { if (!nodes || !tokens) return ERR_JSON_BAD_PARAMS; const struct JsonTokenList* cur_token = tokens; struct JsonNode* nodes_tail = 0; struct JsonNode* cur_node = 0; while (cur_token) { cur_node = (struct JsonNode*)malloc(sizeof(struct JsonNode)); memset(cur_node, 0, sizeof(struct JsonNode)); cur_node->token = &(cur_token->token); if (token_is_keyword(&(cur_token->token))) cur_node->type = JsonNodeKeyword; else if (cur_token->token.type == JsonTokenString) cur_node->type = JsonNodeString; else if (cur_token->token.type == JsonTokenValue) cur_node->type = JsonNodeValue; else cur_node->type = JsonNodeUnknown; if (*nodes == 0) { *nodes = cur_node; nodes_tail = cur_node; } else { nodes_tail->next = cur_node; cur_node->prev = nodes_tail; nodes_tail = cur_node; } if (cur_node->type == JsonNodeKeyword) { int folded = 0; fold_nodes(0, nodes_tail, nodes, &folded); while (folded) { folded = 0; fold_nodes(0, nodes_tail, nodes, &folded); } } if (cur_token->next == 0) { int folded = 0; fold_nodes(1, nodes_tail, nodes, &folded); while (folded) { folded = 0; //nodes tail is invalid now nodes_tail = *nodes; while (nodes_tail->next) nodes_tail = nodes_tail->next; fold_nodes(1, nodes_tail, nodes, &folded); } } cur_token = cur_token->next; } return ERR_JSON_SUCCESS; } int parse_json(struct JsonDocument* doc) { if (doc == 0 || doc->text == 0 || doc->text_length == 0) return ERR_JSON_BAD_PARAMS; int err = get_tokens(doc->text, doc->text_length, &(doc->tokens)); if (err == ERR_JSON_SUCCESS) { //TODO check tokens syntax err = get_nodes(doc->tokens, &(doc->nodes)); } return err; }