Move the logic for loading a json file into the load_json function
This commit is contained in:
		| @@ -4,6 +4,8 @@ | ||||
| #include "json_entities.h" | ||||
| #include "lexer.h" | ||||
|  | ||||
| void parse_token(token_t token); | ||||
| typedef struct parser_s parser_t; | ||||
|  | ||||
| jentity_t *load_json(const char *filepath); | ||||
|  | ||||
| #endif // !PARSER_H | ||||
|   | ||||
							
								
								
									
										42
									
								
								src/main.c
									
									
									
									
									
								
							
							
						
						
									
										42
									
								
								src/main.c
									
									
									
									
									
								
							| @@ -1,4 +1,5 @@ | ||||
| #include "aliases.h" | ||||
| #include "json_entities.h" | ||||
| #include "lexer.h" | ||||
| #include "parser.h" | ||||
| #include <stdio.h> | ||||
| @@ -14,48 +15,13 @@ int main(int argc, char *argv[]) { | ||||
|  | ||||
|   const char *filename = argv[1]; | ||||
|  | ||||
|   FILE *fp = fopen(filename, "r"); | ||||
|   jentity_t *root = load_json(filename); | ||||
|  | ||||
|   fseek(fp, 0, SEEK_END); | ||||
|  | ||||
|   u64 length = ftell(fp); | ||||
|  | ||||
|   fseek(fp, 0, SEEK_SET); | ||||
|  | ||||
|   char json[length + 1]; | ||||
|   memset(json, 0, length + 1); | ||||
|  | ||||
|   fread(json, sizeof(char), length, fp); | ||||
|  | ||||
|   fclose(fp); | ||||
|  | ||||
|   lexer_t *lexer = NULL; | ||||
|  | ||||
|   lexer_init(&lexer); | ||||
|   if (!lexer) { | ||||
|   if (!root) { | ||||
|     return EXIT_FAILURE; | ||||
|   } | ||||
|  | ||||
|   lex_result_t result = get_next_token(lexer, json); | ||||
|  | ||||
|   if (result.error.errno) { | ||||
|     printf("%s\n", result.error.msg); | ||||
|   } else { | ||||
|     while (result.token.type != TK_NO_TOKEN) { | ||||
|       print_token(result.token); | ||||
|  | ||||
|       parse_token(result.token); | ||||
|  | ||||
|       result = get_next_token(lexer, NULL); | ||||
|  | ||||
|       if (result.error.errno) { | ||||
|         printf("%s\n", result.error.msg); | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   lexer_free(&lexer); | ||||
|   print_json(root, 2); | ||||
|  | ||||
|   return EXIT_SUCCESS; | ||||
| } | ||||
|   | ||||
| @@ -5,91 +5,182 @@ | ||||
| #include "lexer.h" | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
|  | ||||
| INTERNAL jentity_t *current = NULL; | ||||
| struct parser_s { | ||||
|   jentity_t *root; | ||||
|   jentity_t *current; | ||||
|   jval_t value; | ||||
| }; | ||||
|  | ||||
| INTERNAL jcoll_t *get_collection_from_entity(const jentity_t *entity); | ||||
| INTERNAL jentity_t *create_new_single_entity(const jval_t value, | ||||
|                                              jentity_t *parent); | ||||
| INTERNAL jentity_t *create_new_pair_entity(dstr_t *key, const jval_t value, | ||||
|                                            jentity_t *parent); | ||||
| INTERNAL void add_key(jentity_t **entity, dstr_t *key, const jval_t *value); | ||||
| INTERNAL jentity_t *add_value(jentity_t **entity, const jval_t *value); | ||||
| INTERNAL void add_collection(jentity_t **entity, const 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); | ||||
|  | ||||
| void parse_token(token_t token) { | ||||
| jentity_t *load_json(const char *filepath) { | ||||
|   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[length + 1]; | ||||
|   memset(json, 0, length + 1); | ||||
|  | ||||
|   fread(json, sizeof(char), length, fp); | ||||
|  | ||||
|   fclose(fp); | ||||
|  | ||||
|   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; | ||||
|   } | ||||
|  | ||||
|   lex_result_t result = get_next_token(lexer, json); | ||||
|  | ||||
|   if (result.error.errno) { | ||||
|     printf("%s\n", result.error.msg); | ||||
|   } else { | ||||
|     while (result.token.type != TK_NO_TOKEN) { | ||||
|       parse_token(parser, result.token); | ||||
|  | ||||
|       result = get_next_token(lexer, NULL); | ||||
|  | ||||
|       if (result.error.errno) { | ||||
|         printf("%s\n", result.error.msg); | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   jentity_t *root = parser->root; | ||||
|  | ||||
|   parser_free(&parser); | ||||
|   lexer_free(&lexer); | ||||
|  | ||||
|   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: { | ||||
|     jval_t value = (jval_t){ | ||||
|     parser->value = (jval_t){ | ||||
|         .type = JVAL_COLLECTION, | ||||
|         .collection = (jcoll_t *)malloc(sizeof(jcoll_t)), | ||||
|     }; | ||||
|  | ||||
|     if (token.type == TK_L_BRACE) { | ||||
|       value.collection->type = JCOLL_OBJECT; | ||||
|       parser->value.collection->type = JCOLL_OBJECT; | ||||
|     } else { | ||||
|       value.collection->type = JCOLL_ARRAY; | ||||
|       parser->value.collection->type = JCOLL_ARRAY; | ||||
|     } | ||||
|  | ||||
|     value.collection->size = 0; | ||||
|     value.collection->begin = NULL; | ||||
|     value.collection->end = NULL; | ||||
|     parser->value.collection->size = 0; | ||||
|     parser->value.collection->begin = NULL; | ||||
|     parser->value.collection->end = NULL; | ||||
|  | ||||
|     add_collection(¤t, &value); | ||||
|     add_collection(parser); | ||||
|  | ||||
|     break; | ||||
|   } | ||||
|   case TK_R_BRACE: | ||||
|   case TK_R_BRACKET: | ||||
|     if (current->parent) { | ||||
|       current = current->parent; | ||||
|     if (parser->current->parent) { | ||||
|       parser->current = parser->current->parent; | ||||
|     } | ||||
|  | ||||
|     break; | ||||
|   case TK_STR_KEY: { | ||||
|     jval_t value = (jval_t){.type = JVAL_EMPTY, .null_val = NULL}; | ||||
|     parser->value = (jval_t){.type = JVAL_EMPTY, .null_val = NULL}; | ||||
|  | ||||
|     add_key(¤t, dstr_from_string(token.value.string), &value); | ||||
|     add_key(parser, dstr_from_string(token.value.string)); | ||||
|  | ||||
|     break; | ||||
|   } | ||||
|   case TK_NULL: { | ||||
|     jval_t value = (jval_t){.type = JVAL_NULL, .null_val = NULL}; | ||||
|     parser->value = (jval_t){.type = JVAL_NULL, .null_val = NULL}; | ||||
|  | ||||
|     add_value(¤t, &value); | ||||
|     add_value(parser); | ||||
|  | ||||
|     break; | ||||
|   } | ||||
|   case TK_BOOL: { | ||||
|     jval_t value = | ||||
|     parser->value = | ||||
|         (jval_t){.type = JVAL_BOOLEAN, .boolean = token.value.boolean}; | ||||
|  | ||||
|     add_value(¤t, &value); | ||||
|     add_value(parser); | ||||
|  | ||||
|     break; | ||||
|   } | ||||
|   case TK_STR_VAL: { | ||||
|     jval_t value = (jval_t){.type = JVAL_STRING, | ||||
|                             .string = dstr_from_string(token.value.string)}; | ||||
|     parser->value = (jval_t){.type = JVAL_STRING, | ||||
|                              .string = dstr_from_string(token.value.string)}; | ||||
|  | ||||
|     add_value(¤t, &value); | ||||
|     add_value(parser); | ||||
|  | ||||
|     break; | ||||
|   } | ||||
|   case TK_INTEGER: { | ||||
|     jval_t value = | ||||
|     parser->value = | ||||
|         (jval_t){.type = JVAL_INTEGER, .num_int = token.value.num_int}; | ||||
|  | ||||
|     add_value(¤t, &value); | ||||
|     add_value(parser); | ||||
|  | ||||
|     break; | ||||
|   } | ||||
|   case TK_DOUBLE: { | ||||
|     jval_t value = | ||||
|     parser->value = | ||||
|         (jval_t){.type = JVAL_DOUBLE, .num_dbl = token.value.num_frac}; | ||||
|  | ||||
|     add_value(¤t, &value); | ||||
|     add_value(parser); | ||||
|  | ||||
|     break; | ||||
|   } | ||||
| @@ -98,45 +189,8 @@ void parse_token(token_t token) { | ||||
|   } | ||||
| } | ||||
|  | ||||
| jcoll_t *get_collection_from_entity(const jentity_t *entity) { | ||||
|   return entity->type == JENTITY_SINGLE ? entity->value.collection | ||||
|                                         : entity->pair.value.collection; | ||||
| } | ||||
|  | ||||
| jentity_t *create_new_single_entity(const jval_t value, jentity_t *parent) { | ||||
|   jentity_t *entity = (jentity_t *)malloc(sizeof(jentity_t)); | ||||
|  | ||||
|   if (!entity) { | ||||
|     return NULL; | ||||
|   } | ||||
|  | ||||
|   entity->type = JENTITY_SINGLE; | ||||
|   entity->value = value; | ||||
|   entity->parent = parent; | ||||
|   entity->next = NULL; | ||||
|  | ||||
|   return entity; | ||||
| } | ||||
|  | ||||
| jentity_t *create_new_pair_entity(dstr_t *key, const jval_t value, | ||||
|                                   jentity_t *parent) { | ||||
|   jentity_t *entity = (jentity_t *)malloc(sizeof(jentity_t)); | ||||
|  | ||||
|   if (!entity) { | ||||
|     return NULL; | ||||
|   } | ||||
|  | ||||
|   entity->type = JENTITY_PAIR; | ||||
|   entity->pair.key = key; | ||||
|   entity->pair.value = value; | ||||
|   entity->parent = parent; | ||||
|   entity->next = NULL; | ||||
|  | ||||
|   return entity; | ||||
| } | ||||
|  | ||||
| void add_key(jentity_t **entity, dstr_t *key, const jval_t *value) { | ||||
|   jcoll_t *collection = get_collection_from_entity(*entity); | ||||
| void add_key(parser_t *parser, dstr_t *key) { | ||||
|   jcoll_t *collection = get_collection_from_entity(parser->current); | ||||
|  | ||||
|   if (!collection) { | ||||
|     return; | ||||
| @@ -144,11 +198,12 @@ void add_key(jentity_t **entity, dstr_t *key, const jval_t *value) { | ||||
|  | ||||
|   if (!(collection->end)) { | ||||
|     collection->begin = collection->end = | ||||
|         create_new_pair_entity(key, *value, *entity); | ||||
|         create_new_pair_entity(key, parser->value, parser->current); | ||||
|  | ||||
|     collection->size = 1; | ||||
|   } else { | ||||
|     jentity_t *new_entity = create_new_pair_entity(key, *value, *entity); | ||||
|     jentity_t *new_entity = | ||||
|         create_new_pair_entity(key, parser->value, parser->current); | ||||
|  | ||||
|     collection->end->next = new_entity; | ||||
|  | ||||
| @@ -158,8 +213,8 @@ void add_key(jentity_t **entity, dstr_t *key, const jval_t *value) { | ||||
|   } | ||||
| } | ||||
|  | ||||
| jentity_t *add_value(jentity_t **entity, const jval_t *value) { | ||||
|   jcoll_t *collection = get_collection_from_entity(*entity); | ||||
| jentity_t *add_value(parser_t *parser) { | ||||
|   jcoll_t *collection = get_collection_from_entity(parser->current); | ||||
|  | ||||
|   if (!collection) { | ||||
|     return NULL; | ||||
| @@ -167,15 +222,16 @@ jentity_t *add_value(jentity_t **entity, const jval_t *value) { | ||||
|  | ||||
|   if (!(collection->end)) { | ||||
|     collection->begin = collection->end = | ||||
|         create_new_single_entity(*value, *entity); | ||||
|         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 = *value; | ||||
|       collection->end->pair.value = parser->value; | ||||
|     } else { | ||||
|       jentity_t *new_entity = create_new_single_entity(*value, *entity); | ||||
|       jentity_t *new_entity = | ||||
|           create_new_single_entity(parser->value, parser->current); | ||||
|  | ||||
|       collection->end->next = new_entity; | ||||
|  | ||||
| @@ -188,12 +244,13 @@ jentity_t *add_value(jentity_t **entity, const jval_t *value) { | ||||
|   return collection->end; | ||||
| } | ||||
|  | ||||
| void add_collection(jentity_t **entity, const jval_t *value) { | ||||
|   if (!(*entity)) { | ||||
|     *entity = create_new_single_entity(*value, NULL); | ||||
| void add_collection(parser_t *parser) { | ||||
|   if (!(parser->root)) { | ||||
|     parser->root = parser->current = | ||||
|         create_new_single_entity(parser->value, NULL); | ||||
|  | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   *entity = add_value(entity, value); | ||||
|   parser->current = add_value(parser); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user