1#ifndef CCC_IMPL_ORDERED_MULTIMAP_H
2#define CCC_IMPL_ORDERED_MULTIMAP_H
28typedef struct ccc_ommap_elem_
32 struct ccc_ommap_elem_ *branch_[2];
33 struct ccc_ommap_elem_ *link_[2];
37 struct ccc_ommap_elem_ *parent_;
38 struct ccc_ommap_elem_ *dup_head_;
45 struct ccc_ommap_elem_ *root_;
46 struct ccc_ommap_elem_ end_;
52 size_t node_elem_offset_;
57struct ccc_omultimap_entry_
59 struct ccc_ommap_ *t_;
60 struct ccc_ent_ entry_;
66 struct ccc_omultimap_entry_ impl_;
72void *ccc_impl_omm_key_in_slot(
struct ccc_ommap_
const *t,
void const *slot);
74ccc_ommap_elem_ *ccc_impl_ommap_elem_in_slot(
struct ccc_ommap_
const *t,
77struct ccc_omultimap_entry_ ccc_impl_omm_entry(struct ccc_ommap_ *t,
80void *ccc_impl_omm_multimap_insert(
struct ccc_ommap_ *t, ccc_ommap_elem_ *n);
85#define ccc_impl_omm_init(tree_name, struct_name, node_elem_field, \
86 key_elem_field, key_cmp_fn, alloc_fn, aux_data) \
88 .root_ = &(tree_name).end_, \
89 .end_ = {{.branch_ = {&(tree_name).end_, &(tree_name).end_}}, \
90 {.parent_ = &(tree_name).end_}}, \
91 .alloc_ = (alloc_fn), \
92 .cmp_ = (key_cmp_fn), \
95 .elem_sz_ = sizeof(struct_name), \
96 .node_elem_offset_ = offsetof(struct_name, node_elem_field), \
97 .key_offset_ = offsetof(struct_name, key_elem_field), \
103#define ccc_impl_omm_new(ordered_map_entry) \
105 void *omm_ins_alloc_ret_ = NULL; \
106 if ((ordered_map_entry)->t_->alloc_) \
109 = (ordered_map_entry) \
110 ->t_->alloc_(NULL, (ordered_map_entry)->t_->elem_sz_, \
111 (ordered_map_entry)->t_->aux_); \
113 omm_ins_alloc_ret_; \
117#define ccc_impl_omm_insert_key_val(ordered_map_entry, new_mem, \
122 *new_mem = lazy_key_value; \
123 new_mem = ccc_impl_omm_multimap_insert( \
124 (ordered_map_entry)->t_, \
125 ccc_impl_ommap_elem_in_slot((ordered_map_entry)->t_, \
131#define ccc_impl_omm_insert_and_copy_key( \
132 omm_insert_entry, omm_insert_entry_ret, key, lazy_value...) \
134 typeof(lazy_value) *omm_new_ins_base_ \
135 = ccc_impl_omm_new((&omm_insert_entry)); \
136 omm_insert_entry_ret = (struct ccc_ent_){ \
137 .e_ = omm_new_ins_base_, \
138 .stats_ = CCC_ENTRY_INSERT_ERROR, \
140 if (omm_new_ins_base_) \
142 *((typeof(lazy_value) *)omm_new_ins_base_) = lazy_value; \
143 *((typeof(key) *)ccc_impl_omm_key_in_slot(omm_insert_entry.t_, \
144 omm_new_ins_base_)) \
146 (void)ccc_impl_omm_multimap_insert( \
147 omm_insert_entry.t_, \
148 ccc_impl_ommap_elem_in_slot(omm_insert_entry.t_, \
149 omm_new_ins_base_)); \
156#define ccc_impl_omm_and_modify_w(ordered_map_entry_ptr, type_name, \
159 __auto_type omm_ent_ptr_ = (ordered_map_entry_ptr); \
160 struct ccc_omultimap_entry_ omm_mod_ent_ \
161 = {.entry_ = {.stats_ = CCC_ENTRY_ARG_ERROR}}; \
164 omm_mod_ent_ = omm_ent_ptr_->impl_; \
165 if (omm_mod_ent_.entry_.stats_ & CCC_ENTRY_OCCUPIED) \
167 type_name *const T = omm_mod_ent_.entry_.e_; \
178#define ccc_impl_omm_or_insert_w(ordered_map_entry_ptr, lazy_key_value...) \
180 __auto_type omm_or_ins_ent_ptr_ = (ordered_map_entry_ptr); \
181 typeof(lazy_key_value) *or_ins_ret_ = NULL; \
182 if (omm_or_ins_ent_ptr_) \
184 struct ccc_omultimap_entry_ *omm_or_ins_ent_ \
185 = &omm_or_ins_ent_ptr_->impl_; \
186 if (omm_or_ins_ent_->entry_.stats_ == CCC_ENTRY_OCCUPIED) \
188 or_ins_ret_ = omm_or_ins_ent_->entry_.e_; \
192 or_ins_ret_ = ccc_impl_omm_new(omm_or_ins_ent_); \
193 ccc_impl_omm_insert_key_val(omm_or_ins_ent_, or_ins_ret_, \
201#define ccc_impl_omm_insert_entry_w(ordered_map_entry_ptr, lazy_key_value...) \
203 __auto_type omm_ins_ent_ptr_ = (ordered_map_entry_ptr); \
204 typeof(lazy_key_value) *omm_ins_ent_ret_ = NULL; \
205 if (omm_ins_ent_ptr_) \
207 struct ccc_omultimap_entry_ *omm_ins_ent_ \
208 = &omm_ins_ent_ptr_->impl_; \
209 omm_ins_ent_ret_ = ccc_impl_omm_new(omm_ins_ent_); \
210 ccc_impl_omm_insert_key_val(omm_ins_ent_, omm_ins_ent_ret_, \
217#define ccc_impl_omm_try_insert_w(ordered_map_ptr, key, lazy_value...) \
219 __auto_type omm_try_ins_ptr_ = (ordered_map_ptr); \
220 struct ccc_ent_ omm_try_ins_ent_ret_ \
221 = {.stats_ = CCC_ENTRY_ARG_ERROR}; \
222 if (omm_try_ins_ptr_) \
224 __auto_type omm_key_ = (key); \
225 struct ccc_omultimap_entry_ omm_try_ins_ent_ \
226 = ccc_impl_omm_entry(omm_try_ins_ptr_, (void *)&omm_key_); \
227 if (!(omm_try_ins_ent_.entry_.stats_ & CCC_ENTRY_OCCUPIED)) \
229 ccc_impl_omm_insert_and_copy_key(omm_try_ins_ent_, \
230 omm_try_ins_ent_ret_, \
231 omm_key_, lazy_value); \
233 else if (omm_try_ins_ent_.entry_.stats_ == CCC_ENTRY_OCCUPIED) \
235 omm_try_ins_ent_ret_ = omm_try_ins_ent_.entry_; \
238 omm_try_ins_ent_ret_; \
242#define ccc_impl_omm_insert_or_assign_w(ordered_map_ptr, key, lazy_value...) \
244 __auto_type omm_ins_or_assign_ptr_ = (ordered_map_ptr); \
245 struct ccc_ent_ omm_ins_or_assign_ent_ret_ \
246 = {.stats_ = CCC_ENTRY_ARG_ERROR}; \
247 if (omm_ins_or_assign_ptr_) \
249 __auto_type omm_key_ = (key); \
250 struct ccc_omultimap_entry_ omm_ins_or_assign_ent_ \
251 = ccc_impl_omm_entry(omm_ins_or_assign_ptr_, \
252 (void *)&omm_key_); \
253 if (!(omm_ins_or_assign_ent_.entry_.stats_ & CCC_ENTRY_OCCUPIED)) \
255 ccc_impl_omm_insert_and_copy_key(omm_ins_or_assign_ent_, \
256 omm_ins_or_assign_ent_ret_, \
257 omm_key_, lazy_value); \
259 else if (omm_ins_or_assign_ent_.entry_.stats_ \
260 == CCC_ENTRY_OCCUPIED) \
262 struct ccc_ommap_elem_ ins_ent_saved_ \
263 = *ccc_impl_ommap_elem_in_slot( \
264 omm_ins_or_assign_ent_.t_, \
265 omm_ins_or_assign_ent_.entry_.e_); \
266 *((typeof(lazy_value) *)omm_ins_or_assign_ent_.entry_.e_) \
268 *ccc_impl_ommap_elem_in_slot(omm_ins_or_assign_ent_.t_, \
269 omm_ins_or_assign_ent_.entry_.e_) \
271 omm_ins_or_assign_ent_ret_ = omm_ins_or_assign_ent_.entry_; \
272 *((typeof(omm_key_) *)ccc_impl_omm_key_in_slot( \
273 omm_ins_or_assign_ptr_, omm_ins_or_assign_ent_ret_.e_)) \
277 omm_ins_or_assign_ent_ret_; \
ccc_threeway_cmp ccc_key_cmp_fn(ccc_key_cmp)
A callback function for three-way comparing two stored keys.
Definition: types.h:333
void * ccc_alloc_fn(void *ptr, size_t size, void *aux)
An allocation function at the core of all containers.
Definition: types.h:283