diff --git a/cfg.h b/cfg.h index 8cd2a7f..85ac215 100644 --- a/cfg.h +++ b/cfg.h @@ -149,7 +149,7 @@ size_t string_hash(string* s) { ///// list is a list with a length and on-demand growing/shrinking -#define LIST(type) \ +#define LIST(type, cleanup) \ typedef struct list_##type { \ size_t len; \ size_t cap; \ @@ -169,6 +169,8 @@ list_##type new_list_##type() { \ } \ \ void free_list_##type(list_##type l) { \ + size_t i; \ + for (i = 0; i < l.len; i++) cleanup(l.data[i]); \ free(l.data); \ } \ \ @@ -208,16 +210,22 @@ void list_set_nth_##type(list_##type* l, size_t n, type elem) { \ ///// map is a hashmap -#define MAP(key_type, val_type, hash, cmp) \ +#define MAP(key_type, val_type, hash, cmp, key_cleanup, val_cleanup) \ typedef struct entry_##key_type##_##val_type { \ key_type key; \ val_type val; \ } entry_##key_type##_##val_type; \ \ -LIST(entry_##key_type##_##val_type); \ -LIST(list_entry_##key_type##_##val_type); \ -LIST(key_type); \ -LIST(val_type); \ +\ +void entry_##key_type##_##val_type##_cleanup(entry_##key_type##_##val_type e) {\ + key_cleanup(e.key);\ + val_cleanup(e.val);\ +}\ +\ +LIST(entry_##key_type##_##val_type, entry_##key_type##_##val_type##_cleanup); \ +LIST(list_entry_##key_type##_##val_type, free_list_entry_##key_type##_##val_type); \ +LIST(key_type, key_cleanup); \ +LIST(val_type, val_cleanup); \ \ typedef struct map_##key_type##_##val_type { \ list_list_entry_##key_type##_##val_type entries; \ @@ -333,7 +341,9 @@ typedef struct config_value { config_value zero_config_value = {0}; -MAP(string, config_value, string_hash, string_compare); +void free_config_value(config_value); + +MAP(string, config_value, string_hash, string_compare, free_string, free_config_value); struct config { map_string_config_value values; @@ -346,7 +356,26 @@ struct config { //// Functions -////// config value functions +void free_config(config c) { + free_map_string_config_value(c.values); +} + +void free_config_value(config_value c) { + switch (c.tag) { + case config_value_section: + free_config(*c.section); + free(c.section); + break; + case config_value_string: + free_string(c.s); + break; + case config_value_list: + free_list_config_value(*c.l); + free(c.l); + break; + // number does not need to be freed + } +} bool config_value_compare(config_value* a, config_value* b) { if (a->tag != b->tag) return false; diff --git a/examples/nested_simple.c b/examples/nested_simple.c index 80ea3a9..f0977e7 100644 --- a/examples/nested_simple.c +++ b/examples/nested_simple.c @@ -5,16 +5,18 @@ int main() { string key; config_add_number(&c, string_from_cstr("mynum"), 42); config_add_string(&c, string_from_cstr("mystring"), string_from_cstr("cfg is pretty awesome")); - list_config_value l = new_list_config_value(); + list_config_value* l = malloc(sizeof(list_config_value)); + *l = new_list_config_value(); for (int i = 0; i < 10; i += 2) { - list_push_config_value(&l, config_number(i)); + list_push_config_value(l, config_number(i)); } - list_push_config_value(&l, config_string(string_from_cstr("value"))); - config_add_list(&c, string_from_cstr("mylist"), &l); - config sub = new_config(); - config_add_number(&sub, string_from_cstr("mysecondnum"), 23); - config_add_string(&sub, string_from_cstr("mysecondstring"), string_from_cstr("\"inner\"\"quoted\"")); - config_add_section(&c, string_from_cstr("mysection"), &sub); + list_push_config_value(l, config_string(string_from_cstr("value"))); + config_add_list(&c, string_from_cstr("mylist"), l); + config* sub = malloc(sizeof(config)); + *sub = new_config(); + config_add_number(sub, string_from_cstr("mysecondnum"), 23); + config_add_string(sub, string_from_cstr("mysecondstring"), string_from_cstr("\"inner\"\"quoted\"")); + config_add_section(&c, string_from_cstr("mysection"), sub); string s = config_str(&c, 0); char* cstr = string_cstr(&s); @@ -22,5 +24,6 @@ int main() { printf("%s\n", cstr); free_string(s); free(cstr); + free_config(c); return 0; } diff --git a/examples/parser_simple.c b/examples/parser_simple.c index 8a1332d..d28be7b 100644 --- a/examples/parser_simple.c +++ b/examples/parser_simple.c @@ -33,5 +33,6 @@ int main(int argc, char** argv) { free_string(str); free(cstr); free(contents); + free_config(c.c); return 0; }