diff --git a/src/json_entities/json_entities.c b/src/json_entities/json_entities.c index cb757eb..f584194 100644 --- a/src/json_entities/json_entities.c +++ b/src/json_entities/json_entities.c @@ -4,9 +4,9 @@ #include #include -// TODO (Abdelrahman): Because print_json and free_json are recursive functions, -// they seem to cause stack overflow when dealing with large files. Refactor -// both of them to avoid this problem. +// TODO (Abdelrahman): Because print_json is a recursive function, it seems to +// cause stack overflow when dealing with large files. Refactor if to avoid this +// problem. void print_json(const jentity_t *entity, u32 indent) { PERSISTENT i32 indentation = 0; @@ -114,50 +114,86 @@ void print_json(const jentity_t *entity, u32 indent) { } } -void free_json(jentity_t **entity) { - if (!(*entity)) { +void free_json(jentity_t **root) { + if (!(*root)) { return; } - jentity_t *entt_ptr = *entity; - + jentity_t *current = *root; + jentity_t *temp = NULL; dstr_t *key = NULL; - const jval_t *value = NULL; + jval_t *value = NULL; - if (entt_ptr->type == JENTITY_SINGLE) { - value = &(entt_ptr->value); - } else { - key = entt_ptr->pair.key; - value = &(entt_ptr->pair.value); - } + while (current) { + if (current->parent) { + // Move the beginning pointer of the collection to the next child - if (key) { - dstr_free(&(entt_ptr->pair.key)); - } + // TODO (Abdelrahman): This part gets repeated for some elements. Try to + // avoid that repetition - switch (value->type) { - case JVAL_COLLECTION: - if (value->collection->begin) { - free_json(&(value->collection->begin)); + jentity_t *parent = current->parent; + jcoll_t *collection = NULL; + + if (parent->type == JENTITY_SINGLE) { + collection = parent->value.collection; + } else { + collection = parent->pair.value.collection; + } + + if (collection) { + collection->begin = current->next; + } } - free(value->collection); + if (current->type == JENTITY_SINGLE) { + key = NULL; + value = &(current->value); + } else { + key = current->pair.key; + value = &(current->pair.value); + } - break; - case JVAL_STRING: - dstr_free(&(entt_ptr->pair.value.string)); + if (key) { + dstr_free(&(current->pair.key)); + } - break; - default: - break; + if (!value) { + break; + } + + if (value->type == JVAL_COLLECTION) { + if (!(value->collection->begin)) { + // Once all children of the collection has been freed, free the memory + // allocated to the collection and the entity that holds it + + free(value->collection); + + temp = current; + + current = current->next != NULL ? current->next : current->parent; + + free(temp); + temp = NULL; + + continue; + } + + current = value->collection->begin; + } else { + if (value->type == JVAL_STRING) { + dstr_free(&(value->string)); + } + + temp = current; + + current = current->next != NULL ? current->next : current->parent; + + free(temp); + temp = NULL; + } } - if (entt_ptr->next) { - free_json(&(entt_ptr->next)); - } - - free(*entity); - *entity = NULL; + *root = NULL; } jcoll_t *get_collection_from_entity(const jentity_t *entity) {