Work out more details of how json_free() needs to work.

The idea is that you can free any element once you are
done with it, even if it is part of an array or hash that
isn't completely read yet.

Removing array elements is reasonably well defined because
nothing else depends on them. Removing a hash key or value
causes it to be replaced by a null unless the other side of
the component has already been nulled out, in which case
the whole pair is removed.
This commit is contained in:
Eric Fischer 2014-02-06 22:45:40 -08:00
parent f0f73c6dd1
commit f67e97cd08
2 changed files with 49 additions and 17 deletions

View File

@ -459,6 +459,17 @@ again:
return NULL;
}
static json_object *fabricate_null(json_object *parent) {
json_object *o = malloc(sizeof(struct json_object));
o->type = JSON_NULL;
o->parent = parent;
o->array = NULL;
o->keys = NULL;
o->values = NULL;
o->length = 0;
return o;
}
void json_free(json_object *o) {
int i;
@ -469,14 +480,33 @@ void json_free(json_object *o) {
// Free any data linked from here
if (o->type == JSON_ARRAY) {
for (i = 0; i < o->length; i++) {
json_free(o->array[i]);
json_object **a = o->array;
int n = o->length;
o->array = NULL;
o->length = 0;
for (i = 0; i < n; i++) {
json_free(a[i]);
}
free(a);
} else if (o->type == JSON_HASH) {
for (i = 0; i < o->length; i++) {
json_free(o->keys[i]);
json_free(o->values[i]);
json_object **k = o->keys;
json_object **v = o->values;
int n = o->length;
o->keys = NULL;
o->values = NULL;
o->length = 0;
for (i = 0; i < n; i++) {
json_free(k[i]);
json_free(v[i]);
}
free(k);
free(v);
} else if (o->type == JSON_STRING) {
free(o->string);
}
@ -500,24 +530,25 @@ void json_free(json_object *o) {
if (o->parent->type == JSON_HASH) {
for (i = 0; i < o->parent->length; i++) {
if (o->parent->keys[i] == o || o->parent->values[i] == o) {
if (o->parent->keys[i] == o) {
o->parent->keys[i] = fabricate_null(o->parent);
break;
}
if (o->parent->values[i] == o) {
o->parent->values[i] = fabricate_null(o->parent);
break;
}
}
if (i < o->parent->length) {
json_object *k = o->parent->keys[i];
json_object *v = o->parent->values[i];
if (o->parent->keys[i] != NULL && o->parent->keys[i]->type == JSON_NULL) {
if (o->parent->values[i] != NULL && o->parent->values[i]->type == JSON_NULL) {
free(o->parent->keys[i]);
free(o->parent->values[i]);
memmove(o->parent->keys + i, o->parent->keys + i + 1, o->parent->length - i - 1);
memmove(o->parent->values + i, o->parent->values + i + 1, o->parent->length - i - 1);
o->parent->length--;
if (o->parent->values[i] == NULL) {
// Have not yet read the value for this pair
} else {
if (o->parent->keys[i] == o) {
} else {
memmove(o->parent->keys + i, o->parent->keys + i + 1, o->parent->length - i - 1);
memmove(o->parent->values + i, o->parent->values + i + 1, o->parent->length - i - 1);
o->parent->length--;
}
}
}

View File

@ -33,5 +33,6 @@ typedef struct json_pull json_pull;
json_pull *json_begin_file(FILE *f);
json_pull *json_begin_string(char *s);
json_object *json_parse(json_pull *j);
void json_free(json_object *j);
json_object *json_hash_get(json_object *o, char *s);