Kestrel Interface
Loading...
Searching...
No Matches
kest_dictionary.h
Go to the documentation of this file.
1#ifndef KEST_DICTIONARY_H_
2#define KEST_DICTIONARY_H_
3
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
12
13struct kest_dictionary;
14struct kest_dictionary_entry_ptr_list;
15
16typedef struct {
17 const char *name;
18 int type;
19 int line;
20 union {
22 float val_float;
23 const char *val_string;
26 struct kest_dictionary_entry_list *val_list;
27 } value;
29
31
32const char *kest_dict_entry_type_to_string(int type);
33const char *kest_dict_entry_type_to_string_nice(int type);
35
41
42struct kest_dictionary;
43
45
46int kest_dictionary_bucket_add_entry_str (kest_dictionary_bucket *dict, const char *name, const char *value);
47int kest_dictionary_bucket_add_entry_int (kest_dictionary_bucket *dict, const char *name, int value);
48int kest_dictionary_bucket_add_entry_float(kest_dictionary_bucket *dict, const char *name, float value);
51
52int kest_dictionary_bucket_lookup_str (kest_dictionary_bucket *dict, const char *name, const char **result);
53int kest_dictionary_bucket_lookup_float(kest_dictionary_bucket *dict, const char *name, float *result);
54int kest_dictionary_bucket_lookup_int (kest_dictionary_bucket *dict, const char *name, int *result);
57
58#define KEST_DICTIONARY_N_BUCKETS 8
59
69
71
73
74int kest_dictionary_add_entry_str (kest_dictionary *dict, const char *name, const char *value);
75int kest_dictionary_add_entry_int (kest_dictionary *dict, const char *name, int value);
76int kest_dictionary_add_entry_float(kest_dictionary *dict, const char *name, float value);
77int kest_dictionary_add_entry_expr (kest_dictionary *dict, const char *name, kest_expression *value);
78int kest_dictionary_add_entry_dict (kest_dictionary *dict, const char *name, kest_dictionary *value);
79
80int kest_dictionary_lookup_str (kest_dictionary *dict, const char *name, const char **result);
81int kest_dictionary_lookup_float(kest_dictionary *dict, const char *name, float *result);
82int kest_dictionary_lookup_int (kest_dictionary *dict, const char *name, int *result);
83int kest_dictionary_lookup_expr (kest_dictionary *dict, const char *name, kest_expression **result);
84int kest_dictionary_lookup_list (kest_dictionary *dict, const char *name, kest_dictionary_entry_list **result);
85int kest_dictionary_lookup_dict (kest_dictionary *dict, const char *name, kest_dictionary **result);
86
87#define ERR_NOT_FOUND 10
88#define ERR_WRONG_TYPE 11
89
90void print_dict(kest_dictionary *dict);
91
93
96
97#define DECLARE_PTR_DICT(X) \
98typedef struct {\
99 const char *key; \
100 X *data; \
101} X##_ptr_dict_entry; \
102\
103DECLARE_LIST(X##_ptr_dict_entry);\
104typedef X##_ptr_dict_entry_list X##_ptr_dict_bucket;\
105\
106typedef struct {\
107 X##_ptr_dict_bucket *buckets;\
108 size_t n_buckets;\
109 kest_allocator alloc;\
110} X##_ptr_dict;\
111\
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));
119
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)\
123{\
124 return X##_ptr_dict_init_with_allocator(dict, n_buckets, NULL);\
125}\
126\
127int X##_ptr_dict_init_with_allocator(X##_ptr_dict *dict, size_t n_buckets, kest_allocator *alloc)\
128{\
129 if (!dict) return ERR_NULL_PTR;\
130 if (n_buckets == 0)\
131 {\
132 dict->buckets = NULL;\
133 dict->n_buckets = 0;\
134 dict->alloc = alloc ? *alloc : (kest_allocator){0};\
135 return NO_ERROR;\
136 }\
137 \
138 dict->n_buckets = 0;\
139 dict->buckets = kest_allocator_alloc(alloc, sizeof(X##_ptr_dict_bucket) * n_buckets);\
140 \
141 if (!dict->buckets)\
142 return ERR_ALLOC_FAIL;\
143 \
144 for (size_t i = 0; i < n_buckets; i++)\
145 X##_ptr_dict_entry_list_init_with_allocator(&dict->buckets[i], alloc);\
146 \
147 dict->n_buckets = n_buckets;\
148 dict->alloc = alloc ? *alloc : (kest_allocator){0};\
149 \
150 return NO_ERROR;\
151}\
152\
153int X##_ptr_dict_entry_cmp(const X##_ptr_dict_entry *a, const X##_ptr_dict_entry *b)\
154{\
155 if (!a || !b) return -1;\
156 if (!a->key || !b->key) return -1;\
157 return strcmp(a->key, b->key);\
158}\
159\
160int X##_ptr_dict_insert(X##_ptr_dict *dict, char *key, X *x)\
161{\
162 if (!dict) return ERR_NULL_PTR;\
163 if (!key) return ERR_BAD_ARGS;\
164 if (!dict->n_buckets) return ERR_BAD_ARGS;\
165 \
166 size_t bucket = hash(key) % dict->n_buckets;\
167 \
168 X##_ptr_dict_entry entry = {.key = key, .data = x};\
169 \
170 int index = X##_ptr_dict_entry_list_index_of(&dict->buckets[bucket], entry, X##_ptr_dict_entry_cmp);\
171 \
172 if (index >= 0)\
173 return ERR_DUPLICATE_KEY;\
174 \
175 entry.key = kest_allocator_strndup(&dict->alloc, key, 1024);\
176 \
177 if (!entry.key)\
178 return ERR_ALLOC_FAIL;\
179 \
180 return X##_ptr_dict_entry_list_append(&dict->buckets[bucket], entry);\
181}\
182X *X##_ptr_dict_lookup(X##_ptr_dict *dict, const char *key)\
183{\
184 if (!dict || !key) return NULL;\
185 if (!dict->n_buckets) return NULL;\
186 \
187 X##_ptr_dict_entry entry = {.key = key, .data = NULL};\
188 \
189 size_t bucket = hash(key) % dict->n_buckets;\
190 \
191 int index = X##_ptr_dict_entry_list_index_of(&dict->buckets[bucket], entry, X##_ptr_dict_entry_cmp);\
192 \
193 if (index >= 0 && index < dict->buckets[bucket].count)\
194 return dict->buckets[bucket].entries[index].data;\
195 \
196 return NULL;\
197}\
198size_t X##_ptr_dict_count(X##_ptr_dict *dict)\
199{\
200 if (!dict) return 0;\
201 \
202 if (!dict->buckets || !dict->n_buckets)\
203 return 0;\
204 \
205 size_t count = 0;\
206 for (size_t i = 0; i < dict->n_buckets; i++)\
207 {\
208 count += dict->buckets[i].count;\
209 }\
210 \
211 return count;\
212}\
213X *X##_ptr_dict_index(X##_ptr_dict *dict, size_t n)\
214{\
215 if (!dict) return NULL;\
216 \
217 if (!dict->buckets || !dict->n_buckets)\
218 return NULL;\
219 \
220 for (size_t i = 0; i < dict->n_buckets; i++)\
221 {\
222 if (dict->buckets[i].count > n)\
223 return dict->buckets[i].entries[n].data;\
224 else\
225 n -= dict->buckets[i].count;\
226 }\
227 \
228 return NULL;\
229}\
230void X##_ptr_dict_destroy(X##_ptr_dict *dict, void (*destructor)(X *x))\
231{\
232 if (!dict)\
233 return;\
234 \
235 if (dict->buckets)\
236 {\
237 for (size_t i = 0; i < dict->n_buckets; i++)\
238 {\
239 for (size_t j = 0; j < dict->buckets[i].count; j++) \
240 {\
241 if (destructor)\
242 destructor(dict->buckets[i].entries[j].data); \
243 kest_allocator_free(&dict->alloc, dict->buckets[i].entries[j].key);\
244 }\
245 \
246 kest_allocator_free(&dict->buckets[i].alloc, dict->buckets[i].entries); \
247 \
248 dict->buckets[i].entries = NULL; \
249 dict->buckets[i].count = 0; \
250 dict->buckets[i].capacity = 0; \
251 \
252 }\
253 \
254 kest_allocator_free(&dict->alloc, dict->buckets);\
255 dict->buckets = NULL;\
256 }\
257 \
258 dict->n_buckets = 0;\
259}
260
261#endif
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)
#define DECLARE_LIST(X)
Definition kest_list.h:4
char_list kest_string
Definition kest_string.h:6
kest_dictionary_entry * entries
int line
const char * name
struct kest_dictionary * val_dict
struct kest_dictionary_entry_list * val_list
int type
int val_int
float val_float
kest_expression * val_expr
const char * val_string
kest_dictionary_entry * entries
kest_dictionary_bucket buckets[KEST_DICTIONARY_N_BUCKETS]
const char * name
kest_effect_desc * result