1#ifndef KEST_DICTIONARY_H_
2#define KEST_DICTIONARY_H_
4#define DICT_ENTRY_TYPE_NOT_FOUND 22222
5#define DICT_ENTRY_TYPE_NOTHING 22221
6#define DICT_ENTRY_TYPE_INT 0
7#define DICT_ENTRY_TYPE_FLOAT 1
8#define DICT_ENTRY_TYPE_STR 2
9#define DICT_ENTRY_TYPE_EXPR 3
10#define DICT_ENTRY_TYPE_SUBDICT 4
11#define DICT_ENTRY_TYPE_LIST 5
14struct kest_dictionary_entry_ptr_list;
58#define KEST_DICTIONARY_N_BUCKETS 8
87#define ERR_NOT_FOUND 10
88#define ERR_WRONG_TYPE 11
97#define DECLARE_PTR_DICT(X) \
101} X##_ptr_dict_entry; \
103DECLARE_LIST(X##_ptr_dict_entry);\
104typedef X##_ptr_dict_entry_list X##_ptr_dict_bucket;\
107 X##_ptr_dict_bucket *buckets;\
109 kest_allocator alloc;\
112int X##_ptr_dict_init(X##_ptr_dict *dict, size_t n_buckets);\
113int X##_ptr_dict_init_with_allocator(X##_ptr_dict *dict, size_t n_buckets, kest_allocator *alloc);\
114int X##_ptr_dict_insert(X##_ptr_dict *dict, char *key, X *x);\
115X *X##_ptr_dict_lookup(X##_ptr_dict *dict, const char *key);\
116size_t X##_ptr_dict_count(X##_ptr_dict *dict);\
117X *X##_ptr_dict_index(X##_ptr_dict *dict, size_t n);\
118void X##_ptr_dict_destroy(X##_ptr_dict *dict, void (*destructor)(X *x));
120#define IMPLEMENT_PTR_DICT(X) \
121IMPLEMENT_LIST(X##_ptr_dict_entry);\
122int X##_ptr_dict_init(X##_ptr_dict *dict, size_t n_buckets)\
124 return X##_ptr_dict_init_with_allocator(dict, n_buckets, NULL);\
127int X##_ptr_dict_init_with_allocator(X##_ptr_dict *dict, size_t n_buckets, kest_allocator *alloc)\
129 if (!dict) return ERR_NULL_PTR;\
132 dict->buckets = NULL;\
133 dict->n_buckets = 0;\
134 dict->alloc = alloc ? *alloc : (kest_allocator){0};\
138 dict->n_buckets = 0;\
139 dict->buckets = kest_allocator_alloc(alloc, sizeof(X##_ptr_dict_bucket) * n_buckets);\
142 return ERR_ALLOC_FAIL;\
144 for (size_t i = 0; i < n_buckets; i++)\
145 X##_ptr_dict_entry_list_init_with_allocator(&dict->buckets[i], alloc);\
147 dict->n_buckets = n_buckets;\
148 dict->alloc = alloc ? *alloc : (kest_allocator){0};\
153int X##_ptr_dict_entry_cmp(const X##_ptr_dict_entry *a, const X##_ptr_dict_entry *b)\
155 if (!a || !b) return -1;\
156 if (!a->key || !b->key) return -1;\
157 return strcmp(a->key, b->key);\
160int X##_ptr_dict_insert(X##_ptr_dict *dict, char *key, X *x)\
162 if (!dict) return ERR_NULL_PTR;\
163 if (!key) return ERR_BAD_ARGS;\
164 if (!dict->n_buckets) return ERR_BAD_ARGS;\
166 size_t bucket = hash(key) % dict->n_buckets;\
168 X##_ptr_dict_entry entry = {.key = key, .data = x};\
170 int index = X##_ptr_dict_entry_list_index_of(&dict->buckets[bucket], entry, X##_ptr_dict_entry_cmp);\
173 return ERR_DUPLICATE_KEY;\
175 entry.key = kest_allocator_strndup(&dict->alloc, key, 1024);\
178 return ERR_ALLOC_FAIL;\
180 return X##_ptr_dict_entry_list_append(&dict->buckets[bucket], entry);\
182X *X##_ptr_dict_lookup(X##_ptr_dict *dict, const char *key)\
184 if (!dict || !key) return NULL;\
185 if (!dict->n_buckets) return NULL;\
187 X##_ptr_dict_entry entry = {.key = key, .data = NULL};\
189 size_t bucket = hash(key) % dict->n_buckets;\
191 int index = X##_ptr_dict_entry_list_index_of(&dict->buckets[bucket], entry, X##_ptr_dict_entry_cmp);\
193 if (index >= 0 && index < dict->buckets[bucket].count)\
194 return dict->buckets[bucket].entries[index].data;\
198size_t X##_ptr_dict_count(X##_ptr_dict *dict)\
200 if (!dict) return 0;\
202 if (!dict->buckets || !dict->n_buckets)\
206 for (size_t i = 0; i < dict->n_buckets; i++)\
208 count += dict->buckets[i].count;\
213X *X##_ptr_dict_index(X##_ptr_dict *dict, size_t n)\
215 if (!dict) return NULL;\
217 if (!dict->buckets || !dict->n_buckets)\
220 for (size_t i = 0; i < dict->n_buckets; i++)\
222 if (dict->buckets[i].count > n)\
223 return dict->buckets[i].entries[n].data;\
225 n -= dict->buckets[i].count;\
230void X##_ptr_dict_destroy(X##_ptr_dict *dict, void (*destructor)(X *x))\
237 for (size_t i = 0; i < dict->n_buckets; i++)\
239 for (size_t j = 0; j < dict->buckets[i].count; j++) \
242 destructor(dict->buckets[i].entries[j].data); \
243 kest_allocator_free(&dict->alloc, dict->buckets[i].entries[j].key);\
246 kest_allocator_free(&dict->buckets[i].alloc, dict->buckets[i].entries); \
248 dict->buckets[i].entries = NULL; \
249 dict->buckets[i].count = 0; \
250 dict->buckets[i].capacity = 0; \
254 kest_allocator_free(&dict->alloc, dict->buckets);\
255 dict->buckets = NULL;\
258 dict->n_buckets = 0;\
int kest_dictionary_lookup_dict(kest_dictionary *dict, const char *name, kest_dictionary **result)
int kest_dictionary_bucket_lookup_int(kest_dictionary_bucket *dict, const char *name, int *result)
int kest_dictionary_lookup_int(kest_dictionary *dict, const char *name, int *result)
int kest_dictionary_lookup_list(kest_dictionary *dict, const char *name, kest_dictionary_entry_list **result)
int kest_dictionary_bucket_lookup_float(kest_dictionary_bucket *dict, const char *name, float *result)
kest_string * kest_dict_entry_to_string(kest_dictionary_entry *entry)
void print_dict(kest_dictionary *dict)
int kest_dictionary_bucket_add_entry_str(kest_dictionary_bucket *dict, const char *name, const char *value)
int kest_parse_dict_val(struct kest_eff_parsing_state *ps, kest_dictionary *dict, kest_dictionary_entry *result)
int kest_dictionary_bucket_add_entry_int(kest_dictionary_bucket *dict, const char *name, int value)
int kest_dictionary_bucket_add_entry(kest_dictionary_bucket *dict, kest_dictionary_entry entry)
int kest_dictionary_bucket_lookup_str(kest_dictionary_bucket *dict, const char *name, const char **result)
int kest_parse_dictionary(struct kest_eff_parsing_state *ps, kest_dictionary **result, const char *name)
int kest_dictionary_add_entry_float(kest_dictionary *dict, const char *name, float value)
int kest_dictionary_lookup_str(kest_dictionary *dict, const char *name, const char **result)
int kest_dictionary_bucket_lookup_expr(kest_dictionary_bucket *dict, const char *name, kest_expression **result)
int kest_dictionary_bucket_lookup_dict(kest_dictionary_bucket *dict, const char *name, struct kest_dictionary **result)
const char * kest_dict_entry_type_to_string(int type)
kest_dictionary * kest_new_dictionary()
int kest_dictionary_lookup_expr(kest_dictionary *dict, const char *name, kest_expression **result)
int kest_dictionary_bucket_add_entry_float(kest_dictionary_bucket *dict, const char *name, float value)
int kest_dictionary_bucket_add_entry_expr(kest_dictionary_bucket *dict, const char *name, kest_expression *value)
const char * kest_dict_entry_type_to_string_nice(int type)
int kest_dictionary_lookup_float(kest_dictionary *dict, const char *name, float *result)
int kest_dictionary_add_entry_dict(kest_dictionary *dict, const char *name, kest_dictionary *value)
int kest_dictionary_bucket_add_entry_dict(kest_dictionary_bucket *dict, const char *name, struct kest_dictionary *value)
int kest_dictionary_add_entry(kest_dictionary *dict, kest_dictionary_entry entry)
#define KEST_DICTIONARY_N_BUCKETS
int kest_dictionary_add_entry_expr(kest_dictionary *dict, const char *name, kest_expression *value)
int kest_dictionary_add_entry_str(kest_dictionary *dict, const char *name, const char *value)
int kest_dictionary_add_entry_int(kest_dictionary *dict, const char *name, int value)
kest_dictionary_entry * entries
struct kest_dictionary * val_dict
struct kest_dictionary_entry_list * val_list
kest_expression * val_expr
kest_dictionary_entry * entries
kest_dictionary_bucket buckets[KEST_DICTIONARY_N_BUCKETS]
kest_effect_desc * result