16#ifndef CCC_IMPL_HANDLE_ORDERED_MAP_H
17#define CCC_IMPL_HANDLE_ORDERED_MAP_H
24#include "impl_types.h"
74 struct ccc_homap_elem *nodes;
97struct ccc_htree_handle
100 struct ccc_homap *hom;
106 ccc_entry_status stats;
115 struct ccc_htree_handle impl;
121void ccc_impl_hom_insert(
struct ccc_homap *hom,
size_t elem_i);
123struct ccc_htree_handle ccc_impl_hom_handle(struct ccc_homap *hom,
126void *ccc_impl_hom_data_at(
struct ccc_homap
const *hom,
size_t slot);
128void *ccc_impl_hom_key_at(
struct ccc_homap
const *hom,
size_t slot);
130size_t ccc_impl_hom_alloc_slot(
struct ccc_homap *hom);
136#define ccc_impl_hom_declare_fixed_map(impl_fixed_map_type_name, \
137 impl_key_val_type_name, impl_capacity) \
138 static_assert((impl_capacity) > 1, \
139 "fixed size map must have capacity greater than 1"); \
142 impl_key_val_type_name data[(impl_capacity)]; \
143 struct ccc_homap_elem nodes[(impl_capacity)]; \
144 }(impl_fixed_map_type_name)
148#define ccc_impl_hom_fixed_capacity(fixed_map_type_name) \
149 (sizeof((fixed_map_type_name){}.nodes) / sizeof(struct ccc_homap_elem))
152#define ccc_impl_hom_init(impl_memory_ptr, impl_type_name, \
153 impl_key_elem_field, impl_key_cmp_fn, impl_alloc_fn, \
154 impl_aux_data, impl_capacity) \
156 .data = (impl_memory_ptr), \
158 .capacity = (impl_capacity), \
162 .sizeof_type = sizeof(impl_type_name), \
163 .key_offset = offsetof(impl_type_name, impl_key_elem_field), \
164 .cmp = (impl_key_cmp_fn), \
165 .alloc = (impl_alloc_fn), \
166 .aux = (impl_aux_data), \
170#define ccc_impl_hom_as(handle_ordered_map_ptr, type_name, handle...) \
171 ((type_name *)ccc_impl_hom_data_at((handle_ordered_map_ptr), (handle)))
176#define ccc_impl_hom_and_modify_w(handle_ordered_map_handle_ptr, type_name, \
179 __auto_type impl_hom_mod_hndl_ptr = (handle_ordered_map_handle_ptr); \
180 struct ccc_htree_handle impl_hom_mod_hndl \
181 = {.stats = CCC_ENTRY_ARG_ERROR}; \
182 if (impl_hom_mod_hndl_ptr) \
184 impl_hom_mod_hndl = impl_hom_mod_hndl_ptr->impl; \
185 if (impl_hom_mod_hndl.stats & CCC_ENTRY_OCCUPIED) \
187 type_name *const T = ccc_impl_hom_data_at( \
188 impl_hom_mod_hndl.hom, impl_hom_mod_hndl.i); \
199#define ccc_impl_hom_or_insert_w(handle_ordered_map_handle_ptr, \
202 __auto_type impl_hom_or_ins_hndl_ptr \
203 = (handle_ordered_map_handle_ptr); \
204 ccc_handle_i impl_hom_or_ins_ret = 0; \
205 if (impl_hom_or_ins_hndl_ptr) \
207 if (impl_hom_or_ins_hndl_ptr->impl.stats == CCC_ENTRY_OCCUPIED) \
209 impl_hom_or_ins_ret = impl_hom_or_ins_hndl_ptr->impl.i; \
213 impl_hom_or_ins_ret = ccc_impl_hom_alloc_slot( \
214 impl_hom_or_ins_hndl_ptr->impl.hom); \
215 if (impl_hom_or_ins_ret) \
217 *((typeof(lazy_key_value) *)ccc_impl_hom_data_at( \
218 impl_hom_or_ins_hndl_ptr->impl.hom, \
219 impl_hom_or_ins_ret)) \
221 ccc_impl_hom_insert(impl_hom_or_ins_hndl_ptr->impl.hom, \
222 impl_hom_or_ins_ret); \
226 impl_hom_or_ins_ret; \
230#define ccc_impl_hom_insert_handle_w(handle_ordered_map_handle_ptr, \
233 __auto_type impl_hom_ins_hndl_ptr = (handle_ordered_map_handle_ptr); \
234 ccc_handle_i impl_hom_ins_hndl_ret = 0; \
235 if (impl_hom_ins_hndl_ptr) \
237 if (!(impl_hom_ins_hndl_ptr->impl.stats & CCC_ENTRY_OCCUPIED)) \
239 impl_hom_ins_hndl_ret = ccc_impl_hom_alloc_slot( \
240 impl_hom_ins_hndl_ptr->impl.hom); \
241 if (impl_hom_ins_hndl_ret) \
243 *((typeof(lazy_key_value) *)ccc_impl_hom_data_at( \
244 impl_hom_ins_hndl_ptr->impl.hom, \
245 impl_hom_ins_hndl_ret)) \
247 ccc_impl_hom_insert(impl_hom_ins_hndl_ptr->impl.hom, \
248 impl_hom_ins_hndl_ret); \
251 else if (impl_hom_ins_hndl_ptr->impl.stats == CCC_ENTRY_OCCUPIED) \
253 *((typeof(lazy_key_value) *)ccc_impl_hom_data_at( \
254 impl_hom_ins_hndl_ptr->impl.hom, \
255 impl_hom_ins_hndl_ptr->impl.i)) \
257 impl_hom_ins_hndl_ret = impl_hom_ins_hndl_ptr->impl.i; \
260 impl_hom_ins_hndl_ret; \
264#define ccc_impl_hom_try_insert_w(handle_ordered_map_ptr, key, lazy_value...) \
266 __auto_type impl_hom_try_ins_map_ptr = (handle_ordered_map_ptr); \
267 struct ccc_handl impl_hom_try_ins_hndl_ret \
268 = {.stats = CCC_ENTRY_ARG_ERROR}; \
269 if (impl_hom_try_ins_map_ptr) \
271 __auto_type impl_hom_key = (key); \
272 struct ccc_htree_handle impl_hom_try_ins_hndl \
273 = ccc_impl_hom_handle(impl_hom_try_ins_map_ptr, \
274 (void *)&impl_hom_key); \
275 if (!(impl_hom_try_ins_hndl.stats & CCC_ENTRY_OCCUPIED)) \
277 impl_hom_try_ins_hndl_ret = (struct ccc_handl){ \
278 .i = ccc_impl_hom_alloc_slot(impl_hom_try_ins_hndl.hom), \
279 .stats = CCC_ENTRY_INSERT_ERROR, \
281 if (impl_hom_try_ins_hndl_ret.i) \
283 *((typeof(lazy_value) *)ccc_impl_hom_data_at( \
284 impl_hom_try_ins_map_ptr, \
285 impl_hom_try_ins_hndl_ret.i)) \
287 *((typeof(impl_hom_key) *)ccc_impl_hom_key_at( \
288 impl_hom_try_ins_hndl.hom, \
289 impl_hom_try_ins_hndl_ret.i)) \
291 ccc_impl_hom_insert(impl_hom_try_ins_hndl.hom, \
292 impl_hom_try_ins_hndl_ret.i); \
293 impl_hom_try_ins_hndl_ret.stats = CCC_ENTRY_VACANT; \
296 else if (impl_hom_try_ins_hndl.stats == CCC_ENTRY_OCCUPIED) \
298 impl_hom_try_ins_hndl_ret = (struct ccc_handl){ \
299 .i = impl_hom_try_ins_hndl.i, \
300 .stats = impl_hom_try_ins_hndl.stats}; \
303 impl_hom_try_ins_hndl_ret; \
307#define ccc_impl_hom_insert_or_assign_w(handle_ordered_map_ptr, key, \
310 __auto_type impl_hom_ins_or_assign_map_ptr = (handle_ordered_map_ptr); \
311 struct ccc_handl impl_hom_ins_or_assign_hndl_ret \
312 = {.stats = CCC_ENTRY_ARG_ERROR}; \
313 if (impl_hom_ins_or_assign_map_ptr) \
315 __auto_type impl_hom_key = (key); \
316 struct ccc_htree_handle impl_hom_ins_or_assign_hndl \
317 = ccc_impl_hom_handle(impl_hom_ins_or_assign_map_ptr, \
318 (void *)&impl_hom_key); \
319 if (!(impl_hom_ins_or_assign_hndl.stats & CCC_ENTRY_OCCUPIED)) \
321 impl_hom_ins_or_assign_hndl_ret = (struct ccc_handl){ \
322 .i = ccc_impl_hom_alloc_slot( \
323 impl_hom_ins_or_assign_hndl.hom), \
324 .stats = CCC_ENTRY_INSERT_ERROR, \
326 if (impl_hom_ins_or_assign_hndl_ret.i) \
328 *((typeof(lazy_value) *)ccc_impl_hom_data_at( \
329 impl_hom_ins_or_assign_map_ptr, \
330 impl_hom_ins_or_assign_hndl_ret.i)) \
332 *((typeof(impl_hom_key) *)ccc_impl_hom_key_at( \
333 impl_hom_ins_or_assign_hndl.hom, \
334 impl_hom_ins_or_assign_hndl_ret.i)) \
336 ccc_impl_hom_insert(impl_hom_ins_or_assign_hndl.hom, \
337 impl_hom_ins_or_assign_hndl_ret.i); \
338 impl_hom_ins_or_assign_hndl_ret.stats = CCC_ENTRY_VACANT; \
341 else if (impl_hom_ins_or_assign_hndl.stats == CCC_ENTRY_OCCUPIED) \
343 *((typeof(lazy_value) *)ccc_impl_hom_data_at( \
344 impl_hom_ins_or_assign_hndl.hom, \
345 impl_hom_ins_or_assign_hndl.i)) \
347 impl_hom_ins_or_assign_hndl_ret = (struct ccc_handl){ \
348 .i = impl_hom_ins_or_assign_hndl.i, \
349 .stats = impl_hom_ins_or_assign_hndl.stats, \
351 *((typeof(impl_hom_key) *)ccc_impl_hom_key_at( \
352 impl_hom_ins_or_assign_hndl.hom, \
353 impl_hom_ins_or_assign_hndl.i)) \
357 impl_hom_ins_or_assign_hndl_ret; \
union ccc_homap_handle ccc_homap_handle
A container specific handle used to implement the Handle Interface.
Definition: handle_ordered_map.h:73
void * ccc_any_alloc_fn(void *ptr, size_t size, void *aux)
An allocation function at the core of all containers.
Definition: types.h:312
ccc_threeway_cmp ccc_any_key_cmp_fn(ccc_any_key_cmp)
A callback function for three-way comparing two stored keys.
Definition: types.h:362
ccc_threeway_cmp
A three-way comparison for comparison functions.
Definition: types.h:153