immovable
This commit is contained in:
45
cfg.h
45
cfg.h
@@ -149,7 +149,7 @@ size_t string_hash(string* s) {
|
|||||||
|
|
||||||
///// list is a list with a length and on-demand growing/shrinking
|
///// list is a list with a length and on-demand growing/shrinking
|
||||||
|
|
||||||
#define LIST(type) \
|
#define LIST(type, cleanup) \
|
||||||
typedef struct list_##type { \
|
typedef struct list_##type { \
|
||||||
size_t len; \
|
size_t len; \
|
||||||
size_t cap; \
|
size_t cap; \
|
||||||
@@ -169,6 +169,8 @@ list_##type new_list_##type() { \
|
|||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
void free_list_##type(list_##type l) { \
|
void free_list_##type(list_##type l) { \
|
||||||
|
size_t i; \
|
||||||
|
for (i = 0; i < l.len; i++) cleanup(l.data[i]); \
|
||||||
free(l.data); \
|
free(l.data); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
@@ -208,16 +210,22 @@ void list_set_nth_##type(list_##type* l, size_t n, type elem) { \
|
|||||||
|
|
||||||
///// map is a hashmap
|
///// 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 { \
|
typedef struct entry_##key_type##_##val_type { \
|
||||||
key_type key; \
|
key_type key; \
|
||||||
val_type val; \
|
val_type val; \
|
||||||
} entry_##key_type##_##val_type; \
|
} entry_##key_type##_##val_type; \
|
||||||
\
|
\
|
||||||
LIST(entry_##key_type##_##val_type); \
|
\
|
||||||
LIST(list_entry_##key_type##_##val_type); \
|
void entry_##key_type##_##val_type##_cleanup(entry_##key_type##_##val_type e) {\
|
||||||
LIST(key_type); \
|
key_cleanup(e.key);\
|
||||||
LIST(val_type); \
|
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 { \
|
typedef struct map_##key_type##_##val_type { \
|
||||||
list_list_entry_##key_type##_##val_type entries; \
|
list_list_entry_##key_type##_##val_type entries; \
|
||||||
@@ -333,7 +341,9 @@ typedef struct config_value {
|
|||||||
|
|
||||||
config_value zero_config_value = {0};
|
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 {
|
struct config {
|
||||||
map_string_config_value values;
|
map_string_config_value values;
|
||||||
@@ -346,7 +356,26 @@ struct config {
|
|||||||
|
|
||||||
//// Functions
|
//// 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) {
|
bool config_value_compare(config_value* a, config_value* b) {
|
||||||
if (a->tag != b->tag) return false;
|
if (a->tag != b->tag) return false;
|
||||||
|
@@ -5,16 +5,18 @@ int main() {
|
|||||||
string key;
|
string key;
|
||||||
config_add_number(&c, string_from_cstr("mynum"), 42);
|
config_add_number(&c, string_from_cstr("mynum"), 42);
|
||||||
config_add_string(&c, string_from_cstr("mystring"), string_from_cstr("cfg is pretty awesome"));
|
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) {
|
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")));
|
list_push_config_value(l, config_string(string_from_cstr("value")));
|
||||||
config_add_list(&c, string_from_cstr("mylist"), &l);
|
config_add_list(&c, string_from_cstr("mylist"), l);
|
||||||
config sub = new_config();
|
config* sub = malloc(sizeof(config));
|
||||||
config_add_number(&sub, string_from_cstr("mysecondnum"), 23);
|
*sub = new_config();
|
||||||
config_add_string(&sub, string_from_cstr("mysecondstring"), string_from_cstr("\"inner\"\"quoted\""));
|
config_add_number(sub, string_from_cstr("mysecondnum"), 23);
|
||||||
config_add_section(&c, string_from_cstr("mysection"), &sub);
|
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);
|
string s = config_str(&c, 0);
|
||||||
char* cstr = string_cstr(&s);
|
char* cstr = string_cstr(&s);
|
||||||
@@ -22,5 +24,6 @@ int main() {
|
|||||||
printf("%s\n", cstr);
|
printf("%s\n", cstr);
|
||||||
free_string(s);
|
free_string(s);
|
||||||
free(cstr);
|
free(cstr);
|
||||||
|
free_config(c);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -33,5 +33,6 @@ int main(int argc, char** argv) {
|
|||||||
free_string(str);
|
free_string(str);
|
||||||
free(cstr);
|
free(cstr);
|
||||||
free(contents);
|
free(contents);
|
||||||
|
free_config(c.c);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user