Skip to content

Commit 9ed74ea

Browse files
committed
Implemented a destructor for JSON values.
The destructor recursively traverses the object tree releasing memory accordingly. Since, key-value pairs are stored in a hash map, the key needs to persist longer than the lifetime of a token, which is where we derive the key from. As of now, tokens are not freed. In the future, we need to implement a recyclable token that is destroyed along with the parser.
1 parent 4bc50d3 commit 9ed74ea

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

include/jtk/support/json.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ jtk_JsonValue_t* jtk_JsonValue_forString(const uint8_t* text, int32_t length);
6262
jtk_JsonValue_t* jtk_JsonValue_forNumber(const uint8_t* text, int32_t length);
6363
jtk_JsonValue_t* jtk_JsonValue_forTrue();
6464
jtk_JsonValue_t* jtk_JsonValue_forFalse();
65+
void jtk_JsonValue_delete(jtk_JsonValue_t* value);
6566

6667
jtk_JsonValue_t* jtk_parseJson(const uint8_t* sequence, int32_t size, jtk_JsonError_t* error);
6768

source/jtk/support/json.c

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,7 @@ Token* nextToken(Parser* parser) {
641641
return newToken;
642642
}
643643

644+
// TODO: Recycle the token object and delete it along with the parser.
644645
Token* consume(Parser* parser) {
645646
Token* temporary = parser->lt1;
646647
parser->lt1 = nextToken(parser);
@@ -688,9 +689,10 @@ jtk_JsonValue_t* parseObject(Parser* parser) {
688689

689690
if (parser->lt1->type == TOKEN_STRING) {
690691
Token* key = consume(parser);
692+
uint8_t* keyText = jtk_CString_newEx(key->text, key->length);
691693
match(parser, TOKEN_COLON);
692694
jtk_JsonValue_t* value = parseValue(parser);
693-
jtk_HashMap_put(result->object, key->text, value);
695+
jtk_HashMap_put(result->object, keyText, value);
694696

695697
while (parser->lt1->type == TOKEN_COMMA) {
696698
consume(parser);
@@ -825,6 +827,36 @@ jtk_JsonValue_t* jtk_JsonValue_forTrue() {
825827
return value;
826828
}
827829

830+
void jtk_JsonValue_delete(jtk_JsonValue_t* value) {
831+
if (value != NULL) {
832+
if (value->type == JTK_JSON_VALUE_STRING) {
833+
jtk_CString_delete(value->string.bytes);
834+
}
835+
else if (value->type == JTK_JSON_VALUE_ARRAY) {
836+
int32_t limit = jtk_ArrayList_getSize(value->array);
837+
int32_t i;
838+
for (i = 0; i < limit; i++) {
839+
jtk_JsonValue_t* temporary =
840+
(jtk_JsonValue_t*)jtk_ArrayList_getValue(value->array, i);
841+
jtk_JsonValue_delete(temporary);
842+
}
843+
jtk_ArrayList_delete(value->array);
844+
}
845+
else if (value->type == JTK_JSON_VALUE_OBJECT) {
846+
jtk_Iterator_t* iterator = jtk_HashMap_getEntryIterator(value->object);
847+
while (jtk_Iterator_hasNext(iterator)) {
848+
jtk_HashMapEntry_t* entry =
849+
(jtk_HashMapEntry_t*)jtk_Iterator_getNext(iterator);
850+
jtk_CString_delete((uint8_t*)entry->m_key);
851+
jtk_JsonValue_delete((jtk_JsonValue_t*)entry->m_value);
852+
}
853+
jtk_Iterator_delete(iterator);
854+
jtk_HashMap_delete(value->object);
855+
}
856+
deallocate(value);
857+
}
858+
}
859+
828860
void handleError() {
829861
printf("Errro!\n");
830862
}
@@ -852,6 +884,7 @@ void toString(jtk_StringBuilder_t* builder, jtk_JsonValue_t* value) {
852884

853885
first = false;
854886
}
887+
jtk_Iterator_delete(iterator);
855888
jtk_StringBuilder_appendCodePoint(builder, '}');
856889
}
857890
else if (value->type == JTK_JSON_VALUE_ARRAY) {
@@ -896,6 +929,7 @@ void toPrettyString(jtk_StringBuilder_t* builder, jtk_JsonValue_t* value,
896929

897930
first = false;
898931
}
932+
jtk_Iterator_delete(iterator);
899933
jtk_StringBuilder_appendCodePoint(builder, '\n');
900934
indent(builder, depth);
901935
jtk_StringBuilder_appendCodePoint(builder, '}');

0 commit comments

Comments
 (0)