Fix all memory leaks
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
|
||||
#include <stdbool.h> // bool
|
||||
|
||||
#define OBJ_SIZE 64
|
||||
#define OBJ_SIZE 32
|
||||
|
||||
typedef struct obj_entry {
|
||||
char const* key;
|
||||
@@ -25,7 +25,7 @@ struct json_value {
|
||||
enum json_type type;
|
||||
union {
|
||||
obj_t* object;
|
||||
struct json_value** array;
|
||||
struct json_value** array; // we need an array of pointers to allow null termination
|
||||
char* string;
|
||||
bool boolean;
|
||||
double number;
|
||||
@@ -34,8 +34,10 @@ struct json_value {
|
||||
|
||||
void* obj_at(obj_t m, char* const key);
|
||||
bool obj_insert(obj_t m, char* const key, struct json_value* value);
|
||||
void obj_delete(obj_t m);
|
||||
void obj_delete(obj_t* m);
|
||||
|
||||
void print_json(struct json_value val, int indent);
|
||||
|
||||
void json_value_delete(struct json_value val);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -10,11 +10,12 @@
|
||||
|
||||
bool obj_insert(obj_t m, char* const key, struct json_value* value);
|
||||
size_t obj_hash(char const* str);
|
||||
void obj_delete(obj_t m);
|
||||
void obj_delete(obj_t* m);
|
||||
void* obj_at(obj_t m, char* const key);
|
||||
|
||||
void print_array(struct json_value** arr, int cur_indent, int indent_amount);
|
||||
void print_json_value(struct json_value val, int cur_indent, int indent_amount);
|
||||
void print_object(obj_t obj, int cur_indent, int indent_amount);
|
||||
void* obj_at(obj_t m, char* const key);
|
||||
|
||||
/*
|
||||
djb2 string hash
|
||||
@@ -104,7 +105,7 @@ bool obj_insert(obj_t m, char* const key, struct json_value* value)
|
||||
|
||||
/* populate new entry */
|
||||
cur = malloc_or_die(sizeof(struct obj_entry));
|
||||
cur->key = strdup(key);
|
||||
cur->key = key;
|
||||
cur->val = value;
|
||||
cur->next = m[i];
|
||||
|
||||
@@ -114,27 +115,52 @@ bool obj_insert(obj_t m, char* const key, struct json_value* value)
|
||||
return true;
|
||||
}
|
||||
|
||||
void json_value_delete(struct json_value val)
|
||||
{
|
||||
switch (val.type) {
|
||||
case array:
|
||||
for (size_t i = 0; val.array[i] != NULL; i++) {
|
||||
json_value_delete(*(val.array[i]));
|
||||
free(val.array[i]);
|
||||
}
|
||||
|
||||
free(val.array);
|
||||
break;
|
||||
|
||||
case object:
|
||||
obj_delete(val.object);
|
||||
break;
|
||||
|
||||
case string:
|
||||
free(val.string);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Free memory allocated for obj
|
||||
|
||||
TODO: recurively delete children objects
|
||||
*/
|
||||
void obj_delete(obj_t m)
|
||||
void obj_delete(obj_t* m)
|
||||
{
|
||||
for (size_t i = 0; i < OBJ_SIZE; i++) {
|
||||
if (m[i] == NULL)
|
||||
continue;
|
||||
|
||||
struct obj_entry *e = m[i], *tmp;
|
||||
struct obj_entry *e = (*m)[i], *tmp;
|
||||
|
||||
while (e != NULL) {
|
||||
tmp = e;
|
||||
json_value_delete(*(e->val));
|
||||
free((char*)e->key);
|
||||
free(e->val);
|
||||
|
||||
tmp = e;
|
||||
e = e->next;
|
||||
free(tmp);
|
||||
}
|
||||
}
|
||||
free(m);
|
||||
}
|
||||
|
||||
void add_indent(int n)
|
||||
@@ -181,7 +207,7 @@ void print_array(struct json_value** arr, int cur_indent, int indent_amount)
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; arr[i+1] != NULL; i++) {
|
||||
for (size_t i = 0; arr[i + 1] != NULL; i++) {
|
||||
putchar('\n');
|
||||
add_indent(cur_indent);
|
||||
print_json_value(*arr[i], cur_indent + indent_amount, indent_amount);
|
||||
|
||||
@@ -16,9 +16,13 @@ int main(int argc, char* argv[])
|
||||
|
||||
FILE* fp = fopen(argv[1], "r");
|
||||
|
||||
volatile struct json_value x = parse_json_value(fp);
|
||||
struct json_value x = parse_json_value(fp);
|
||||
|
||||
print_json(x, 1);
|
||||
// print_json(x, 1);
|
||||
|
||||
json_value_delete(x);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
25
src/parse.c
25
src/parse.c
@@ -113,7 +113,7 @@ struct json_value parse_json_value(FILE* fp)
|
||||
char* read_string(FILE* fp)
|
||||
{
|
||||
int c;
|
||||
size_t i = 0, result_size = 16 * sizeof(char);
|
||||
size_t i = 0, result_size = 16;
|
||||
char* result = malloc_or_die(result_size);
|
||||
|
||||
bool escaped = false;
|
||||
@@ -141,6 +141,7 @@ char* read_string(FILE* fp)
|
||||
return realloc_or_die(result, i);
|
||||
|
||||
case EOF:
|
||||
free(result);
|
||||
err_ctx(EARLY_EOF, fp, "(%s) unexpected EOF", __func__);
|
||||
|
||||
default:
|
||||
@@ -170,9 +171,11 @@ obj_t* read_object(FILE* fp)
|
||||
|
||||
switch (fgetc(fp)) {
|
||||
case EOF:
|
||||
free(result);
|
||||
err_ctx(EARLY_EOF, fp, "(%s) unexpected EOF", __func__);
|
||||
|
||||
default:
|
||||
free(result);
|
||||
err_ctx(UNEXPECTED_CHAR, fp, "(%s) expected \"", __func__);
|
||||
|
||||
case '"':
|
||||
@@ -191,9 +194,11 @@ obj_t* read_object(FILE* fp)
|
||||
break;
|
||||
|
||||
case EOF:
|
||||
free(result);
|
||||
err_ctx(EARLY_EOF, fp, "(%s) unexpected EOF", __func__);
|
||||
|
||||
default:
|
||||
free(result);
|
||||
err_ctx(UNEXPECTED_CHAR, fp, "(%s) expected ':'", __func__);
|
||||
}
|
||||
|
||||
@@ -204,14 +209,19 @@ obj_t* read_object(FILE* fp)
|
||||
*val = parse_json_value(fp);
|
||||
|
||||
/* insert key-value pair to obj */
|
||||
if (!obj_insert(*result, key, val))
|
||||
if (!obj_insert(*result, key, val)) {
|
||||
free(result);
|
||||
free(val);
|
||||
errx(EXIT_FAILURE, "failed to insert pair (%s, %p)", key, (void*)val);
|
||||
}
|
||||
|
||||
/* read separator or end of object */
|
||||
discard_whitespace(fp);
|
||||
|
||||
switch (fgetc(fp)) {
|
||||
case EOF:
|
||||
free(val);
|
||||
free(result);
|
||||
err_ctx(EARLY_EOF, fp, "(%s) unexpected EOF", __func__);
|
||||
|
||||
case ',':
|
||||
@@ -221,6 +231,8 @@ obj_t* read_object(FILE* fp)
|
||||
return result;
|
||||
|
||||
default:
|
||||
free(val);
|
||||
free(result);
|
||||
err_ctx(UNEXPECTED_CHAR, fp, "(%s) expected ',' or '}'", __func__);
|
||||
}
|
||||
}
|
||||
@@ -252,6 +264,11 @@ struct json_value** read_array(FILE* fp)
|
||||
|
||||
switch (c) {
|
||||
case EOF:
|
||||
free(output);
|
||||
|
||||
for (size_t j = 0; j < i; j++)
|
||||
free(output[j]);
|
||||
|
||||
err_ctx(EARLY_EOF, fp, "(%s) unexpected EOF", __func__);
|
||||
break;
|
||||
|
||||
@@ -281,7 +298,7 @@ struct json_value** read_array(FILE* fp)
|
||||
void read_null(FILE* fp)
|
||||
{
|
||||
static const char ok[] = { 'n', 'u', 'l', 'l' };
|
||||
char buf[sizeof(ok)];
|
||||
static char buf[sizeof(ok)];
|
||||
|
||||
size_t n_read = fread(buf, sizeof(char), sizeof(ok), fp);
|
||||
|
||||
@@ -304,7 +321,7 @@ bool read_boolean(FILE* fp)
|
||||
static const char t[] = { 't', 'r', 'u', 'e' };
|
||||
static const char f[] = { 'f', 'a', 'l', 's', 'e' };
|
||||
|
||||
char buf[sizeof(f)] = { 0 };
|
||||
static char buf[sizeof(f)] = { 0 };
|
||||
|
||||
size_t n_read = fread(buf, sizeof(char), sizeof(f), fp);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user