#include "json/parser.h" #include "aliases.h" #include "processor/ids.h" #include "profiler/timer.h" #include "json/dstring.h" #include "json/json_entities.h" #include "json/lexer.h" #include #include #include struct parser_s { jentity_t *root; jentity_t *current; jval_t value; }; INTERNAL void parser_free(parser_t **parser); INTERNAL void parser_init(parser_t **parser); INTERNAL void parse_token(parser_t *parser, token_t token); INTERNAL void add_key(parser_t *parser, dstr_t *key); INTERNAL jentity_t *add_value(parser_t *parser); INTERNAL void add_collection(parser_t *parser); jentity_t *load_json(const char *filepath) { SAMPLE_START(PROFILER_ID_READ_JSON_FILE, "READ JSON FILE"); FILE *fp = fopen(filepath, "r"); if (!fp) { return NULL; } fseek(fp, 0, SEEK_END); u64 length = ftell(fp); fseek(fp, 0, SEEK_SET); char *json = (char *)malloc(sizeof(char) * (length + 1)); memset(json, 0, length + 1); fread(json, sizeof(char), length, fp); fclose(fp); SAMPLE_END(PROFILER_ID_READ_JSON_FILE); SAMPLE_START(PROFILER_ID_PARSER_SETUP, "JSON PARSER SETUP"); lexer_t *lexer = NULL; parser_t *parser = NULL; lexer_init(&lexer); if (!lexer) { return NULL; } parser_init(&parser); if (!parser) { lexer_free(&lexer); return NULL; } SAMPLE_END(PROFILER_ID_PARSER_SETUP); SAMPLE_START(PROFILER_ID_LEX_GET_TOKEN, "GET NEXT TOKEN"); lex_result_t result = get_next_token(lexer, json); SAMPLE_END(PROFILER_ID_LEX_GET_TOKEN); if (result.error.errno) { printf("%s\n", result.error.msg); } else { while (result.token.type != TK_NO_TOKEN) { SAMPLE_START(PROFILER_ID_PARSE_TOKEN, "PARSE TOKEN"); parse_token(parser, result.token); SAMPLE_END(PROFILER_ID_PARSE_TOKEN); SAMPLE_START(PROFILER_ID_LEX_GET_TOKEN, "GET NEXT TOKEN"); result = get_next_token(lexer, NULL); SAMPLE_END(PROFILER_ID_LEX_GET_TOKEN); if (result.error.errno) { printf("%s\n", result.error.msg); break; } } } jentity_t *root = parser->root; SAMPLE_START(PROFILER_ID_PARSER_TEAR_DOWN, "PARSER TEAR DOWN"); parser_free(&parser); lexer_free(&lexer); free(json); SAMPLE_END(PROFILER_ID_PARSER_TEAR_DOWN); return root; } void parser_init(parser_t **parser) { if (*parser) { parser_free(parser); } *parser = (parser_t *)malloc(sizeof(parser_t)); if (!(*parser)) { return; } (*parser)->root = NULL; (*parser)->current = NULL; (*parser)->value = (jval_t){0}; } void parser_free(parser_t **parser) { if (!(*parser)) { return; } (*parser)->root = NULL; (*parser)->current = NULL; free(*parser); *parser = NULL; } void parse_token(parser_t *parser, token_t token) { switch (token.type) { case TK_L_BRACE: case TK_L_BRACKET: { parser->value = (jval_t){ .type = JVAL_COLLECTION, .collection = (jcoll_t *)malloc(sizeof(jcoll_t)), }; if (token.type == TK_L_BRACE) { parser->value.collection->type = JCOLL_OBJECT; } else { parser->value.collection->type = JCOLL_ARRAY; } parser->value.collection->size = 0; parser->value.collection->begin = NULL; parser->value.collection->end = NULL; add_collection(parser); break; } case TK_R_BRACE: case TK_R_BRACKET: if (parser->current->parent) { parser->current = parser->current->parent; } break; case TK_STR_KEY: { parser->value = (jval_t){.type = JVAL_EMPTY, .null_val = NULL}; add_key(parser, dstr_from_string(token.value.string)); break; } case TK_NULL: { parser->value = (jval_t){.type = JVAL_NULL, .null_val = NULL}; add_value(parser); break; } case TK_BOOL: { parser->value = (jval_t){.type = JVAL_BOOLEAN, .boolean = token.value.boolean}; add_value(parser); break; } case TK_STR_VAL: { parser->value = (jval_t){.type = JVAL_STRING, .string = dstr_from_string(token.value.string)}; add_value(parser); break; } case TK_INTEGER: { parser->value = (jval_t){.type = JVAL_INTEGER, .num_int = token.value.num_int}; add_value(parser); break; } case TK_DOUBLE: { parser->value = (jval_t){.type = JVAL_DOUBLE, .num_dbl = token.value.num_frac}; add_value(parser); break; } case TK_NO_TOKEN: break; } } void add_key(parser_t *parser, dstr_t *key) { jcoll_t *collection = get_collection_from_entity(parser->current); if (!collection) { return; } if (!(collection->end)) { collection->begin = collection->end = create_new_pair_entity(key, parser->value, parser->current); collection->size = 1; } else { jentity_t *new_entity = create_new_pair_entity(key, parser->value, parser->current); collection->end->next = new_entity; collection->end = new_entity; ++(collection->size); } } jentity_t *add_value(parser_t *parser) { jcoll_t *collection = get_collection_from_entity(parser->current); if (!collection) { return NULL; } if (!(collection->end)) { collection->begin = collection->end = create_new_single_entity(parser->value, parser->current); collection->size = 1; } else { if (collection->end->type == JENTITY_PAIR && collection->end->pair.value.type == JVAL_EMPTY) { collection->end->pair.value = parser->value; } else { jentity_t *new_entity = create_new_single_entity(parser->value, parser->current); collection->end->next = new_entity; collection->end = new_entity; ++(collection->size); } } return collection->end; } void add_collection(parser_t *parser) { if (!(parser->root)) { parser->root = parser->current = create_new_single_entity(parser->value, NULL); return; } parser->current = add_value(parser); }