16#ifndef CCC_PRIVATE_TREE_MAP_H
17#define CCC_PRIVATE_TREE_MAP_H
25#include "private_types.h"
102void *CCC_private_tree_map_key_in_slot(
struct CCC_Tree_map const *,
106CCC_private_tree_map_node_in_slot(
struct CCC_Tree_map const *,
110CCC_private_tree_map_entry(struct
CCC_Tree_map const *,
void const *key);
112void *CCC_private_tree_map_insert(
119#define CCC_private_tree_map_initialize( \
120 private_struct_name, private_node_node_field, private_key_node_field, \
121 private_key_order_fn, private_allocate, private_context_data) \
125 .key_offset = offsetof(private_struct_name, private_key_node_field), \
126 .type_intruder_offset \
127 = offsetof(private_struct_name, private_node_node_field), \
128 .sizeof_type = sizeof(private_struct_name), \
129 .compare = (private_key_order_fn), \
130 .allocate = (private_allocate), \
131 .context = (private_context_data), \
135#define CCC_private_tree_map_from( \
136 private_type_intruder_field_name, private_key_field_name, private_compare, \
137 private_allocate, private_destroy, private_context_data, \
138 private_compound_literal_array...) \
140 typeof(*private_compound_literal_array) *private_tree_map_type_array \
141 = private_compound_literal_array; \
142 struct CCC_Tree_map private_map = CCC_private_tree_map_initialize( \
143 typeof(*private_tree_map_type_array), \
144 private_type_intruder_field_name, private_key_field_name, \
145 private_compare, private_allocate, private_context_data); \
146 if (private_map.allocate) \
148 size_t const private_count \
149 = sizeof(private_compound_literal_array) \
150 / sizeof(*private_tree_map_type_array); \
151 for (size_t private_i = 0; private_i < private_count; ++private_i) \
153 struct CCC_Tree_map_entry private_tree_map_entry \
154 = CCC_private_tree_map_entry( \
156 (void *)&private_tree_map_type_array[private_i] \
157 .private_key_field_name); \
158 if (!(private_tree_map_entry.entry.status \
159 & CCC_ENTRY_OCCUPIED)) \
161 typeof(*private_tree_map_type_array) *const \
163 = private_map.allocate((CCC_Allocator_context){ \
165 .bytes = private_map.sizeof_type, \
166 .context = private_map.context, \
168 if (!private_new_slot) \
170 (void)CCC_tree_map_clear(&private_map, \
175 = private_tree_map_type_array[private_i]; \
176 CCC_private_tree_map_insert( \
178 CCC_private_tree_map_node_in_slot( \
179 &private_map, private_tree_map_entry.entry.type), \
180 private_tree_map_entry.last_order, \
181 CCC_private_tree_map_node_in_slot(&private_map, \
182 private_new_slot)); \
186 struct CCC_Tree_map_node private_node_saved \
187 = *CCC_private_tree_map_node_in_slot( \
188 &private_map, private_tree_map_entry.entry.type); \
189 *((typeof(*private_tree_map_type_array) *) \
190 private_tree_map_entry.entry.type) \
191 = private_tree_map_type_array[private_i]; \
192 *CCC_private_tree_map_node_in_slot( \
193 &private_map, private_tree_map_entry.entry.type) \
194 = private_node_saved; \
204#define CCC_private_tree_map_new(Tree_map_entry) \
206 void *private_tree_map_ins_allocate_ret = NULL; \
207 if ((Tree_map_entry)->map->allocate) \
209 private_tree_map_ins_allocate_ret \
211 ->map->allocate((CCC_Allocator_context){ \
213 .bytes = (Tree_map_entry)->map->sizeof_type, \
214 .context = (Tree_map_entry)->map->context, \
217 private_tree_map_ins_allocate_ret; \
221#define CCC_private_tree_map_insert_key_val(Tree_map_entry, new_data, \
222 type_compound_literal...) \
226 *new_data = type_compound_literal; \
227 new_data = CCC_private_tree_map_insert( \
228 (Tree_map_entry)->map, \
229 CCC_private_tree_map_node_in_slot( \
230 (Tree_map_entry)->map, (Tree_map_entry)->entry.type), \
231 (Tree_map_entry)->last_order, \
232 CCC_private_tree_map_node_in_slot((Tree_map_entry)->map, \
238#define CCC_private_tree_map_insert_and_copy_key( \
239 tree_map_insert_entry, tree_map_insert_entry_ret, key, \
240 type_compound_literal...) \
242 typeof(type_compound_literal) *private_tree_map_new_ins_base \
243 = CCC_private_tree_map_new((&tree_map_insert_entry)); \
244 tree_map_insert_entry_ret = (struct CCC_Entry){ \
245 .type = private_tree_map_new_ins_base, \
246 .status = CCC_ENTRY_INSERT_ERROR, \
248 if (private_tree_map_new_ins_base) \
250 *private_tree_map_new_ins_base = type_compound_literal; \
251 *((typeof(key) *)CCC_private_tree_map_key_in_slot( \
252 tree_map_insert_entry.map, private_tree_map_new_ins_base)) \
254 (void)CCC_private_tree_map_insert( \
255 tree_map_insert_entry.map, \
256 CCC_private_tree_map_node_in_slot( \
257 tree_map_insert_entry.map, \
258 tree_map_insert_entry.entry.type), \
259 tree_map_insert_entry.last_order, \
260 CCC_private_tree_map_node_in_slot( \
261 tree_map_insert_entry.map, \
262 private_tree_map_new_ins_base)); \
269#define CCC_private_tree_map_and_modify_with(Tree_map_entry_pointer, \
270 type_name, closure_over_T...) \
272 __auto_type private_tree_map_ent_pointer = (Tree_map_entry_pointer); \
273 struct CCC_Tree_map_entry private_tree_map_mod_ent \
274 = {.entry = {.status = CCC_ENTRY_ARGUMENT_ERROR}}; \
275 if (private_tree_map_ent_pointer) \
277 private_tree_map_mod_ent = private_tree_map_ent_pointer->private; \
278 if (private_tree_map_mod_ent.entry.status & CCC_ENTRY_OCCUPIED) \
280 type_name *const T = private_tree_map_mod_ent.entry.type; \
287 private_tree_map_mod_ent; \
291#define CCC_private_tree_map_or_insert_with(Tree_map_entry_pointer, \
292 type_compound_literal...) \
294 __auto_type private_or_ins_entry_pointer = (Tree_map_entry_pointer); \
295 typeof(type_compound_literal) *private_tree_map_or_ins_ret = NULL; \
296 if (private_or_ins_entry_pointer) \
298 if (private_or_ins_entry_pointer->private.entry.status \
299 == CCC_ENTRY_OCCUPIED) \
301 private_tree_map_or_ins_ret \
302 = private_or_ins_entry_pointer->private.entry.type; \
306 private_tree_map_or_ins_ret = CCC_private_tree_map_new( \
307 &private_or_ins_entry_pointer->private); \
308 CCC_private_tree_map_insert_key_val( \
309 &private_or_ins_entry_pointer->private, \
310 private_tree_map_or_ins_ret, type_compound_literal); \
313 private_tree_map_or_ins_ret; \
317#define CCC_private_tree_map_insert_entry_with(Tree_map_entry_pointer, \
318 type_compound_literal...) \
320 __auto_type private_ins_entry_pointer = (Tree_map_entry_pointer); \
321 typeof(type_compound_literal) *private_tree_map_ins_ent_ret = NULL; \
322 if (private_ins_entry_pointer) \
324 if (!(private_ins_entry_pointer->private.entry.status \
325 & CCC_ENTRY_OCCUPIED)) \
327 private_tree_map_ins_ent_ret = CCC_private_tree_map_new( \
328 &private_ins_entry_pointer->private); \
329 CCC_private_tree_map_insert_key_val( \
330 &private_ins_entry_pointer->private, \
331 private_tree_map_ins_ent_ret, type_compound_literal); \
333 else if (private_ins_entry_pointer->private.entry.status \
334 == CCC_ENTRY_OCCUPIED) \
336 struct CCC_Tree_map_node private_ins_ent_saved \
337 = *CCC_private_tree_map_node_in_slot( \
338 private_ins_entry_pointer->private.map, \
339 private_ins_entry_pointer->private.entry.type); \
340 *((typeof(private_tree_map_ins_ent_ret)) \
341 private_ins_entry_pointer->private.entry.type) \
342 = type_compound_literal; \
343 *CCC_private_tree_map_node_in_slot( \
344 private_ins_entry_pointer->private.map, \
345 private_ins_entry_pointer->private.entry.type) \
346 = private_ins_ent_saved; \
347 private_tree_map_ins_ent_ret \
348 = private_ins_entry_pointer->private.entry.type; \
351 private_tree_map_ins_ent_ret; \
355#define CCC_private_tree_map_try_insert_with(Tree_map_pointer, key, \
356 type_compound_literal...) \
358 struct CCC_Tree_map *const private_try_ins_map_pointer \
359 = (Tree_map_pointer); \
360 struct CCC_Entry private_tree_map_try_ins_ent_ret \
361 = {.status = CCC_ENTRY_ARGUMENT_ERROR}; \
362 if (private_try_ins_map_pointer) \
364 __auto_type private_tree_map_key = (key); \
365 struct CCC_Tree_map_entry private_tree_map_try_ins_ent \
366 = CCC_private_tree_map_entry(private_try_ins_map_pointer, \
367 (void *)&private_tree_map_key); \
368 if (!(private_tree_map_try_ins_ent.entry.status \
369 & CCC_ENTRY_OCCUPIED)) \
371 CCC_private_tree_map_insert_and_copy_key( \
372 private_tree_map_try_ins_ent, \
373 private_tree_map_try_ins_ent_ret, private_tree_map_key, \
374 type_compound_literal); \
376 else if (private_tree_map_try_ins_ent.entry.status \
377 == CCC_ENTRY_OCCUPIED) \
379 private_tree_map_try_ins_ent_ret \
380 = private_tree_map_try_ins_ent.entry; \
383 private_tree_map_try_ins_ent_ret; \
387#define CCC_private_tree_map_insert_or_assign_with(Tree_map_pointer, key, \
388 type_compound_literal...) \
390 struct CCC_Tree_map *const private_ins_or_assign_map_pointer \
391 = (Tree_map_pointer); \
392 struct CCC_Entry private_tree_map_ins_or_assign_ent_ret \
393 = {.status = CCC_ENTRY_ARGUMENT_ERROR}; \
394 if (private_ins_or_assign_map_pointer) \
396 __auto_type private_tree_map_key = (key); \
397 struct CCC_Tree_map_entry private_tree_map_ins_or_assign_ent \
398 = CCC_private_tree_map_entry( \
399 private_ins_or_assign_map_pointer, \
400 (void *)&private_tree_map_key); \
401 if (!(private_tree_map_ins_or_assign_ent.entry.status \
402 & CCC_ENTRY_OCCUPIED)) \
404 CCC_private_tree_map_insert_and_copy_key( \
405 private_tree_map_ins_or_assign_ent, \
406 private_tree_map_ins_or_assign_ent_ret, \
407 private_tree_map_key, type_compound_literal); \
409 else if (private_tree_map_ins_or_assign_ent.entry.status \
410 == CCC_ENTRY_OCCUPIED) \
412 struct CCC_Tree_map_node private_ins_ent_saved \
413 = *CCC_private_tree_map_node_in_slot( \
414 private_tree_map_ins_or_assign_ent.map, \
415 private_tree_map_ins_or_assign_ent.entry.type); \
416 *((typeof(type_compound_literal) *) \
417 private_tree_map_ins_or_assign_ent.entry.type) \
418 = type_compound_literal; \
419 *CCC_private_tree_map_node_in_slot( \
420 private_tree_map_ins_or_assign_ent.map, \
421 private_tree_map_ins_or_assign_ent.entry.type) \
422 = private_ins_ent_saved; \
423 private_tree_map_ins_or_assign_ent_ret \
424 = private_tree_map_ins_or_assign_ent.entry; \
425 *((typeof(private_tree_map_key) *) \
426 CCC_private_tree_map_key_in_slot( \
427 private_tree_map_ins_or_assign_ent.map, \
428 private_tree_map_ins_or_assign_ent_ret.type)) \
429 = private_tree_map_key; \
432 private_tree_map_ins_or_assign_ent_ret; \
Definition: private_types.h:53
Definition: private_tree_map.h:78
struct CCC_Entry entry
Definition: private_tree_map.h:86
CCC_Order last_order
Definition: private_tree_map.h:84
struct CCC_Tree_map * map
Definition: private_tree_map.h:80
Definition: private_tree_map.h:32
uint8_t parity
Definition: private_tree_map.h:38
struct CCC_Tree_map_node * branch[2]
Definition: private_tree_map.h:34
struct CCC_Tree_map_node * parent
Definition: private_tree_map.h:36
Definition: private_tree_map.h:54
void * context
Definition: private_tree_map.h:71
size_t count
Definition: private_tree_map.h:58
struct CCC_Tree_map_node * root
Definition: private_tree_map.h:56
CCC_Allocator * allocate
Definition: private_tree_map.h:69
size_t sizeof_type
Definition: private_tree_map.h:65
size_t key_offset
Definition: private_tree_map.h:60
size_t type_intruder_offset
Definition: private_tree_map.h:63
CCC_Key_comparator * compare
Definition: private_tree_map.h:67
CCC_Order
A three-way comparison for comparison functions.
Definition: types.h:171
CCC_Order CCC_Key_comparator(CCC_Key_comparator_context)
A callback function for three-way comparing two stored keys.
Definition: types.h:383
void * CCC_Allocator(CCC_Allocator_context)
An allocation function at the core of all containers.
Definition: types.h:340
Definition: private_tree_map.h:94
struct CCC_Tree_map_entry private
Definition: private_tree_map.h:96