data_structures_rmolinari 0.4.4 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
data/ext/cc.h ADDED
@@ -0,0 +1,3879 @@
1
+ /*----------------------------------------- CC: CONVENIENT CONTAINERS v1.0.1 -------------------------------------------
2
+
3
+ This library provides usability-oriented generic containers (vectors, linked lists, unordered maps, and unordered sets).
4
+
5
+ Features:
6
+
7
+ - Fully generic API (no need to specify element or key type except when first declaring a container).
8
+ - No need to pre-declare container types per element or key/element pair.
9
+ - Type safety.
10
+ - User-defined destructor, comparison, and hash functions associated with element and key types.
11
+ - Handles memory allocation failure.
12
+ - Single header.
13
+ - Compiles in C and C++.
14
+
15
+ Requires C23, or C11 and compiler support for __typeof__, or C++11.
16
+
17
+ Tested with GCC, MinGW, and Clang.
18
+
19
+ #including the library:
20
+
21
+ Place this at the top of your file/s:
22
+
23
+ #include "cc.h"
24
+
25
+ The following can be #defined before #including the library in any file:
26
+
27
+ #define CC_NO_SHORT_NAMES
28
+ By default, CC exposes API macros without the "cc_" prefix.
29
+ Define this flag to withhold the unprefixed names.
30
+
31
+ The following can be #defined anywhere and affect all calls to API macros where the definition is visible:
32
+
33
+ #define CC_REALLOC my_realloc
34
+ Causes API macros to use a custom realloc function rather than the one in the standard library.
35
+
36
+ #define CC_FREE my_free
37
+ Causes API macros to use a custom free function rather than the one in the standard library.
38
+
39
+ API:
40
+
41
+ General notes:
42
+
43
+ - API macros may evaluate their first argument - the pointer to the container - multiple times, so never use
44
+ expressions with side effects (e.g. &our_containers[ ++i ] ) for that argument. In GCC and Clang, attempting to do
45
+ so will cause a compiler warning. All other arguments are only evaluated once.
46
+ - If CC_NO_SHORT_NAMES was declared, all API macros are prefixed with "cc_".
47
+ - Duplicating a container handle via assignment and then operating on the duplicate will invalidate the original.
48
+ Hence, only create a duplicate via assignment (including through function parameters and return values) if you have
49
+ finished with the original.
50
+ - An iterator is a pointer to an element in the container or to the associated end (or r_end, if the container
51
+ supports it). In the documentation below, these pointers are called "pointer-iterators".
52
+ - In the documentation below, el_ty is the container's element type and key_ty is the container's key type (where
53
+ applicable).
54
+
55
+ All containers:
56
+
57
+ The following macros behave the same way for all containers:
58
+
59
+ void init( <any container type> *cntr )
60
+
61
+ Initializes cntr for use.
62
+ This call cannot fail (it does not allocate memory).
63
+
64
+ bool init_clone( <any container type> *cntr, <same container type> *src )
65
+
66
+ Initializes cntr as a shallow copy of src.
67
+ Returns true, or false if unsuccessful due to memory allocation failure.
68
+
69
+ size_t size( <any container type> *cntr )
70
+
71
+ Returns the number of elements.
72
+
73
+ void clear( <any container type> *cntr )
74
+
75
+ Erases all elements, calling the element and key types' destructors if they exist.
76
+
77
+ void cleanup( <any container type> *cntr )
78
+
79
+ Erases all elements (calling the element and key types' destructors if they exist), frees any other memory
80
+ associated with the container, and initializes the container for reuse.
81
+
82
+ for_each( <any container type> *cntr, i_name )
83
+
84
+ Creates a loop iterating over all elements from first to last.
85
+ This macro declares a pointer-iterator (el_ty *) named i_name.
86
+ It is equivalent to
87
+ for( el_ty *i_name = first( cntr ); i_name != end( cntr ); i_name = next( cntr, i_name ) )
88
+ and should be followed by the loop body.
89
+
90
+ Vector (a dynamic array that stores elements in contiguous memory):
91
+
92
+ vec( el_ty ) cntr
93
+
94
+ Declares an uninitialized vector named cntr.
95
+
96
+ size_t cap( vec( el_ty ) *cntr )
97
+
98
+ Returns the current capacity.
99
+
100
+ bool reserve( vec( el_ty ) *cntr, size_t n )
101
+
102
+ Ensures that the the capacity is large enough to support n elements.
103
+ Returns true, or false if unsuccessful due to memory allocation failure.
104
+
105
+ bool resize( vec( el_ty ) *cntr, size_t n )
106
+
107
+ Sets the number of elements to n.
108
+ If n is above the current size, the new elements are uninitialized.
109
+ If n is below the current size, the element type's destructor (if it exists) is called for each erased element.
110
+ Returns true, or false if unsuccessful due to memory allocation failure.
111
+
112
+ bool shrink( vec( el_ty ) *cntr )
113
+
114
+ Shrinks the capacity to the current size.
115
+ Returns true, or false if unsuccessful due to memory allocation failure.
116
+
117
+ el_ty *get( vec( el_ty ) *cntr, size_t i )
118
+
119
+ Returns an a pointer-iterator to the element at index i.
120
+
121
+ el_ty *push( vec( el_ty ) *cntr, el_ty el )
122
+
123
+ Inserts el at the end of the vector.
124
+ Returns a pointer-iterator to the new element, or NULL in the case of memory allocation failure.
125
+
126
+ el_ty *push_n( vec( el_ty ) *cntr, el_ty *els, size_t n )
127
+
128
+ Inserts n elements from array els at the end of the vector.
129
+ Returns a pointer-iterator to the first new element, or NULL in the case of memory allocation failure.
130
+
131
+ el_ty *insert( vec( el_ty ) *cntr, size_t i, el_ty el )
132
+
133
+ Inserts el at index i.
134
+ Returns a pointer-iterator to the new element, or NULL in the case of memory allocation failure.
135
+
136
+ el_ty *insert_n( vec( el_ty ) *cntr, size_t i, el_ty *els, size_t n )
137
+
138
+ Inserts n elements from array els at index i.
139
+ Returns a pointer-iterator to the first new element, or NULL in the case of memory allocation failure.
140
+
141
+ el_ty *erase( vec( el_ty ) *cntr, size_t i )
142
+
143
+ Erases the element at index i, calling the element type's destructor if it exists.
144
+ Returns a pointer-iterator to the element after the erased element, or an end pointer-iterator if there
145
+ is no subsequent element.
146
+
147
+ el_ty *erase_n( vec( el_ty ) *cntr, size_t i, size_t n )
148
+
149
+ Erases n elements beginning at index i, calling the element type's destructor, if it exists, for each
150
+ erased element.
151
+ Returns a pointer-iterator to the element after the erased elements, or an end pointer-iterator if there is no
152
+ subsequent element.
153
+
154
+ el_ty *end( vec( el_ty ) *cntr )
155
+
156
+ Returns an end pointer-iterator.
157
+ This call is synonymous with get( cntr, size( cntr ) ).
158
+
159
+ el_ty *first( vec( el_ty ) *cntr )
160
+
161
+ Returns an pointer-iterator to the first element, or an end pointer-iterator if the vector is empty.
162
+ This call is synonymous with get( cntr, 0 ).
163
+
164
+ el_ty *last( vec( el_ty ) *cntr )
165
+
166
+ Returns a pointer-iterator to the last element.
167
+ This call is synonymous with get( cntr, size( cntr ) - 1 ).
168
+ It assumes that at the vector is not empty.
169
+
170
+ el_ty *next( vec( el_ty ) *cntr, el_ty *i )
171
+
172
+ Returns a pointer-iterator to the element after the element pointed to by i, or an end pointer-iterator if i
173
+ points to the last element.
174
+
175
+ Notes:
176
+ - Vector pointer-iterators (including end) are invalidated by any API calls that cause memory reallocation.
177
+
178
+ List (a doubly linked list with sentinels):
179
+
180
+ list( el_ty ) cntr
181
+
182
+ Declares an uninitialized list named cntr.
183
+
184
+ el_ty *insert( list( el_ty ) *cntr, el_ty *i, el_ty el )
185
+
186
+ Inserts el before pointer-iterator i.
187
+ Returns a pointer-iterator to the new element, or NULL in the case of memory allocation failure.
188
+
189
+ el_ty *push( list( el_ty ) *cntr, el_ty el )
190
+
191
+ Inserts el at the end of the list.
192
+ Returns a pointer-iterator to the new element, or NULL in the case of memory allocation failure.
193
+ This call is synonymous with insert( cntr, end( cntr ), el ).
194
+
195
+ el_ty *erase( list( el_ty ) *cntr, el_ty *i )
196
+
197
+ Erases element pointed to by pointer-iterator i, calling the element type's destructor if it exists.
198
+ Returns a pointer-iterator to the element after i, or an end pointer-iterator if i was the last element.
199
+
200
+ bool splice( list( el_ty ) *cntr, el_ty *i, list( el_ty ) src, el_ty *src_i )
201
+
202
+ Removes element pointed to by pointer-iterator src_i from src and inserts it before the element pointed to by
203
+ pointer-iterator i in cntr.
204
+ Returns true, or false if unsuccessful.
205
+ This call only allocates memory, and therefore can only fail, if the list has not had any element inserted,
206
+ pushed, or spliced into it since it was initialized.
207
+
208
+ el_ty *first( list( el_ty ) *cntr )
209
+
210
+ Returns a pointer-iterator to the first element, or an end pointer-iterator if the list is empty.
211
+
212
+ el_ty *last( list( el_ty ) *cntr )
213
+
214
+ Returns a pointer-iterator to the last element, or an r_end pointer-iterator if the list is empty.
215
+
216
+ el_ty *r_end( list( el_ty ) *cntr )
217
+
218
+ Returns an r_end (reverse end) pointer-iterator for the list. r_end acts as a sentinel node.
219
+
220
+ el_ty *end( list( el_ty ) *cntr )
221
+
222
+ Returns an end pointer-iterator for the list. End acts as a sentinel node.
223
+
224
+ el_ty *next( list( el_ty ) *cntr, el_ty *i )
225
+
226
+ Returns a pointer-iterator to the element after the one pointed to by i.
227
+ If i points to the last element, the return value is an end pointer-iterator.
228
+ If i points to r_end, the return value is a pointer-iterator to the first element, or an end pointer-iterator if
229
+ the list is empty.
230
+
231
+ el_ty *prev( list( el_ty ) *cntr, el_ty *i )
232
+
233
+ Returns a pointer-iterator to the element before the one pointed to by i.
234
+ If i points to the first element, the return value is an r_end pointer-iterator.
235
+ If i points to end, then the return value is a pointer-iterator to the last element, or an r_end pointer-iterator
236
+ if the list is empty.
237
+
238
+ r_for_each( list( el_ty ) *cntr, i_name )
239
+
240
+ Creates a loop iterating over all elements from last to first.
241
+ This macro declares an el_ty * pointer-iterator named i_name.
242
+ It is equivalent to
243
+ for( el_ty *i_name = last( cntr ); i_name != r_end( cntr ); i_name = prev( cntr, i_name ) )
244
+ and should be followed by the body of the loop.
245
+
246
+ Notes:
247
+ - List pointer-iterators (including r_end and end) are not invalidated by any API calls besides init and cleanup,
248
+ unless they point to erased elements.
249
+
250
+ Map (an unordered container associating elements with keys, implemented as a Robin Hood hash table):
251
+
252
+ map( key_ty, el_ty ) cntr
253
+
254
+ Declares an uninitialized map named cntr.
255
+ key_ty must be a type, or alias for a type, for which comparison and hash functions have been defined.
256
+ This requirement is enforced internally such that neglecting it causes a compiler error.
257
+ For types with in-built comparison and hash functions, and for details on how to declare new comparison and hash
258
+ functions, see "Destructor, comparison, and hash functions and custom max load factors" below.
259
+
260
+ size_t cap( map( key_ty, el_ty ) *cntr )
261
+
262
+ Returns the current capacity, i.e. bucket count.
263
+ Note that the number of elements a map can support without rehashing is not its capacity but its capacity
264
+ multiplied by the max load factor associated with its key type.
265
+
266
+ bool reserve( map( key_ty, el_ty ) *cntr, size_t n )
267
+
268
+ Ensures that the capacity is large enough to support n elements without rehashing.
269
+ Returns true, or false if unsuccessful due to memory allocation failure.
270
+
271
+ bool shrink( map( key_ty, el_ty ) *cntr )
272
+
273
+ Shrinks the capacity to best accommodate the current size.
274
+ Returns true, or false if unsuccessful due to memory allocation failure.
275
+
276
+ el_ty *insert( map( key_ty, el_ty ) *cntr, key_ty key, el_ty el )
277
+
278
+ Inserts element el with the specified key.
279
+ If an element with the same key already exists, the existing element is replaced.
280
+ Returns a pointer-iterator to the new element, or NULL in the case of memory allocation failure.
281
+ If adding one element would violate the map's max load factor, failure can occur even if it already contains the
282
+ key.
283
+
284
+ el_ty *get( map( key_ty, el_ty ) *cntr, key_ty key )
285
+
286
+ Returns a pointer-iterator to the element with the specified key, or NULL if no such element exists.
287
+
288
+ el_ty *get_or_insert( map( key_ty, el_ty ) *cntr, key_ty key, el_ty el )
289
+
290
+ Inserts element el if no element with the specified key already exist.
291
+ Returns a pointer-iterator to the new element if it was inserted, or a pointer-iterator to the existing
292
+ element with the same key, or NULL in the case of memory allocation failure.
293
+ If adding one element would violate the map's max load factor, failure can occur even if it already contains the
294
+ key.
295
+ Determine whether an element was inserted by comparing the map's size before and after the call.
296
+
297
+ const key_ty *key_for( map( key_ty, el_ty ) *cntr, el_ty *i )
298
+
299
+ Returns a const pointer to the key for the element pointed to by pointer-iterator i.
300
+
301
+ bool erase( map( key_ty, el_ty ) *cntr, key_ty key )
302
+
303
+ Erases the element with the specified key, if it exists.
304
+ Returns true if an element was erased, or false if no such element exists.
305
+
306
+ void erase_itr( map( key_ty, el_ty ) *cntr, el_ty *i )
307
+
308
+ Erases the element pointed to by pointer-iterator i.
309
+
310
+ el_ty *first( map( key_ty, el_ty ) *cntr )
311
+
312
+ Returns a pointer-iterator to the first element, or an end pointer-iterator if the map is empty.
313
+
314
+ el_ty *last( map( key_ty, el_ty ) *cntr )
315
+
316
+ Returns a pointer-iterator to the last element, or an r_end pointer-iterator if the map is empty.
317
+
318
+ el_ty *r_end( map( key_ty, el_ty ) *cntr )
319
+
320
+ Returns an r_end (reverse end) pointer-iterator for the map.
321
+
322
+ el_ty *end( map( key_ty, el_ty ) *cntr )
323
+
324
+ Returns an end pointer-iterator for the map.
325
+
326
+ el_ty *next( map( key_ty, el_ty ) *cntr, el_ty *i )
327
+
328
+ Returns a pointer-iterator to the element after the one pointed to by i.
329
+ If i points to the last element, the value returned is an end pointer-iterator.
330
+ If i points to r_end, the value returned points to the first element, or is an end pointer-iterator if the map is
331
+ empty.
332
+
333
+ el_ty *prev( map( key_ty, el_ty ) *cntr, el_ty *i )
334
+
335
+ Returns a pointer-iterator to the element before the one pointed to by i.
336
+ If i points to the first element, the value returned is an r_end pointer-iterator.
337
+ If i points to end, then the value returned points to the last element, or is an r_end pointer-iterator if the map
338
+ is empty.
339
+
340
+ for_each( map( key_ty, el_ty ) *cntr, key_ptr_name, i_name )
341
+
342
+ Creates a loop iterating over all elements from first to last, with easy access to the corresponding keys.
343
+ This macro declares a pointer to the key (const key_ty *) named key_ptr_name and a pointer-iterator (el_ty *)
344
+ named i_name.
345
+ It should be followed by the body of the loop.
346
+
347
+ r_for_each( map( key_ty, el_ty ) *cntr, i_name )
348
+
349
+ Creates a loop iterating over all elements from last to first.
350
+ This macro declares an el_ty * pointer-iterator named i_name.
351
+ It is equivalent to
352
+ for( el_ty *i_name = last( cntr ); i_name != r_end( cntr ); i_name = prev( cntr, i_name ) )
353
+ and should be followed by the body of the loop.
354
+
355
+ r_for_each( map( key_ty, el_ty ) *cntr, key_ptr_name, i_name )
356
+
357
+ Creates a loop iterating over all elements from last to first, with easy access to the corresponding keys.
358
+ This macro declares a pointer to the key (const key_ty *) named key_ptr_name and a pointer-iterator (el_ty *)
359
+ named i_name.
360
+ It should be followed by the body of the loop.
361
+
362
+ Notes:
363
+ - Map pointer-iterators (including r_end and end) may be invalidated by any API calls that cause memory
364
+ reallocation.
365
+
366
+ Set (Robin Hood hash table for elements without a separate key):
367
+
368
+ set( el_ty ) cntr
369
+
370
+ Declares an uninitialized set named cntr.
371
+ el_ty must be a type, or alias for a type, for which comparison and hash functions have been defined.
372
+ This requirement is enforced internally such that neglecting it causes a compiler error.
373
+ For types with in-built comparison and hash functions, and for details on how to declare new comparison and hash
374
+ functions, see "Destructor, comparison, and hash functions and custom max load factors" below.
375
+
376
+ size_t cap( set( el_ty ) *cntr )
377
+
378
+ Returns the current capacity, i.e. bucket count.
379
+ Note that the number of elements a set can support without rehashing is not its capacity but its capacity
380
+ multiplied by the max load factor associated with its key type.
381
+
382
+ bool reserve( set( el_ty ) *cntr, size_t n )
383
+
384
+ Ensures that the capacity is large enough to support n elements without rehashing.
385
+ Returns true, or false if unsuccessful due to memory allocation failure.
386
+
387
+ bool shrink( set( el_ty ) *cntr )
388
+
389
+ Shrinks the capacity to best accommodate the current size.
390
+ Returns true, or false if unsuccessful due to memory allocation failure.
391
+
392
+ el_ty *insert( set( el_ty ) *cntr, el_ty el )
393
+
394
+ Inserts element el.
395
+ If the element already exists, the existing element is replaced.
396
+ Returns a pointer-iterator to the new element, or NULL in the case of memory allocation failure.
397
+ Note that if adding one element would violate the set's max load factor, failure can occur even if it already
398
+ contains el.
399
+
400
+ el_ty *get( set( el_ty ) *cntr, el_ty el )
401
+
402
+ Returns a pointer-iterator to element el, or NULL if no such element exists.
403
+
404
+ el_ty *get_or_insert( set( el_ty ) *cntr, el_ty el )
405
+
406
+ Inserts element el if it does not already exist.
407
+ Returns a pointer-iterator to the new element if it was inserted, or a pointer-iterator to the existing element,
408
+ or NULL in the case of memory allocation failure.
409
+ If adding one element would violate the set's max load factor, failure can occur even if it already contains the
410
+ element.
411
+ Determine whether an element was inserted by comparing the set's size before and after the call.
412
+
413
+ bool erase( set( el_ty ) *cntr, el_ty el )
414
+
415
+ Erases the element el, if it exists.
416
+ Returns true if an element was erased, or false if no such element exists.
417
+
418
+ el_ty *first( set( el_ty ) *cntr )
419
+
420
+ Returns a pointer-iterator to the first element, or an end pointer-iterator if the set is empty.
421
+
422
+ el_ty *last( set( el_ty ) *cntr )
423
+
424
+ Returns a pointer-iterator to the last element, or an r_end pointer-iterator if the set is empty.
425
+
426
+ el_ty *r_end( set( el_ty ) *cntr )
427
+
428
+ Returns an r_end (reverse end) pointer-iterator for the set.
429
+
430
+ el_ty *end( set( el_ty ) *cntr )
431
+
432
+ Returns an end pointer-iterator for the set.
433
+
434
+ el_ty *next( set( el_ty ) *cntr, el_ty *i )
435
+
436
+ Returns a pointer-iterator to the element after the one pointed to by i.
437
+ If i points to the last element, the pointer-iterator returned is an end pointer-iterator.
438
+ If i points to r_end, then the pointer-iterator returned points to the first element, or is an end
439
+ pointer-iterator if the set is empty.
440
+
441
+ el_ty *prev( set( el_ty ) *cntr, el_ty *i )
442
+
443
+ Returns a pointer-iterator to the element before the one pointed to by i.
444
+ If i points to the first element, the return value is an r_end pointer-iterator.
445
+ If i points to end, then the pointer-iterator returned points to the last element, or is an r_end pointer-iterator
446
+ if the set is empty.
447
+
448
+ r_for_each( set( el_ty ) *cntr, i_name )
449
+
450
+ Creates a loop iterating over all elements from last to first.
451
+ This macro declares an el_ty * pointer-iterator named i_name.
452
+ It is equivalent to
453
+ for( el_ty *i_name = last( cntr ); i_name != r_end( cntr ); i_name = prev( cntr, i_name ) )
454
+ and should be followed by the body of the loop.
455
+
456
+ Notes:
457
+ - Set pointer-iterators (including r_end and end) may be invalidated by any API calls that cause memory
458
+ reallocation.
459
+
460
+ Destructor, comparison, and hash functions and custom max load factors:
461
+
462
+ This part of the API allows the user to define custom destructor, comparison, and hash functions and max load
463
+ factors for a type.
464
+ Once these functions are defined, any container using that type for its elements or keys will call them
465
+ automatically.
466
+ Once the max load factor is defined, any map using the type for its key and any set using the type for its elements
467
+ will use the defined load factor to determine when rehashing is necessary.
468
+
469
+ #define CC_DTOR ty, { function body }
470
+ #include "cc.h"
471
+
472
+ Defines a destructor for type ty.
473
+ The signature of the function is void ( ty val ).
474
+
475
+ #define CC_CMPR ty, { function body }
476
+ #include "cc.h"
477
+
478
+ Defines a comparison function for type ty.
479
+ The signature of the function is int ( ty val_1, ty val_2 ).
480
+ The function should return 0 if val_1 and val_2 are equal, a negative integer if val_1 is less than val_2, and a
481
+ positive integer if val_1 is more than val_2.
482
+
483
+ #define CC_HASH ty, { function body }
484
+ #include "cc.h"
485
+
486
+ Defines a hash function for type ty.
487
+ The signature of the function is size_t ( ty val ).
488
+ The function should return the hash of val.
489
+
490
+ #define CC_LOAD ty, max_load_factor
491
+
492
+ Defines the max load factor for type ty.
493
+ max_load_factor should be a float or double between 0.0 and 1.0.
494
+ The default max load factor is 0.8.
495
+
496
+ Trivial example:
497
+
498
+ typedef struct { int x; } my_type;
499
+ #define CC_DTOR my_type, { printf( "!%d\n", val.x ); }
500
+ #define CC_CMPR my_type, { return ( val_1.x > val_2.x ) - ( val_1.x < val_2.x ); }
501
+ #define CC_HASH my_type, { return val.x * 2654435761ull; }
502
+ #define CC_LOAD my_type, 0.5
503
+ #include "cc.h"
504
+
505
+ Notes:
506
+ - These functions are inline and have static scope, so you need to either redefine them in each translation unit
507
+ from which they should be called or (preferably) define them in a shared header. For structs or unions, a sensible
508
+ place to define them would be immediately after the definition of the struct or union.
509
+ - Only one destructor, comparison, or hash function or max load factor should be defined by the user for each type.
510
+ - #including cc.h in these cases does not #include the full header, so you still need to #include it separately
511
+ at the top of your files.
512
+ - In-built comparison and hash functions are already defined for the following types: char, unsigned char, signed
513
+ char, unsigned short, short, unsigned int, int, unsigned long, long, unsigned long long, long long, size_t, and
514
+ char * (a NULL-terminated string). Defining a comparsion or hash function for one of these types will overwrite
515
+ the in-built function.
516
+
517
+ Version history:
518
+
519
+ 27/01/2023 1.0.1: Minor corrections to code comments.
520
+ 26/12/2022 1.0.0: Initial release.
521
+
522
+ License (MIT):
523
+
524
+ Copyright (c) 2022-2023 Jackson L. Allan
525
+
526
+ Permission is hereby granted, free of charge, to any person obtaining a copy
527
+ of this software and associated documentation files (the "Software"), to deal
528
+ in the Software without restriction, including without limitation the rights
529
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
530
+ copies of the Software, and to permit persons to whom the Software is
531
+ furnished to do so, subject to the following conditions:
532
+
533
+ The above copyright notice and this permission notice shall be included in all
534
+ copies or substantial portions of the Software.
535
+
536
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
537
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
538
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
539
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
540
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
541
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
542
+ SOFTWARE.
543
+ */
544
+
545
+ #if !defined( CC_DTOR ) && !defined( CC_CMPR ) && !defined( CC_HASH )/*-----------------------------------------------*/
546
+ /* */
547
+ /* REGULAR HEADER MODE */
548
+ /* */
549
+ /*--------------------------------------------------------------------------------------------------------------------*/
550
+
551
+ #ifndef CC_NO_SHORT_NAMES
552
+ #define vec( ... ) cc_vec( __VA_ARGS__ )
553
+ #define list( ... ) cc_list( __VA_ARGS__ )
554
+ #define map( ... ) cc_map( __VA_ARGS__ )
555
+ #define set( ... ) cc_set( __VA_ARGS__ )
556
+ #define init( ... ) cc_init( __VA_ARGS__ )
557
+ #define init_clone( ... ) cc_init_clone( __VA_ARGS__ )
558
+ #define size( ... ) cc_size( __VA_ARGS__ )
559
+ #define cap( ... ) cc_cap( __VA_ARGS__ )
560
+ #define reserve( ... ) cc_reserve( __VA_ARGS__ )
561
+ #define resize( ... ) cc_resize( __VA_ARGS__ )
562
+ #define shrink( ... ) cc_shrink( __VA_ARGS__ )
563
+ #define insert( ... ) cc_insert( __VA_ARGS__ )
564
+ #define insert_n( ... ) cc_insert_n( __VA_ARGS__ )
565
+ #define get_or_insert( ... ) cc_get_or_insert( __VA_ARGS__ )
566
+ #define push( ... ) cc_push( __VA_ARGS__ )
567
+ #define push_n( ... ) cc_push_n( __VA_ARGS__ )
568
+ #define splice( ... ) cc_splice( __VA_ARGS__ )
569
+ #define get( ... ) cc_get( __VA_ARGS__ )
570
+ #define key_for( ... ) cc_key_for( __VA_ARGS__ )
571
+ #define erase( ... ) cc_erase( __VA_ARGS__ )
572
+ #define erase_n( ... ) cc_erase_n( __VA_ARGS__ )
573
+ #define erase_itr( ... ) cc_erase_itr( __VA_ARGS__ )
574
+ #define clear( ... ) cc_clear( __VA_ARGS__ )
575
+ #define cleanup( ... ) cc_cleanup( __VA_ARGS__ )
576
+ #define first( ... ) cc_first( __VA_ARGS__ )
577
+ #define last( ... ) cc_last( __VA_ARGS__ )
578
+ #define r_end( ... ) cc_r_end( __VA_ARGS__ )
579
+ #define end( ... ) cc_end( __VA_ARGS__ )
580
+ #define next( ... ) cc_next( __VA_ARGS__ )
581
+ #define prev( ... ) cc_prev( __VA_ARGS__ )
582
+ #define for_each( ... ) cc_for_each( __VA_ARGS__ )
583
+ #define r_for_each( ... ) cc_r_for_each( __VA_ARGS__ )
584
+ #endif
585
+
586
+ #ifndef CC_H
587
+ #define CC_H
588
+
589
+ #include <stdalign.h>
590
+ #include <stdbool.h>
591
+ #include <stddef.h>
592
+ #include <stdlib.h>
593
+ #include <string.h>
594
+
595
+ #ifdef __cplusplus
596
+ #include <type_traits>
597
+ #endif
598
+
599
+ /*--------------------------------------------------------------------------------------------------------------------*/
600
+ /* Preliminary */
601
+ /*--------------------------------------------------------------------------------------------------------------------*/
602
+
603
+ // _Static_assert alternative that can be used inside an expression.
604
+ #define CC_STATIC_ASSERT( xp ) (void)sizeof( char[ (xp) ? 1 : -1 ] )
605
+
606
+ // In GCC and Clang, we can generate a warning if the user passes an expression that may have side effects as the first
607
+ // argument of API macros.
608
+ // If the expression could have side effects, the compiler will not able able to resolve a comparision of it with itself
609
+ // at compile time, which we can check using __builtin_constant_p.
610
+ // The warning itself is generated via a division by zero.
611
+ // This macro may produce false positives (e.g. for &my_containers[ my_func() ] where my_func is a pure function that
612
+ // always returns the same value), but that is a reasonable price to pay for more macro safety.
613
+
614
+ #ifdef __GNUC__
615
+
616
+ #define CC_WARN_DUPLICATE_SIDE_EFFECTS( cntr ) \
617
+ (void)( \
618
+ "WARNING: CONTAINER ARGUMENT MAY HAVE DUPLICATED SIDE EFFECTS" &&1/__builtin_constant_p((cntr)==(cntr)) \
619
+ ) \
620
+
621
+ #else
622
+ #define CC_WARN_DUPLICATE_SIDE_EFFECTS( cntr ) (void)0
623
+ #endif
624
+
625
+ // CC_SELECT_ON_NUM_ARGS macro for overloading API macros based on number of arguments.
626
+ #define CC_CAT_( a, b ) a##b
627
+ #define CC_CAT( a, b ) CC_CAT_( a, b )
628
+ #define CC_N_ARGS_( _1, _2, _3, _4, _5, _6, n, ... ) n
629
+ #define CC_N_ARGS( ... ) CC_N_ARGS_( __VA_ARGS__, _6, _5, _4, _3, _2, _1, x )
630
+ #define CC_SELECT_ON_NUM_ARGS( func, ... ) CC_CAT( func, CC_N_ARGS( __VA_ARGS__ ) )( __VA_ARGS__ )
631
+
632
+ // Typeof for expressions and abstract declarations.
633
+ #ifdef __cplusplus
634
+ #define CC_TYPEOF_XP( xp ) std::decay<std::remove_reference<decltype( xp )>::type>::type
635
+ #define CC_TYPEOF_TY( ty ) std::decay<std::remove_reference<decltype( std::declval<ty>() )>::type>::type
636
+ #else
637
+ // TODO: Add C23 check once C23 is supported by major compilers.
638
+ #define CC_TYPEOF_XP( xp ) __typeof__( xp )
639
+ #define CC_TYPEOF_TY( ty ) __typeof__( ty )
640
+ #endif
641
+
642
+ // Macro used with CC_STATIC_ASSERT to provide type safety in cc_init_clone and cc_splice calls.
643
+ #ifdef __cplusplus
644
+ #define CC_IS_SAME_TY( a, b ) std::is_same<CC_TYPEOF_XP( a ), CC_TYPEOF_XP( b )>::value
645
+ #else
646
+ #define CC_IS_SAME_TY( a, b ) _Generic( (a), CC_TYPEOF_XP( b ): true, default: false )
647
+ #endif
648
+
649
+ // Macro used primarily for silencing unused-expression warnings for macros that return cast pointers.
650
+ // This issued seems to affect Clang in particular.
651
+ // GCC, on the other hand, seems to accept that pointer casts may be redundant.
652
+ #ifdef __cplusplus
653
+ template<typename ty_1, typename ty_2> ty_1 cc_maybe_unused( ty_2 xp ){ return (ty_1)xp; }
654
+ #define CC_CAST_MAYBE_UNUSED( ty, xp ) cc_maybe_unused<ty>( xp )
655
+ #else
656
+ #define CC_CAST_MAYBE_UNUSED( ty, xp ) ( ( ty ){ 0 } = ( (ty)( xp ) ) )
657
+ #endif
658
+
659
+ // Some functions that must return true/false must return the value in the form of a pointer.
660
+ // This is because they are paired in ternary expressions inside API macros with other functions for other containers
661
+ // that return a pointer (primarily cc_erase).
662
+ // While any suitably aligned pointer - e.g. the container handle - would do, we declare a global cc_dummy_true_ptr for
663
+ // the sake of code readability.
664
+ static max_align_t cc_dummy_true;
665
+ static void *cc_dummy_true_ptr = &cc_dummy_true;
666
+
667
+ // Container ids to identify container type at compile-time.
668
+ #define CC_VEC 1
669
+ #define CC_LIST 2
670
+ #define CC_MAP 3
671
+ #define CC_SET 4
672
+
673
+ // Produces underlying function pointer type for a given element/key type pair.
674
+ #define CC_MAKE_BASE_FNPTR_TY( el_ty, key_ty ) CC_TYPEOF_TY( CC_TYPEOF_TY( el_ty ) (*)( CC_TYPEOF_TY( key_ty )* ) )
675
+
676
+ // Produces container handle for a given element type, key type, and container id.
677
+ // In other words, this macro creates a pointer that carries all the information needed to identify and operate on a
678
+ // container at compile time: el_ty (*(*)[ cntr_id ])( key_ty * ).
679
+ // That is a pointer to an array of function pointers whose signature is el_ty ( key_ty * ).
680
+ #define CC_MAKE_CNTR_TY( el_ty, key_ty, cntr_id ) CC_TYPEOF_TY( CC_MAKE_BASE_FNPTR_TY( el_ty, key_ty )(*)[ cntr_id ] )
681
+
682
+ // Dummy type used as key type in containers that don't use keys.
683
+ // This greatly reduces the complexity of API macros.
684
+ typedef struct{ char nothing; } cc_dummy_ty;
685
+
686
+ // API macros for declaring containers.
687
+
688
+ #define cc_vec( el_ty ) CC_MAKE_CNTR_TY( el_ty, cc_dummy_ty, CC_VEC )
689
+
690
+ #define cc_list( el_ty ) CC_MAKE_CNTR_TY( el_ty, cc_dummy_ty, CC_LIST )
691
+
692
+ #define cc_map( key_ty, el_ty ) CC_MAKE_CNTR_TY( \
693
+ el_ty, \
694
+ key_ty, \
695
+ /* Compiler error if key type lacks compare and hash functions. */ \
696
+ CC_MAP * ( ( CC_HAS_CMPR( key_ty ) && CC_HAS_HASH( key_ty ) ) ? 1 : -1 ) \
697
+ ) \
698
+
699
+ #define cc_set( el_ty ) CC_MAKE_CNTR_TY( \
700
+ /* As set simply wraps map, we use el_ty as both the element and key types. */ \
701
+ /* This allows minimal changes to map macros and functions to make sets work. */ \
702
+ el_ty, \
703
+ el_ty, \
704
+ /* Compiler error if el type lacks compare and hash functions. */ \
705
+ CC_SET * ( ( CC_HAS_CMPR( el_ty ) && CC_HAS_HASH( el_ty ) ) ? 1 : -1 ) \
706
+ ) \
707
+
708
+ // Retrieves a container's id (CC_VEC, CC_LIST, etc.) from its handle.
709
+ #define CC_CNTR_ID( cntr ) ( sizeof( *cntr ) / sizeof( **cntr ) )
710
+
711
+ // Retrieves a container's element type from its handle.
712
+ #define CC_EL_TY( cntr ) CC_TYPEOF_XP( (**cntr)( NULL ) )
713
+
714
+ // CC_KEY_TY macros for retrieving a container's key type from its handle (i.e. from the argument of the base function
715
+ // pointer).
716
+ #ifdef __cplusplus // For C++, this can be done easily with the help of a template function.
717
+
718
+ template<typename el_ty, typename key_ty>
719
+ key_ty cc_key_ty( el_ty (*)( key_ty * ) )
720
+ {
721
+ key_ty dummy;
722
+ return dummy;
723
+ }
724
+
725
+ #define CC_KEY_TY( cntr ) CC_TYPEOF_XP( cc_key_ty( **cntr ) )
726
+
727
+ #else // For C, we need to use _Generic trickery to match the base function pointer type with a key type previously
728
+ // coupled with a compare function.
729
+ // Returns cc_dummy_t if no compare function for type has been defined.
730
+
731
+ #define CC_KEY_TY_SLOT( n, arg ) CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( arg ), cc_cmpr_##n##_ty ): ( cc_cmpr_##n##_ty ){ 0 },
732
+ #define CC_KEY_TY( cntr ) \
733
+ CC_TYPEOF_XP( \
734
+ _Generic( (**cntr), \
735
+ CC_FOR_EACH_CMPR( CC_KEY_TY_SLOT, cntr ) \
736
+ default: _Generic( (**cntr), \
737
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), char ): ( char ){ 0 }, \
738
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), unsigned char ): ( unsigned char ){ 0 }, \
739
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), signed char ): ( signed char ){ 0 }, \
740
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), unsigned short ): ( unsigned short ){ 0 }, \
741
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), short ): ( short ){ 0 }, \
742
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), unsigned int ): ( unsigned int ){ 0 }, \
743
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), int ): ( int ){ 0 }, \
744
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), unsigned long ): ( unsigned long ){ 0 }, \
745
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), long ): ( long ){ 0 }, \
746
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), unsigned long long ): ( unsigned long long ){ 0 }, \
747
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), long long ): ( long long ){ 0 }, \
748
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), cc_maybe_size_t ): ( size_t ){ 0 }, \
749
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), char * ): ( char * ){ 0 }, \
750
+ default: (cc_dummy_ty){ 0 } \
751
+ ) \
752
+ ) \
753
+ ) \
754
+
755
+ #endif
756
+
757
+ // Macros to provide easy access to a container's element and key sizes.
758
+ #define CC_EL_SIZE( cntr ) sizeof( CC_EL_TY( cntr ) )
759
+ #define CC_KEY_SIZE( cntr ) sizeof( CC_KEY_TY( cntr ) )
760
+
761
+ // Macro to round up a number to a multiple of a factor.
762
+ // This is used to determine bucket size and offsets in sets and maps.
763
+ #define CC_ROUND_UP( n, factor ) ( ( ( (n) + (factor) - 1 ) / (factor) ) * (factor) )
764
+
765
+ // If the user has defined CC_REALLOC and CC_FREE, then CC_GET_REALLOC and CC_GET_FREE are replaced with those macros.
766
+ // Otherwise, they are replaced by realloc and free from the standard library.
767
+ #define CC_ARG_2_( _1, _2, ... ) _2
768
+ #define CC_ARG_2( ... ) CC_ARG_2_( __VA_ARGS__ )
769
+ #define CC_REALLOC_COMMA ,
770
+ #define CC_GET_REALLOC CC_ARG_2( CC_CAT( CC_REALLOC, _COMMA ) realloc, CC_REALLOC, )
771
+ #define CC_FREE_COMMA ,
772
+ #define CC_GET_FREE CC_ARG_2( CC_CAT( CC_FREE, _COMMA ) free, CC_FREE, )
773
+
774
+ // Default max load factor for maps and sets.
775
+ #define CC_DEFAULT_LOAD 0.8
776
+
777
+ // Swaps a block of memory (used for Robin-Hooding in maps and sets).
778
+ static inline void cc_memswap( void *a, void *b, size_t size )
779
+ {
780
+ for( size_t i = 0; i < size; ++i )
781
+ {
782
+ char temp = ( (char *)a )[ i ];
783
+ ( (char *)a )[ i ] = ( (char *)b )[ i ];
784
+ ( (char *)b )[ i ] = temp;
785
+ }
786
+ }
787
+
788
+ // CC_MAKE_LVAL_COPY macro for making an addressable temporary copy of a variable or expression.
789
+ // The copy is valid until at least the end of full expression surrounding the macro call.
790
+ // In C, this is accomplished using a compound literal.
791
+ // In C++, we use rvalue reference magic.
792
+ // This is used, for example, to pass a pointer to an element (which the user may have provided as an rvalue) into an
793
+ // insert function.
794
+ #ifdef __cplusplus
795
+ template<class ty> ty& cc_unmove( ty&& var ) { return var; }
796
+ #define CC_MAKE_LVAL_COPY( ty, xp ) cc_unmove( ty( xp ) )
797
+ #else
798
+ #define CC_MAKE_LVAL_COPY( ty, xp ) *( ty[ 1 ] ){ xp }
799
+ #endif
800
+
801
+ // CC_IF_THEN_XP_ELSE_DUMMY macro for allowing an expression only if a condition is true.
802
+ // If not true, then the macro returns a dummy value of a specified type.
803
+ // This macros allows API macros to have arguments whose type depends on the container id where the different container
804
+ // types are incompatible.
805
+ // Without it, those macros could not compile.
806
+ // In other words, this macro achieves SFINAE-like functionality.
807
+ #ifdef __cplusplus
808
+
809
+ template<bool cond, class ty, class xp_ty, typename std::enable_if<cond, bool>::type = true>
810
+ xp_ty cc_if_then_xp_else_dummy( xp_ty xp ){ return xp; }
811
+
812
+ template<bool cond, class ty, class xp_ty, typename std::enable_if<!cond, bool>::type = true>
813
+ ty cc_if_then_xp_else_dummy( xp_ty xp ){ return ty(); }
814
+
815
+ #define CC_IF_THEN_XP_ELSE_DUMMY( cond, xp, ty ) ( cc_if_then_xp_else_dummy<cond, ty>( xp ) )
816
+
817
+ #else
818
+
819
+ #define CC_IF_THEN_XP_ELSE_DUMMY( cond, xp, dummy_type ) \
820
+ _Generic( (char (*)[ 1 + (bool)( cond ) ]){ 0 }, \
821
+ char (*)[ 1 ]: (dummy_type){ 0 }, \
822
+ char (*)[ 2 ]: xp \
823
+ ) \
824
+
825
+ #endif
826
+
827
+ // CC_IF_THEN_PTR_TO_BOOL_ELSE_PTR macro for casting a pointer to bool only if a condition is true.
828
+ // It is necessary because some API macros (e.g. cc_erase) should return a bool to the user for certain containers and a
829
+ // pointer to an element for others.
830
+ // With this macro, all the corresponding internal functions can return pointers, and the pointer is cast to bool at the
831
+ // highest level if dictated by the container id.
832
+ #ifdef __cplusplus
833
+
834
+ template<bool cond, class ptr_ty, typename std::enable_if<cond, bool>::type = true> \
835
+ bool cc_if_then_ptr_to_bool_else_ptr( ptr_ty ptr ){ return ptr; } \
836
+
837
+ template<bool cond, class ptr_ty, typename std::enable_if<!cond, bool>::type = true> \
838
+ ptr_ty cc_if_then_ptr_to_bool_else_ptr( ptr_ty ptr ){ return ptr; } \
839
+
840
+ #define CC_IF_THEN_PTR_TO_BOOL_ELSE_PTR( cond, ptr ) \
841
+ cc_if_then_ptr_to_bool_else_ptr<cond>( ptr ) \
842
+
843
+ #else
844
+
845
+ #define CC_IF_THEN_PTR_TO_BOOL_ELSE_PTR( cond, ptr ) \
846
+ _Generic( (char (*)[ 1 + (bool)( cond ) ]){ 0 }, \
847
+ char (*)[ 1 ]: ptr, \
848
+ char (*)[ 2 ]: CC_CAST_MAYBE_UNUSED( bool, ptr ) \
849
+ ) \
850
+
851
+ #endif
852
+
853
+ // Return type for all functions that could reallocate a container's memory.
854
+ // It contains a new container handle (the pointer may have changed to due reallocation) and an additional pointer whose
855
+ // purpose depends on the function.
856
+ // For functions that insert elements, that pointer points to the newly inserted elements, or NULL in the case of
857
+ // allocation failure.
858
+ // For other functions, that pointer is a dummy pointer that evaluates to true, or NULL in the case of allocation
859
+ // failure (i.e. its only purpose is to convey whether the operation was successful).
860
+ // The struct is aligned to max_align_t because the container handle must temporarily point to it (see
861
+ // CC_POINT_HNDL_TO_ALLOCING_FN_RESULT below).
862
+ typedef struct
863
+ {
864
+ alignas( max_align_t )
865
+ void *new_cntr;
866
+ void *other_ptr;
867
+ } cc_allocing_fn_result_ty;
868
+
869
+ // Helper function for one-line cc_allocing_fn_result_ty.
870
+ static inline cc_allocing_fn_result_ty cc_make_allocing_fn_result( void *new_cntr, void *other_ptr )
871
+ {
872
+ cc_allocing_fn_result_ty result;
873
+ result.new_cntr = new_cntr;
874
+ result.other_ptr = other_ptr;
875
+ return result;
876
+ }
877
+
878
+ // Performs memcpy and returns ptr.
879
+ // Used in conjunction with cc_allocing_fn_result_ty (see below).
880
+ static inline void *cc_memcpy_and_return_ptr( void *dest, void *src, size_t size, void *ptr )
881
+ {
882
+ memcpy( dest, src, size );
883
+ return ptr;
884
+ }
885
+
886
+ // All macros that call functions that could cause memory reallocation do two essential things to circumvent limitations
887
+ // of ISO C (such as the inability to declare variables in expressions and _Thread_local linking issues).
888
+ // Firstly, they temporarily set the container handle to point to a temporary cc_insert_result object returned by the
889
+ // call to the function (see CC_MAKE_LVAL_COPY above).
890
+ #define CC_POINT_HNDL_TO_ALLOCING_FN_RESULT( cntr, fn_call ) \
891
+ cntr = (CC_TYPEOF_XP( cntr ))&CC_MAKE_LVAL_COPY( cc_allocing_fn_result_ty, fn_call ) \
892
+
893
+ // Secondly, they call cc_memcpy_and_return_ptr to restore the correct container handle (a new pointer in the case of
894
+ // reallocation) and return a pointer, either to any new elements or to signify success/failure, to the user.
895
+ // (In the latter case, that pointer is cast to bool in the API macro before being passed to the user.)
896
+ // Without this call, we would be unable to access the new elements/success-or-failure pointer stored in the
897
+ // cc_allocing_fn_result_ty after restoring the correct container handle.
898
+ // Note that outside the function, a temporary container handle is created from the new handle in the
899
+ // cc_allocing_fn_result_ty so that the later (void *) is properly converted to the correct handle type.
900
+ // This new, correctly typed handle is then memcpy-ed over the user-supplied handle inside the function.
901
+ #define CC_FIX_HNDL_AND_RETURN_OTHER_PTR( cntr ) \
902
+ cc_memcpy_and_return_ptr( \
903
+ &cntr, \
904
+ &CC_MAKE_LVAL_COPY( CC_TYPEOF_XP( cntr ), ( (cc_allocing_fn_result_ty *)cntr )->new_cntr ), \
905
+ sizeof( cntr ), \
906
+ ( (cc_allocing_fn_result_ty *)cntr )->other_ptr \
907
+ ) \
908
+
909
+ /*--------------------------------------------------------------------------------------------------------------------*/
910
+ /* Vector */
911
+ /*--------------------------------------------------------------------------------------------------------------------*/
912
+
913
+ // Vector header.
914
+ typedef struct
915
+ {
916
+ alignas( max_align_t )
917
+ size_t size;
918
+ size_t cap;
919
+ } cc_vec_hdr_ty;
920
+
921
+ // Global placeholder for vector with no allocated storage.
922
+ // In the case of vectors, the placeholder allows us to avoid checking for a NULL container handle inside functions.
923
+ static const cc_vec_hdr_ty cc_vec_placeholder = { 0, 0 };
924
+
925
+ #define CC_VEC_INIT( cntr ) \
926
+ ( \
927
+ cntr = (CC_TYPEOF_XP( cntr ))&cc_vec_placeholder, \
928
+ (void)0 \
929
+ ) \
930
+
931
+ // Provides easy access to a vector's header.
932
+ static inline cc_vec_hdr_ty *cc_vec_hdr( void *cntr )
933
+ {
934
+ return (cc_vec_hdr_ty *)cntr;
935
+ }
936
+
937
+ static inline size_t cc_vec_size( void *cntr )
938
+ {
939
+ return cc_vec_hdr( cntr )->size;
940
+ }
941
+
942
+ static inline size_t cc_vec_cap( void *cntr )
943
+ {
944
+ return cc_vec_hdr( cntr )->cap;
945
+ }
946
+
947
+ static inline bool cc_vec_is_placeholder( void *cntr )
948
+ {
949
+ return cc_vec_hdr( cntr )->cap == 0;
950
+ }
951
+
952
+ // Returns a pointer-iterator to the element at index i.
953
+ static inline void *cc_vec_get( void *cntr, size_t i, size_t el_size )
954
+ {
955
+ return (char *)cntr + sizeof( cc_vec_hdr_ty ) + el_size * i;
956
+ }
957
+
958
+ #define CC_VEC_GET( cntr, i ) cc_vec_get( cntr, i, CC_EL_SIZE( cntr ) )
959
+
960
+ // Ensures that the capacity is large enough to support n elements without reallocation.
961
+ // Returns a cc_allocing_fn_result_ty containing the new handle and a pointer that evaluates to true if the operation was
962
+ // successful.
963
+ static inline cc_allocing_fn_result_ty cc_vec_reserve(
964
+ void *cntr,
965
+ size_t n,
966
+ size_t el_size,
967
+ void *(*realloc_)( void *, size_t )
968
+ )
969
+ {
970
+ if( cc_vec_cap( cntr ) >= n )
971
+ return cc_make_allocing_fn_result( cntr, cc_dummy_true_ptr );
972
+
973
+ bool is_placeholder = cc_vec_is_placeholder( cntr );
974
+
975
+ cc_vec_hdr_ty *new_cntr = (cc_vec_hdr_ty *)realloc_(
976
+ is_placeholder ? NULL : cntr,
977
+ sizeof( cc_vec_hdr_ty ) + el_size * n
978
+ );
979
+
980
+ if( !new_cntr )
981
+ return cc_make_allocing_fn_result( cntr, NULL );
982
+
983
+ if( is_placeholder )
984
+ new_cntr->size = 0;
985
+
986
+ new_cntr->cap = n;
987
+ return cc_make_allocing_fn_result( new_cntr, cc_dummy_true_ptr );
988
+ }
989
+
990
+ #define CC_VEC_RESERVE( cntr, n ) \
991
+ ( \
992
+ CC_POINT_HNDL_TO_ALLOCING_FN_RESULT( \
993
+ cntr, \
994
+ cc_vec_reserve( cntr, n, CC_EL_SIZE( cntr ), CC_GET_REALLOC ) \
995
+ ), \
996
+ (bool)CC_FIX_HNDL_AND_RETURN_OTHER_PTR( cntr ) \
997
+ ) \
998
+
999
+ // Inserts elements at index i.
1000
+ // Returns a cc_allocing_fn_result_ty containing the new handle and a pointer-iterator to the newly inserted elements.
1001
+ // If the underlying storage needed to be expanded and an allocation failure occurred, or if n is zero, the latter
1002
+ // pointer will be NULL.
1003
+ static inline cc_allocing_fn_result_ty cc_vec_insert(
1004
+ void *cntr,
1005
+ size_t i,
1006
+ void *els,
1007
+ size_t n,
1008
+ size_t el_size,
1009
+ void *( *realloc_ )( void *, size_t )
1010
+ )
1011
+ {
1012
+ if( n == 0 )
1013
+ return cc_make_allocing_fn_result( cntr, NULL );
1014
+
1015
+ if( cc_vec_size( cntr ) + n > cc_vec_cap( cntr ) )
1016
+ {
1017
+ size_t cap = cc_vec_cap( cntr );
1018
+ if( !cap )
1019
+ cap = 2;
1020
+
1021
+ while( cap < cc_vec_size( cntr ) + n )
1022
+ cap *= 2;
1023
+
1024
+ cc_allocing_fn_result_ty result = cc_vec_reserve( cntr, cap, el_size, realloc_ );
1025
+ if( !result.other_ptr )
1026
+ return result;
1027
+
1028
+ cntr = result.new_cntr;
1029
+ }
1030
+
1031
+ void *new_els = cc_vec_get( cntr, i, el_size );
1032
+ memmove( cc_vec_get( cntr, i + n, el_size ), new_els, el_size * ( cc_vec_hdr( cntr )->size - i ) );
1033
+ memcpy( new_els, els, el_size * n );
1034
+ cc_vec_hdr( cntr )->size += n;
1035
+
1036
+ return cc_make_allocing_fn_result( cntr, new_els );
1037
+ }
1038
+
1039
+ #define CC_VEC_INSERT_N( cntr, i, els, n ) \
1040
+ ( \
1041
+ CC_POINT_HNDL_TO_ALLOCING_FN_RESULT( \
1042
+ cntr, \
1043
+ cc_vec_insert( cntr, i, els, n, CC_EL_SIZE( cntr ), CC_GET_REALLOC ) \
1044
+ ), \
1045
+ CC_FIX_HNDL_AND_RETURN_OTHER_PTR( cntr ) \
1046
+ ) \
1047
+
1048
+ #define CC_VEC_INSERT( cntr, i, el ) CC_VEC_INSERT_N( cntr, i, &CC_MAKE_LVAL_COPY( CC_EL_TY( cntr ), el ), 1 )
1049
+
1050
+ #define CC_VEC_PUSH_N( cntr, els, n ) CC_VEC_INSERT_N( cntr, cc_vec_size( cntr ), els, n )
1051
+
1052
+ #define CC_VEC_PUSH( cntr, el ) CC_VEC_PUSH_N( cntr, &CC_MAKE_LVAL_COPY( CC_EL_TY( cntr ), el ), 1 )
1053
+
1054
+ // Erases n elements at index i.
1055
+ // Returns a pointer-iterator to the element after the erased elements, or an end pointer-iterator if there is no
1056
+ // subsequent element.
1057
+ static inline void *cc_vec_erase_n( void *cntr, size_t i, size_t n, size_t el_size, void ( *dtor )( void * ) )
1058
+ {
1059
+ if( n == 0 )
1060
+ return cc_vec_get( cntr, i, el_size );
1061
+
1062
+ if( dtor )
1063
+ for( size_t j = 0; j < n; ++j )
1064
+ dtor( cc_vec_get( cntr, i + j, el_size ) );
1065
+
1066
+ memmove(
1067
+ cc_vec_get( cntr, i, el_size ),
1068
+ cc_vec_get( cntr, i + n, el_size ),
1069
+ ( cc_vec_hdr( cntr )->size - n - i ) * el_size
1070
+ );
1071
+
1072
+ cc_vec_hdr( cntr )->size -= n;
1073
+ return cc_vec_get( cntr, i, el_size );
1074
+ }
1075
+
1076
+ #define CC_VEC_ERASE_N( cntr, i, n ) cc_vec_erase_n( cntr, i, n, CC_EL_SIZE( cntr ), CC_EL_DTOR( cntr ) )
1077
+
1078
+ #define CC_VEC_ERASE( cntr, i ) CC_VEC_ERASE_N( cntr, i, 1 )
1079
+
1080
+ // Sets the number of elements in the vector.
1081
+ // If n is below the current size, then the destructor is called for all erased elements.
1082
+ // In this case, the vector's capacity is not changed.
1083
+ // If n is above the current size, the new elements are uninitialized.
1084
+ // Returns a cc_allocing_fn_result_ty containing new container handle and a pointer that evaluates to true if the
1085
+ // operation was successful and false in the case of allocation failure.
1086
+ static inline cc_allocing_fn_result_ty cc_vec_resize(
1087
+ void *cntr,
1088
+ size_t n,
1089
+ size_t el_size,
1090
+ void ( *dtor )( void * ),
1091
+ void *( *realloc_ )( void *, size_t )
1092
+ )
1093
+ {
1094
+ // No resize necessary (also handles placeholder).
1095
+ if( n == cc_vec_size( cntr ) )
1096
+ return cc_make_allocing_fn_result( cntr, cc_dummy_true_ptr );
1097
+
1098
+ // Downsizing.
1099
+ if( n < cc_vec_size( cntr ) )
1100
+ {
1101
+ cc_vec_erase_n( cntr, n, cc_vec_size( cntr ) - n, el_size, dtor );
1102
+ return cc_make_allocing_fn_result( cntr, cc_dummy_true_ptr );
1103
+ }
1104
+
1105
+ // Up-sizing.
1106
+ cc_allocing_fn_result_ty result = cc_vec_reserve( cntr, n, el_size, realloc_ );
1107
+ if( !result.other_ptr )
1108
+ return result;
1109
+
1110
+ cc_vec_hdr( result.new_cntr )->size = n;
1111
+
1112
+ return result;
1113
+ }
1114
+
1115
+ #define CC_VEC_RESIZE( cntr, n ) \
1116
+ ( \
1117
+ CC_POINT_HNDL_TO_ALLOCING_FN_RESULT( \
1118
+ cntr, \
1119
+ cc_vec_resize( cntr, n, CC_EL_SIZE( cntr ), CC_EL_DTOR( cntr ), CC_GET_REALLOC ) \
1120
+ ), \
1121
+ (bool)CC_FIX_HNDL_AND_RETURN_OTHER_PTR( cntr ) \
1122
+ ) \
1123
+
1124
+ // Shrinks vector's capacity to its current size.
1125
+ // Returns a cc_allocing_fn_result_ty containing the new container handle and a pointer that evaluates to true if the
1126
+ // operation was successful and false in the case of allocation failure.
1127
+ static inline cc_allocing_fn_result_ty cc_vec_shrink(
1128
+ void *cntr,
1129
+ size_t el_size,
1130
+ void *( *realloc_ )( void *, size_t ),
1131
+ void ( *free_ )( void * )
1132
+ )
1133
+ {
1134
+ if( cc_vec_size( cntr ) == cc_vec_cap( cntr ) ) // Also handles placeholder.
1135
+ return cc_make_allocing_fn_result( cntr, cc_dummy_true_ptr );
1136
+
1137
+ if( cc_vec_size( cntr ) == 0 )
1138
+ {
1139
+ // Restore placeholder.
1140
+ free_( cntr );
1141
+ return cc_make_allocing_fn_result( (void *)&cc_vec_placeholder, cc_dummy_true_ptr );
1142
+ }
1143
+
1144
+ cc_vec_hdr_ty *new_cntr = (cc_vec_hdr_ty *)realloc_( cntr, sizeof( cc_vec_hdr_ty ) + el_size * cc_vec_size( cntr ) );
1145
+ if( !new_cntr )
1146
+ return cc_make_allocing_fn_result( cntr, NULL );
1147
+
1148
+ cc_vec_hdr( new_cntr )->cap = cc_vec_size( new_cntr );
1149
+ return cc_make_allocing_fn_result( new_cntr, cc_dummy_true_ptr );
1150
+ }
1151
+
1152
+ #define CC_VEC_SHRINK( cntr ) \
1153
+ ( \
1154
+ CC_POINT_HNDL_TO_ALLOCING_FN_RESULT( \
1155
+ cntr, \
1156
+ cc_vec_shrink( cntr, CC_EL_SIZE( cntr ), CC_GET_REALLOC, CC_GET_FREE ) \
1157
+ ), \
1158
+ (bool)CC_FIX_HNDL_AND_RETURN_OTHER_PTR( cntr ) \
1159
+ ) \
1160
+
1161
+ // Initializes a shallow copy of the source vector.
1162
+ // The capacity of the new vector is the size of the source vector, not its capacity.
1163
+ // Returns a the pointer to the copy, or NULL in the case of allocation failure.
1164
+ // That return value is cast to bool in the corresponding macro.
1165
+ static inline void *cc_vec_init_clone( void *src, size_t el_size, void *( *realloc_ )( void *, size_t ) )
1166
+ {
1167
+ if( cc_vec_size( src ) == 0 )
1168
+ return (void *)&cc_vec_placeholder;
1169
+
1170
+ cc_allocing_fn_result_ty result = cc_vec_resize(
1171
+ (void *)&cc_vec_placeholder,
1172
+ cc_vec_size( src ),
1173
+ el_size,
1174
+ NULL, // dtor unused.
1175
+ realloc_
1176
+ );
1177
+
1178
+ if( !result.other_ptr )
1179
+ return NULL;
1180
+
1181
+ memcpy( cc_vec_get( result.new_cntr, 0, el_size ), cc_vec_get( src, 0, el_size ), el_size * cc_vec_size( src ) );
1182
+ return result.new_cntr;
1183
+ }
1184
+
1185
+ #define CC_VEC_INIT_CLONE( cntr, src ) \
1186
+ ( cntr = (CC_TYPEOF_XP( cntr ))cc_vec_init_clone( src, CC_EL_SIZE( cntr ), CC_GET_REALLOC ) ) \
1187
+
1188
+ // Erases all elements, calling the destructors if necessary, without changing the vector's capacity.
1189
+ void cc_vec_clear( void *cntr, size_t el_size, void (*dtor)( void * ) )
1190
+ {
1191
+ cc_vec_erase_n( cntr, 0, cc_vec_size( cntr ), el_size, dtor );
1192
+ }
1193
+
1194
+ #define CC_VEC_CLEAR( cntr ) cc_vec_clear( cntr, CC_EL_SIZE( cntr ), CC_EL_DTOR( cntr ) )
1195
+
1196
+ // Clears the vector and frees its memory if it is not a placeholder.
1197
+ void cc_vec_cleanup( void *cntr, size_t el_size, void (*dtor)( void * ), void (*free_)( void * ) )
1198
+ {
1199
+ cc_vec_clear( cntr, el_size, dtor );
1200
+
1201
+ if( !cc_vec_is_placeholder( cntr ) )
1202
+ free_( cntr );
1203
+ }
1204
+
1205
+ #define CC_VEC_CLEANUP( cntr ) \
1206
+ ( \
1207
+ cc_vec_cleanup( cntr, CC_EL_SIZE( cntr ), CC_EL_DTOR( cntr ), CC_GET_FREE ), \
1208
+ CC_VEC_INIT( cntr ) \
1209
+ ) \
1210
+
1211
+ static inline void *cc_vec_first( void *cntr )
1212
+ {
1213
+ return (char *)cntr + sizeof( cc_vec_hdr_ty );
1214
+ }
1215
+
1216
+ static inline void *cc_vec_last( void *cntr, size_t el_size )
1217
+ {
1218
+ return cc_vec_get( cntr, cc_vec_size( cntr ) - 1, el_size );
1219
+ }
1220
+
1221
+ #define CC_VEC_LAST( cntr ) cc_vec_last( cntr, CC_EL_SIZE( cntr ) )
1222
+
1223
+ static inline void *cc_vec_end( void *cntr, size_t el_size )
1224
+ {
1225
+ return cc_vec_get( cntr, cc_vec_size( cntr ), el_size );
1226
+ }
1227
+
1228
+ #define CC_VEC_END( cntr ) cc_vec_end( cntr, CC_EL_SIZE( cntr ) )
1229
+
1230
+ static inline void *cc_vec_next( void *i, size_t el_size )
1231
+ {
1232
+ return (char *)i + el_size;
1233
+ }
1234
+
1235
+ #define CC_VEC_NEXT( cntr, i ) cc_vec_next( i, CC_EL_SIZE( cntr ) )
1236
+
1237
+ /*--------------------------------------------------------------------------------------------------------------------*/
1238
+ /* List */
1239
+ /*--------------------------------------------------------------------------------------------------------------------*/
1240
+
1241
+ // List is implemented a doubly linked list with sentinel nodes.
1242
+
1243
+ // Node header.
1244
+ // It does not need to be aligned to alignof( max_align_t ) because no memory is allocated after the header.
1245
+ typedef struct cc_listnode_hdr_ty
1246
+ {
1247
+ alignas( max_align_t )
1248
+ struct cc_listnode_hdr_ty *prev;
1249
+ struct cc_listnode_hdr_ty *next;
1250
+ } cc_listnode_hdr_ty;
1251
+
1252
+ // List header.
1253
+ typedef struct
1254
+ {
1255
+ size_t size;
1256
+ cc_listnode_hdr_ty r_end;
1257
+ cc_listnode_hdr_ty end;
1258
+ } cc_list_hdr_ty;
1259
+
1260
+ // Placeholder for list with no allocated header.
1261
+ // The main purpose this serves is to provide every list with stable r_end and end iterators across translation units
1262
+ // and irrespective of whether any memory has been allocated for its header.
1263
+ // Every list initially (after cc_init) points to this placeholder, which differs across translation units, and is then
1264
+ // associated with that placeholder until cc_cleanup is called.
1265
+ // Calls to cc_r_end and cc_end on a list return pointers to the associated placeholder's r_end and end elements even
1266
+ // after a header has been dynamically allocated to it.
1267
+ // The way this works is that the placeholder's r_end.prev pointer points to the placeholder's r_end (i.e. a circular
1268
+ // link), and ditto for end.next.
1269
+ // Meanwhile, a list with an allocated header has it's r_end.prev pointer point to the placeholder's r_end, and ditto
1270
+ // for it's end.next pointer.
1271
+ // Therefore cc_list_hdr( cntr )->r_end.prev always produces the associated placeholder's r_end, and ditto for
1272
+ // cc_list_hdr( cntr )->end.next.
1273
+ // Unfortunately, this means that r_end and end must be handled as special cases during inserts, splices, and iteration.
1274
+ const static cc_list_hdr_ty cc_list_placeholder = {
1275
+ 0,
1276
+ {
1277
+ (cc_listnode_hdr_ty *)&cc_list_placeholder.r_end /* Circular link */,
1278
+ (cc_listnode_hdr_ty *)&cc_list_placeholder.end
1279
+ },
1280
+ {
1281
+ (cc_listnode_hdr_ty *)&cc_list_placeholder.r_end,
1282
+ (cc_listnode_hdr_ty *)&cc_list_placeholder.end /* Circular link */
1283
+ }
1284
+ };
1285
+
1286
+ #define CC_LIST_INIT( cntr ) \
1287
+ ( \
1288
+ cntr = (CC_TYPEOF_XP( cntr ))&cc_list_placeholder, \
1289
+ (void)0 \
1290
+ ) \
1291
+
1292
+ // Provides easy access to list header.
1293
+ static inline cc_list_hdr_ty *cc_list_hdr( void *cntr )
1294
+ {
1295
+ return (cc_list_hdr_ty *)cntr;
1296
+ }
1297
+
1298
+ // Provides easy access to a list node header from a pointer-iterator.
1299
+ static inline cc_listnode_hdr_ty *cc_listnode_hdr( void *i )
1300
+ {
1301
+ return (cc_listnode_hdr_ty *)( (char *)i - sizeof( cc_listnode_hdr_ty ) );
1302
+ }
1303
+
1304
+ // Provides easy access to a pointer-iterator from pointer to a list node header.
1305
+ static inline void *cc_list_el( void *i )
1306
+ {
1307
+ return (char *)i + sizeof( cc_listnode_hdr_ty );
1308
+ }
1309
+
1310
+ static inline bool cc_list_is_placeholder( void *cntr )
1311
+ {
1312
+ return cc_list_hdr( cntr )->r_end.prev == &cc_list_hdr( cntr )->r_end;
1313
+ }
1314
+
1315
+ // Iteration.
1316
+
1317
+ static inline void *cc_list_r_end( void *cntr )
1318
+ {
1319
+ return cc_list_el( cc_list_hdr( cntr )->r_end.prev );
1320
+ }
1321
+
1322
+ static inline void *cc_list_end( void *cntr )
1323
+ {
1324
+ return cc_list_el( cc_list_hdr( cntr )->end.next );
1325
+ }
1326
+
1327
+ static inline void *cc_list_prev( void *cntr, void *i )
1328
+ {
1329
+ cc_listnode_hdr_ty *prev = cc_listnode_hdr( i )->prev;
1330
+
1331
+ // If i is r_end, then we need to decrement the iterator once more to ensure that the returned iterator is the r_end
1332
+ // of the placeholder originally associated with the list.
1333
+ if( prev == &cc_list_hdr( cntr )->r_end )
1334
+ prev = prev->prev;
1335
+
1336
+ return cc_list_el( prev );
1337
+ }
1338
+
1339
+ static inline void *cc_list_next( void *cntr, void *i )
1340
+ {
1341
+ cc_listnode_hdr_ty *next = cc_listnode_hdr( i )->next;
1342
+
1343
+ // See comment in cc_list_prev above.
1344
+ if( next == &cc_list_hdr( cntr )->end )
1345
+ next = next->next;
1346
+
1347
+ return cc_list_el( next );
1348
+ }
1349
+
1350
+ static inline void *cc_list_first( void *cntr )
1351
+ {
1352
+ return cc_list_next( cntr, cc_list_el( &cc_list_hdr( cntr )->r_end ) );
1353
+ }
1354
+
1355
+ static inline void *cc_list_last( void *cntr )
1356
+ {
1357
+ return cc_list_prev( cntr, cc_list_el( &cc_list_hdr( cntr )->end ) );
1358
+ }
1359
+
1360
+ static inline size_t cc_list_size( void *cntr )
1361
+ {
1362
+ return cc_list_hdr( cntr )->size;
1363
+ }
1364
+
1365
+ // Allocates a header for a list that is currently a placeholder.
1366
+ // Returns the new container handle, or NULL in the case of allocation failure.
1367
+ static inline void *cc_list_alloc_hdr( void *cntr, void *( *realloc_ )( void *, size_t ) )
1368
+ {
1369
+ cc_list_hdr_ty *new_cntr = (cc_list_hdr_ty *)realloc_( NULL, sizeof( cc_list_hdr_ty ) );
1370
+ if( !new_cntr )
1371
+ return NULL;
1372
+
1373
+ new_cntr->r_end.next = &new_cntr->end;
1374
+ new_cntr->end.prev = &new_cntr->r_end;
1375
+
1376
+ // Link the new header's r_end and end with the original placeholder's r_end and end.
1377
+ new_cntr->r_end.prev = &cc_list_hdr( cntr )->r_end;
1378
+ new_cntr->end.next = &cc_list_hdr( cntr )->end;
1379
+
1380
+ new_cntr->size = 0;
1381
+ return new_cntr;
1382
+ }
1383
+
1384
+ // Attaches a node to the list before the node pointed to be pointer-iterator i.
1385
+ static inline void cc_list_attach( void *cntr, void *i, cc_listnode_hdr_ty *node )
1386
+ {
1387
+ // Handle r_end and end iterators as a special case.
1388
+ // We need to convert the iterator from the global placeholder's r_end or end to the local r_end or end.
1389
+ if( i == cc_list_r_end( cntr ) )
1390
+ i = cc_list_el( &cc_list_hdr( cntr )->r_end );
1391
+ else if( i == cc_list_end( cntr ) )
1392
+ i = cc_list_el( &cc_list_hdr( cntr )->end );
1393
+
1394
+ // Link node.
1395
+ node->next = cc_listnode_hdr( i );
1396
+ node->prev = node->next->prev;
1397
+ node->next->prev = node;
1398
+ node->prev->next = node;
1399
+ }
1400
+
1401
+ // Inserts an element into the list before before the node pointed to be pointer-iterator i.
1402
+ // Returns a cc_allocing_fn_result_ty containing the new container handle and a pointer-iterator to the newly inserted
1403
+ // element (or NULL in the case of allocation failure).
1404
+ static inline cc_allocing_fn_result_ty cc_list_insert(
1405
+ void *cntr,
1406
+ void *i,
1407
+ void *el,
1408
+ size_t el_size,
1409
+ void *( *realloc_ )( void *, size_t )
1410
+ )
1411
+ {
1412
+ if( cc_list_is_placeholder( cntr ) )
1413
+ {
1414
+ void *new_cntr = cc_list_alloc_hdr( cntr, realloc_ );
1415
+ if( !new_cntr )
1416
+ return cc_make_allocing_fn_result( cntr, NULL );
1417
+
1418
+ cntr = new_cntr;
1419
+ }
1420
+
1421
+ cc_listnode_hdr_ty *new_node = (cc_listnode_hdr_ty *)realloc_( NULL, sizeof( cc_listnode_hdr_ty ) + el_size );
1422
+ if( !new_node )
1423
+ return cc_make_allocing_fn_result( cntr, NULL );
1424
+
1425
+ memcpy( cc_list_el( new_node ), el, el_size );
1426
+
1427
+ // Handle r_end and end iterators as a special case.
1428
+ // We need to convert the iterator from the associated placeholder's r_end or end to the local r_end or end.
1429
+ if( i == cc_list_r_end( cntr ) )
1430
+ i = cc_list_el( &cc_list_hdr( cntr )->r_end );
1431
+ else if( i == cc_list_end( cntr ) )
1432
+ i = cc_list_el( &cc_list_hdr( cntr )->end );
1433
+
1434
+ cc_list_attach( cntr, i, new_node );
1435
+
1436
+ ++cc_list_hdr( cntr )->size;
1437
+
1438
+ return cc_make_allocing_fn_result( cntr, cc_list_el( new_node ) );
1439
+ }
1440
+
1441
+ #define CC_LIST_INSERT( cntr, i, el ) \
1442
+ ( \
1443
+ CC_POINT_HNDL_TO_ALLOCING_FN_RESULT( \
1444
+ cntr, \
1445
+ cc_list_insert( cntr, i, &CC_MAKE_LVAL_COPY( CC_EL_TY( cntr ), el ), CC_EL_SIZE( cntr ), CC_GET_REALLOC ) \
1446
+ ), \
1447
+ CC_FIX_HNDL_AND_RETURN_OTHER_PTR( cntr ) \
1448
+ ) \
1449
+
1450
+ #define CC_LIST_PUSH( cntr, el ) CC_LIST_INSERT( cntr, cc_list_end( cntr ), el )
1451
+
1452
+ // Erases the element pointed to by pointer-iterator i and returns a pointer-iterator to next element (or end if the
1453
+ // element was the last element in the list.)
1454
+ static inline void *cc_list_erase( void *cntr, void *i, void ( *dtor )( void * ), void ( *free_ )( void * ) )
1455
+ {
1456
+ cc_listnode_hdr_ty *hdr = cc_listnode_hdr( i );
1457
+ cc_listnode_hdr_ty *next = hdr->next;
1458
+ hdr->prev->next = next;
1459
+ next->prev = hdr->prev;
1460
+
1461
+ if( dtor )
1462
+ dtor( i );
1463
+
1464
+ free_( hdr );
1465
+ --cc_list_hdr( cntr )->size;
1466
+
1467
+ // If next is end, we need to make sure we're returning the associated placeholder's end.
1468
+ if( next == &cc_list_hdr( cntr )->end )
1469
+ next = next->next;
1470
+
1471
+ return cc_list_el( next );
1472
+ }
1473
+
1474
+ #define CC_LIST_ERASE( cntr, i ) cc_list_erase( cntr, i, CC_EL_DTOR( cntr ), CC_GET_FREE )
1475
+
1476
+ // Removes the element pointed to by pointer-iterator src_i from the source list and attaches it to the list.
1477
+ // Although this function never allocates memory for the element/node itself, it must allocate the list's header if the
1478
+ // list is currently a placeholder.
1479
+ // Returns a cc_allocing_fn_result_ty containing the new container handle and a pointer that evaluates to true if the
1480
+ // operation was successful or false in the case of allocation failure.
1481
+ static inline cc_allocing_fn_result_ty cc_list_splice(
1482
+ void *cntr,
1483
+ void *i,
1484
+ void *src,
1485
+ void *src_i,
1486
+ void *( *realloc_ )( void *, size_t )
1487
+ )
1488
+ {
1489
+ if( cc_list_is_placeholder( cntr ) )
1490
+ {
1491
+ void *new_cntr = cc_list_alloc_hdr( cntr, realloc_ );
1492
+ if( !new_cntr )
1493
+ return cc_make_allocing_fn_result( cntr, NULL );
1494
+
1495
+ cntr = new_cntr;
1496
+ }
1497
+
1498
+ cc_listnode_hdr( src_i )->prev->next = cc_listnode_hdr( src_i )->next;
1499
+ cc_listnode_hdr( src_i )->next->prev = cc_listnode_hdr( src_i )->prev;
1500
+ cc_list_attach( cntr, i, cc_listnode_hdr( src_i ) );
1501
+
1502
+ --cc_list_hdr( src )->size;
1503
+ ++cc_list_hdr( cntr )->size;
1504
+
1505
+ return cc_make_allocing_fn_result( cntr, cc_dummy_true_ptr );
1506
+ }
1507
+
1508
+ #define CC_LIST_SPLICE( cntr, i, src, src_i ) \
1509
+ ( \
1510
+ CC_POINT_HNDL_TO_ALLOCING_FN_RESULT( \
1511
+ cntr, \
1512
+ cc_list_splice( cntr, i, src, src_i, CC_GET_REALLOC ) \
1513
+ ), \
1514
+ CC_FIX_HNDL_AND_RETURN_OTHER_PTR( cntr ) \
1515
+ ) \
1516
+
1517
+ // Initializes a shallow copy of the source list.
1518
+ // This requires allocating memory for every node, as well as for the list's header unless src is a placeholder.
1519
+ // Returns a the pointer to the copy, or NULL in the case of allocation failure.
1520
+ // That return value is cast to bool in the corresponding macro.
1521
+ static inline void *cc_list_init_clone(
1522
+ void *src,
1523
+ size_t el_size,
1524
+ void *( *realloc_ )( void *, size_t ),
1525
+ void ( *free_ )( void * )
1526
+ )
1527
+ {
1528
+ cc_allocing_fn_result_ty result = { (void *)&cc_list_placeholder, cc_dummy_true_ptr };
1529
+ for( void *i = cc_list_first( src ); i != cc_list_end( src ); i = cc_list_next( src, i ) )
1530
+ {
1531
+ result = cc_list_insert( result.new_cntr, cc_list_end( result.new_cntr ), i, el_size, realloc_ );
1532
+ if( !result.other_ptr )
1533
+ {
1534
+ // Erase incomplete clone without invoking destructors.
1535
+
1536
+ void *j = cc_list_first( result.new_cntr );
1537
+ while( j != cc_list_end( result.new_cntr ) )
1538
+ {
1539
+ void *next = cc_list_next( result.new_cntr, j );
1540
+ free_( cc_listnode_hdr( j ) );
1541
+ j = next;
1542
+ }
1543
+
1544
+ if( !cc_list_is_placeholder( result.new_cntr ) )
1545
+ free_( result.new_cntr );
1546
+
1547
+ return NULL;
1548
+ }
1549
+ }
1550
+
1551
+ return result.new_cntr;
1552
+ }
1553
+
1554
+ #define CC_LIST_INIT_CLONE( cntr, src ) \
1555
+ ( cntr = (CC_TYPEOF_XP( cntr ))cc_list_init_clone( src, CC_EL_SIZE( cntr ), CC_GET_REALLOC, CC_GET_FREE ) ) \
1556
+
1557
+ // Erases all elements, calling their destructors if necessary.
1558
+ static inline void cc_list_clear( void *cntr, void ( *dtor )( void * ), void ( *free_ )( void * ) )
1559
+ {
1560
+ while( cc_list_first( cntr ) != cc_list_end( cntr ) )
1561
+ cc_list_erase( cntr, cc_list_first( cntr ), dtor, free_ );
1562
+ }
1563
+
1564
+ #define CC_LIST_CLEAR( cntr ) cc_list_clear( cntr, CC_EL_DTOR( cntr ), CC_GET_FREE )
1565
+
1566
+ // Erases all elements, calling their destructors if necessary, and frees memory for the list's header if it is not
1567
+ // a placeholder.
1568
+ static inline void cc_list_cleanup( void *cntr, void ( *dtor )( void * ), void ( *free_ )( void * ) )
1569
+ {
1570
+ cc_list_clear( cntr, dtor, free_ );
1571
+ if( !cc_list_is_placeholder( cntr ) )
1572
+ free_( cntr );
1573
+ }
1574
+
1575
+ #define CC_LIST_CLEANUP( cntr ) \
1576
+ ( \
1577
+ cc_list_cleanup( cntr, CC_EL_DTOR( cntr ), CC_GET_FREE ), \
1578
+ CC_LIST_INIT( cntr ) \
1579
+ ) \
1580
+
1581
+ /*--------------------------------------------------------------------------------------------------------------------*/
1582
+ /* Map */
1583
+ /*--------------------------------------------------------------------------------------------------------------------*/
1584
+
1585
+ // Map is implemented as a Robin Hood (open-addressing) hash table with a power-of-2 capacity.
1586
+
1587
+ // Probe length type.
1588
+ // An unsigned char would probably be fine, but we use unsigned int just in case.
1589
+ // A probe length of 0 denotes an empty bucket, whereas a probe length of 1 denotes an element in its home bucket.
1590
+ // This optimization allows us to eliminate separate checks for empty buckets.
1591
+ typedef unsigned int cc_probelen_ty;
1592
+
1593
+ // Macros for calculating the position of element and probe length inside a bucket, as well as bucket size.
1594
+ // The element is at the beginning of bucket.
1595
+
1596
+ #define CC_MAP_KEY_OFFSET( cntr ) CC_ROUND_UP( CC_EL_SIZE( cntr ), alignof( CC_KEY_TY( cntr ) ) )
1597
+
1598
+ #define CC_MAP_PROBELEN_OFFSET( cntr ) \
1599
+ CC_ROUND_UP( CC_MAP_KEY_OFFSET( cntr ) + CC_KEY_SIZE( cntr ), alignof( cc_probelen_ty ) ) \
1600
+
1601
+ #define CC_MAP_BUCKET_SIZE( cntr ) \
1602
+ CC_ROUND_UP( \
1603
+ CC_MAP_PROBELEN_OFFSET( cntr ) + sizeof( cc_probelen_ty ), \
1604
+ alignof( CC_KEY_TY( cntr ) ) > alignof( CC_EL_TY( cntr ) ) ? \
1605
+ alignof( CC_KEY_TY( cntr ) ) \
1606
+ : \
1607
+ alignof( CC_EL_TY( cntr ) ) \
1608
+ ) \
1609
+
1610
+ // Map header.
1611
+ typedef struct
1612
+ {
1613
+ alignas( max_align_t )
1614
+ size_t size;
1615
+ size_t cap;
1616
+ } cc_map_hdr_ty;
1617
+
1618
+ // Placeholder for map with no allocated memory.
1619
+ // In the case of maps, this placeholder allows us to avoid checking for a NULL handle inside functions.
1620
+ static const cc_map_hdr_ty cc_map_placeholder = { 0, 0 };
1621
+
1622
+ #define CC_MAP_INIT( cntr ) \
1623
+ ( \
1624
+ cntr = (CC_TYPEOF_XP( cntr ))&cc_map_placeholder, \
1625
+ (void)0 \
1626
+ ) \
1627
+
1628
+ // Provides easy access to map header.
1629
+ static inline cc_map_hdr_ty *cc_map_hdr( void *cntr )
1630
+ {
1631
+ return (cc_map_hdr_ty *)cntr;
1632
+ }
1633
+
1634
+ // Functions for easily accessing element, key, and probe length for the bucket at index i.
1635
+ // The element pointer also denotes the beginning of the bucket.
1636
+
1637
+ static inline void *cc_map_el( void *cntr, size_t i, size_t bucket_size )
1638
+ {
1639
+ return (char *)cntr + sizeof( cc_map_hdr_ty ) + bucket_size * i;
1640
+ }
1641
+
1642
+ static inline void *cc_map_key( void *cntr, size_t i, size_t bucket_size, size_t key_offset )
1643
+ {
1644
+ return (char *)cc_map_el( cntr, i, bucket_size ) + key_offset;
1645
+ }
1646
+
1647
+ static inline cc_probelen_ty *cc_map_probelen( void *cntr, size_t i, size_t bucket_size, size_t probelen_offset )
1648
+ {
1649
+ return (cc_probelen_ty *)( (char *)cc_map_el( cntr, i, bucket_size ) + probelen_offset );
1650
+ }
1651
+
1652
+ static inline size_t cc_map_size( void *cntr )
1653
+ {
1654
+ return cc_map_hdr( cntr )->size;
1655
+ }
1656
+
1657
+ static inline size_t cc_map_cap( void *cntr )
1658
+ {
1659
+ return cc_map_hdr( cntr )->cap;
1660
+ }
1661
+
1662
+ static inline bool cc_map_is_placeholder( void *cntr )
1663
+ {
1664
+ return cc_map_cap( cntr ) == 0;
1665
+ }
1666
+
1667
+ // Inserts an element into the map.
1668
+ // Assumes that the map has empty slots and therefore that failure cannot occur (hence the "raw" label).
1669
+ // If replace is true, then el will replace any existing element with the same key.
1670
+ // Returns a pointer-iterator to the newly inserted element, or to the existing element with the same key if replace is
1671
+ // false.
1672
+ // For the exact mechanics of Robin-Hood hashing, see Sebastian Sylvan's helpful article:
1673
+ // www.sebastiansylvan.com/post/robin-hood-hashing-should-be-your-default-hash-table-implementation
1674
+ static inline void *cc_map_insert_raw(
1675
+ void *cntr,
1676
+ void *el,
1677
+ void *key,
1678
+ bool replace,
1679
+ size_t bucket_size,
1680
+ size_t el_size,
1681
+ size_t key_offset,
1682
+ size_t key_size,
1683
+ size_t probelen_offset,
1684
+ int ( *cmpr )( void *, void *),
1685
+ size_t ( *hash )( void *),
1686
+ void ( *key_dtor )( void * ),
1687
+ void ( *el_dtor )( void * )
1688
+ )
1689
+ {
1690
+ size_t i = hash( key ) & ( cc_map_hdr( cntr )->cap - 1 );
1691
+ cc_probelen_ty probelen = 1;
1692
+ void *placed_original_el = NULL;
1693
+
1694
+ while( true )
1695
+ {
1696
+ // Empty bucket.
1697
+ if( !*cc_map_probelen( cntr, i, bucket_size, probelen_offset ) )
1698
+ {
1699
+ memcpy( cc_map_key( cntr, i, bucket_size, key_offset ), key, key_size );
1700
+ memcpy( cc_map_el( cntr, i, bucket_size ), el, el_size );
1701
+
1702
+ *cc_map_probelen( cntr, i, bucket_size, probelen_offset ) = probelen;
1703
+
1704
+ ++cc_map_hdr( cntr )->size;
1705
+
1706
+ return placed_original_el ? placed_original_el : cc_map_el( cntr, i, bucket_size );
1707
+ }
1708
+
1709
+ // Existing element with same key.
1710
+ // This case can only occur before any steal occurs.
1711
+ if(
1712
+ probelen == *cc_map_probelen( cntr, i, bucket_size, probelen_offset ) &&
1713
+ cmpr( cc_map_key( cntr, i, bucket_size, key_offset ), key ) == 0
1714
+ )
1715
+ {
1716
+ if( replace )
1717
+ {
1718
+ if( key_dtor )
1719
+ key_dtor( cc_map_key( cntr, i, bucket_size, key_offset ) );
1720
+
1721
+ if( el_dtor )
1722
+ el_dtor( cc_map_el( cntr, i, bucket_size ) );
1723
+
1724
+ memcpy( cc_map_key( cntr, i, bucket_size, key_offset ), key, key_size );
1725
+ memcpy( cc_map_el( cntr, i, bucket_size ), el, el_size );
1726
+ }
1727
+
1728
+ return cc_map_el( cntr, i, bucket_size );
1729
+ }
1730
+
1731
+ // Stealing bucket.
1732
+ if( probelen > *cc_map_probelen( cntr, i, bucket_size, probelen_offset ) )
1733
+ {
1734
+ cc_memswap( key, cc_map_key( cntr, i, bucket_size, key_offset ), key_size );
1735
+ cc_memswap( el, cc_map_el( cntr, i, bucket_size ), el_size );
1736
+
1737
+ cc_probelen_ty temp_probelen = *cc_map_probelen( cntr, i, bucket_size, probelen_offset );
1738
+ *cc_map_probelen( cntr, i, bucket_size, probelen_offset ) = probelen;
1739
+ probelen = temp_probelen;
1740
+
1741
+ if( !placed_original_el )
1742
+ placed_original_el = cc_map_el( cntr, i, bucket_size );
1743
+ }
1744
+
1745
+ i = ( i + 1 ) & ( cc_map_hdr( cntr )->cap - 1 );
1746
+ ++probelen;
1747
+ }
1748
+ }
1749
+
1750
+ // Returns the minimum capacity required to accommodate n elements, which is governed by the max load factor associated
1751
+ // with the map's key type.
1752
+ static inline size_t cc_map_min_cap_for_n_els( size_t n, double max_load )
1753
+ {
1754
+ if( n == 0 )
1755
+ return 0;
1756
+
1757
+ // Round up to power of 2.
1758
+ size_t cap = 8;
1759
+ while( n > cap * max_load )
1760
+ cap *= 2;
1761
+
1762
+ return cap;
1763
+ }
1764
+
1765
+ // Creates a rehashed duplicate of cntr with capacity cap.
1766
+ // Assumes that cap is large enough to accommodate all elements in cntr without violating the max load factor.
1767
+ // Returns pointer to the duplicate, or NULL in the case of allocation failure.
1768
+ static inline void *cc_map_make_rehash(
1769
+ void *cntr,
1770
+ size_t cap,
1771
+ size_t bucket_size,
1772
+ size_t el_size,
1773
+ size_t key_offset,
1774
+ size_t key_size,
1775
+ size_t probelen_offset,
1776
+ int ( *cmpr )( void *, void * ),
1777
+ size_t ( *hash )( void * ),
1778
+ void *( *realloc_ )( void *, size_t )
1779
+ )
1780
+ {
1781
+ cc_map_hdr_ty *new_cntr = (cc_map_hdr_ty *)realloc_( NULL, sizeof( cc_map_hdr_ty ) + bucket_size * cap );
1782
+ if( !new_cntr )
1783
+ return NULL;
1784
+
1785
+ new_cntr->size = 0;
1786
+ new_cntr->cap = cap;
1787
+ for( size_t i = 0; i < cap; ++i )
1788
+ *cc_map_probelen( new_cntr, i, bucket_size, probelen_offset ) = 0;
1789
+
1790
+ for( size_t i = 0; i < cc_map_hdr( cntr )->cap; ++i )
1791
+ if( *cc_map_probelen( cntr, i, bucket_size, probelen_offset ) )
1792
+ cc_map_insert_raw(
1793
+ new_cntr,
1794
+ cc_map_el( cntr, i, bucket_size ),
1795
+ cc_map_key( cntr, i, bucket_size, key_offset ),
1796
+ false, // No replacements can occur anyway as all keys already in the map are unique.
1797
+ bucket_size,
1798
+ el_size,
1799
+ key_offset,
1800
+ key_size,
1801
+ probelen_offset,
1802
+ cmpr,
1803
+ hash,
1804
+ // No need to pass destructors as no elements will be erased.
1805
+ NULL,
1806
+ NULL
1807
+ );
1808
+
1809
+ return new_cntr;
1810
+ }
1811
+
1812
+ // Reserves capacity such that the map can accommodate n elements without reallocation (i.e. without violating the
1813
+ // max load factor).
1814
+ // Returns a cc_allocing_fn_result_ty containing new container handle and a pointer that evaluates to true if the
1815
+ // operation successful or false in the case of allocation failure.
1816
+ static inline cc_allocing_fn_result_ty cc_map_reserve(
1817
+ void *cntr,
1818
+ size_t n,
1819
+ size_t bucket_size,
1820
+ size_t el_size,
1821
+ size_t key_offset,
1822
+ size_t key_size,
1823
+ size_t probelen_offset,
1824
+ int ( *cmpr )( void *, void * ),
1825
+ size_t ( *hash )( void * ),
1826
+ double max_load,
1827
+ void *( *realloc_ )( void *, size_t ),
1828
+ void ( *free_ )( void * )
1829
+ )
1830
+ {
1831
+ size_t cap = cc_map_min_cap_for_n_els( n, max_load );
1832
+
1833
+ if( cc_map_cap( cntr ) >= cap )
1834
+ return cc_make_allocing_fn_result( cntr, cc_dummy_true_ptr );
1835
+
1836
+ void *new_cntr = cc_map_make_rehash(
1837
+ cntr,
1838
+ cap,
1839
+ bucket_size,
1840
+ el_size,
1841
+ key_offset,
1842
+ key_size,
1843
+ probelen_offset,
1844
+ cmpr,
1845
+ hash,
1846
+ realloc_
1847
+ );
1848
+ if( !new_cntr )
1849
+ return cc_make_allocing_fn_result( cntr, NULL );
1850
+
1851
+ if( !cc_map_is_placeholder( cntr ) )
1852
+ free_( cntr );
1853
+
1854
+ return cc_make_allocing_fn_result( new_cntr, cc_dummy_true_ptr );
1855
+ }
1856
+
1857
+ #define CC_MAP_RESERVE( cntr, n ) \
1858
+ ( \
1859
+ CC_POINT_HNDL_TO_ALLOCING_FN_RESULT( \
1860
+ cntr, \
1861
+ cc_map_reserve( \
1862
+ cntr, \
1863
+ n, \
1864
+ CC_MAP_BUCKET_SIZE( cntr ), \
1865
+ CC_EL_SIZE( cntr ), \
1866
+ CC_MAP_KEY_OFFSET( cntr ), \
1867
+ CC_KEY_SIZE( cntr ), \
1868
+ CC_MAP_PROBELEN_OFFSET( cntr ), \
1869
+ CC_KEY_CMPR( cntr ), \
1870
+ CC_KEY_HASH( cntr ), \
1871
+ CC_KEY_LOAD( cntr ), \
1872
+ CC_GET_REALLOC, \
1873
+ CC_GET_FREE \
1874
+ ) \
1875
+ ), \
1876
+ (bool)CC_FIX_HNDL_AND_RETURN_OTHER_PTR( cntr ) \
1877
+ ) \
1878
+
1879
+ // Inserts an element.
1880
+ // If replace is true, then el replaces any existing element with the same key.
1881
+ // If the map exceeds its load factor, the underlying storage is expanded and a complete rehash occurs.
1882
+ // Returns a cc_allocing_fn_result_ty containing the new container handle and a pointer to the newly inserted element, or
1883
+ // to the existing element with the same key if replace is false.
1884
+ // If the underlying storage needed to be expanded and an allocation failure occurred, the latter pointer will be NULL.
1885
+ // This function checks to ensure that the map could accommodate an insertion before searching for the existing element.
1886
+ // Therefore, failure can occur even if an element with the same key already exists and no reallocation was actually
1887
+ // necessary.
1888
+ // This was a design choice in favor of code simplicity and readability over ideal behavior in a corner case.
1889
+ static inline cc_allocing_fn_result_ty cc_map_insert(
1890
+ void *cntr,
1891
+ void *el,
1892
+ void *key,
1893
+ bool replace,
1894
+ size_t bucket_size,
1895
+ size_t el_size,
1896
+ size_t key_offset,
1897
+ size_t key_size,
1898
+ size_t probelen_offset,
1899
+ int (*cmpr)( void *, void * ),
1900
+ size_t (*hash)( void * ),
1901
+ double max_load,
1902
+ void ( *key_dtor )( void * ),
1903
+ void ( *el_dtor )( void * ),
1904
+ void *( *realloc_ )( void *, size_t ),
1905
+ void ( *free_ )( void * )
1906
+ )
1907
+ {
1908
+ if( cc_map_size( cntr ) + 1 > cc_map_cap( cntr ) * max_load )
1909
+ {
1910
+ cc_allocing_fn_result_ty result = cc_map_reserve(
1911
+ cntr,
1912
+ cc_map_size( cntr ) + 1,
1913
+ bucket_size,
1914
+ el_size,
1915
+ key_offset,
1916
+ key_size,
1917
+ probelen_offset,
1918
+ cmpr,
1919
+ hash,
1920
+ max_load,
1921
+ realloc_,
1922
+ free_
1923
+ );
1924
+
1925
+ if( !result.other_ptr )
1926
+ return result;
1927
+
1928
+ cntr = result.new_cntr;
1929
+ }
1930
+
1931
+ void *new_el = cc_map_insert_raw(
1932
+ cntr,
1933
+ el,
1934
+ key,
1935
+ replace,
1936
+ bucket_size,
1937
+ el_size,
1938
+ key_offset,
1939
+ key_size,
1940
+ probelen_offset,
1941
+ cmpr,
1942
+ hash,
1943
+ key_dtor,
1944
+ el_dtor
1945
+ );
1946
+
1947
+ return cc_make_allocing_fn_result( cntr, new_el );
1948
+ }
1949
+
1950
+ #define CC_MAP_INSERT( cntr, key, el, replace ) \
1951
+ ( \
1952
+ CC_POINT_HNDL_TO_ALLOCING_FN_RESULT( \
1953
+ cntr, \
1954
+ cc_map_insert( \
1955
+ cntr, \
1956
+ &CC_MAKE_LVAL_COPY( CC_EL_TY( cntr ), el ), \
1957
+ &CC_MAKE_LVAL_COPY( CC_KEY_TY( cntr ), key ), \
1958
+ replace, \
1959
+ CC_MAP_BUCKET_SIZE( cntr ), \
1960
+ CC_EL_SIZE( cntr ), \
1961
+ CC_MAP_KEY_OFFSET( cntr ), \
1962
+ CC_KEY_SIZE( cntr ), \
1963
+ CC_MAP_PROBELEN_OFFSET( cntr ), \
1964
+ CC_KEY_CMPR( cntr ), \
1965
+ CC_KEY_HASH( cntr ), \
1966
+ CC_KEY_LOAD( cntr ), \
1967
+ CC_KEY_DTOR( cntr ), \
1968
+ CC_EL_DTOR( cntr ), \
1969
+ CC_GET_REALLOC, \
1970
+ CC_GET_FREE \
1971
+ ) \
1972
+ ), \
1973
+ CC_FIX_HNDL_AND_RETURN_OTHER_PTR( cntr ) \
1974
+ ) \
1975
+
1976
+ // Returns a pointer-iterator to the element with the specified key, or NULL if no such element exists.
1977
+ static inline void *cc_map_get(
1978
+ void *cntr,
1979
+ void *key,
1980
+ size_t bucket_size,
1981
+ size_t key_offset,
1982
+ size_t probelen_offset,
1983
+ int (*cmpr)( void *, void *),
1984
+ size_t (*hash)( void *) )
1985
+ {
1986
+ if( cc_map_size( cntr ) == 0 )
1987
+ return NULL;
1988
+
1989
+ size_t i = hash( key ) & ( cc_map_hdr( cntr )->cap - 1 );
1990
+ cc_probelen_ty probelen = 1;
1991
+
1992
+ while( probelen <= *cc_map_probelen( cntr, i, bucket_size, probelen_offset ) )
1993
+ {
1994
+ if(
1995
+ probelen == *cc_map_probelen( cntr, i, bucket_size, probelen_offset ) &&
1996
+ cmpr( cc_map_key( cntr, i, bucket_size, key_offset ), key ) == 0
1997
+ )
1998
+ return cc_map_el( cntr, i, bucket_size );
1999
+
2000
+ i = ( i + 1 ) & ( cc_map_hdr( cntr )->cap - 1 );
2001
+ ++probelen;
2002
+ }
2003
+
2004
+ return NULL;
2005
+ }
2006
+
2007
+ #define CC_MAP_GET( cntr, key ) \
2008
+ cc_map_get( \
2009
+ cntr, \
2010
+ &CC_MAKE_LVAL_COPY( CC_KEY_TY( cntr ), key ), \
2011
+ CC_MAP_BUCKET_SIZE( cntr ), \
2012
+ CC_MAP_KEY_OFFSET( cntr ), \
2013
+ CC_MAP_PROBELEN_OFFSET( cntr ), \
2014
+ CC_KEY_CMPR( cntr ), \
2015
+ CC_KEY_HASH( cntr ) \
2016
+ ) \
2017
+
2018
+ // Returns a pointer to the key for the element pointed to by pointer-iterator i.
2019
+ static inline void *cc_map_key_for( void *i, size_t key_offset )
2020
+ {
2021
+ return (char *)i + key_offset;
2022
+ }
2023
+
2024
+ #define CC_MAP_KEY_FOR( cntr, i ) cc_map_key_for( i, CC_MAP_KEY_OFFSET( cntr ) )
2025
+
2026
+ // Erases the element pointer to by pointer-iterator itr.
2027
+ // For the exact mechanics of erasing elements in a Robin-Hood hash table, see Sebastian Sylvan's:
2028
+ // www.sebastiansylvan.com/post/more-on-robin-hood-hashing-2/
2029
+ static inline void cc_map_erase_itr(
2030
+ void *cntr,
2031
+ void *itr,
2032
+ size_t bucket_size,
2033
+ size_t el_size,
2034
+ size_t key_offset,
2035
+ size_t key_size,
2036
+ size_t probelen_offset,
2037
+ void ( *key_dtor )( void * ),
2038
+ void ( *el_dtor )( void * )
2039
+ )
2040
+ {
2041
+ size_t i = ( (char *)itr - (char *)cc_map_el( cntr, 0, bucket_size ) ) / bucket_size;
2042
+ *cc_map_probelen( cntr, i, bucket_size, probelen_offset ) = 0;
2043
+ --cc_map_hdr( cntr )->size;
2044
+
2045
+ if( key_dtor )
2046
+ key_dtor( cc_map_key( cntr, i, bucket_size, key_offset ) );
2047
+
2048
+ if( el_dtor )
2049
+ el_dtor( cc_map_el( cntr, i, bucket_size ) );
2050
+
2051
+ while( true )
2052
+ {
2053
+ size_t next = ( i + 1 ) & ( cc_map_hdr( cntr )->cap - 1 );
2054
+ if( *cc_map_probelen( cntr, next, bucket_size, probelen_offset ) <= 1 )
2055
+ break; // Empty slot or key already in its home bucket, so all done.
2056
+
2057
+ //Bump backwards.
2058
+
2059
+ memcpy(
2060
+ cc_map_key( cntr, i, bucket_size, key_offset ),
2061
+ cc_map_key( cntr, next, bucket_size, key_offset ),
2062
+ key_size
2063
+ );
2064
+ memcpy( cc_map_el( cntr, i, bucket_size ), cc_map_el( cntr, next, bucket_size ), el_size );
2065
+
2066
+ *cc_map_probelen( cntr, i, bucket_size, probelen_offset ) =
2067
+ *cc_map_probelen( cntr, next, bucket_size, probelen_offset ) - 1;
2068
+ *cc_map_probelen( cntr, next, bucket_size, probelen_offset ) = 0;
2069
+
2070
+ i = next;
2071
+ }
2072
+ }
2073
+
2074
+ #define CC_MAP_ERASE_ITR( cntr, i ) \
2075
+ cc_map_erase_itr( \
2076
+ cntr, \
2077
+ i, \
2078
+ CC_MAP_BUCKET_SIZE( cntr ), \
2079
+ CC_EL_SIZE( cntr ), \
2080
+ CC_MAP_KEY_OFFSET( cntr ), \
2081
+ CC_KEY_SIZE( cntr ), \
2082
+ CC_MAP_PROBELEN_OFFSET( cntr ), \
2083
+ CC_KEY_DTOR( cntr ), \
2084
+ CC_EL_DTOR( cntr ) \
2085
+ ) \
2086
+
2087
+
2088
+ // Erases the element with the specified key, if it exists.
2089
+ // Returns a pointer that evaluates to true if an element was erased, or else is NULL.
2090
+ // This pointer is eventually cast to bool by the cc_erase API macro.
2091
+ static inline void *cc_map_erase(
2092
+ void *cntr,
2093
+ void *key,
2094
+ size_t bucket_size,
2095
+ size_t el_size,
2096
+ size_t key_offset,
2097
+ size_t key_size,
2098
+ size_t probelen_offset,
2099
+ int ( *cmpr )( void *, void *),
2100
+ size_t ( *hash )( void * ),
2101
+ void ( *key_dtor )( void * ),
2102
+ void ( *el_dtor )( void * )
2103
+ )
2104
+ {
2105
+ if( cc_map_size( cntr ) == 0 )
2106
+ return NULL;
2107
+
2108
+ size_t i = hash( key ) & ( cc_map_hdr( cntr )->cap - 1 );
2109
+ cc_probelen_ty probelen = 1;
2110
+
2111
+ while( probelen <= *cc_map_probelen( cntr, i, bucket_size, probelen_offset ) )
2112
+ {
2113
+ if(
2114
+ probelen == *cc_map_probelen( cntr, i, bucket_size, probelen_offset ) &&
2115
+ cmpr( cc_map_key( cntr, i, bucket_size, key_offset ), key ) == 0
2116
+ )
2117
+ {
2118
+ cc_map_erase_itr(
2119
+ cntr,
2120
+ cc_map_el( cntr, i, bucket_size ),
2121
+ bucket_size,
2122
+ el_size,
2123
+ key_offset,
2124
+ key_size,
2125
+ probelen_offset,
2126
+ key_dtor,
2127
+ el_dtor
2128
+ );
2129
+
2130
+ return cc_dummy_true_ptr;
2131
+ }
2132
+
2133
+ i = ( i + 1 ) & ( cc_map_hdr( cntr )->cap - 1 );
2134
+ ++probelen;
2135
+ }
2136
+
2137
+ return NULL;
2138
+ }
2139
+
2140
+ #define CC_MAP_ERASE( cntr, key ) \
2141
+ cc_map_erase( \
2142
+ cntr, \
2143
+ &CC_MAKE_LVAL_COPY( CC_KEY_TY( cntr ), key ), \
2144
+ CC_MAP_BUCKET_SIZE( cntr ), \
2145
+ CC_EL_SIZE( cntr ), \
2146
+ CC_MAP_KEY_OFFSET( cntr ), \
2147
+ CC_KEY_SIZE( cntr ), \
2148
+ CC_MAP_PROBELEN_OFFSET( cntr ), \
2149
+ CC_KEY_CMPR( cntr ), \
2150
+ CC_KEY_HASH( cntr ), \
2151
+ CC_KEY_DTOR( cntr ), \
2152
+ CC_EL_DTOR( cntr ) \
2153
+ ) \
2154
+
2155
+ // Initializes a shallow copy of the source map.
2156
+ // The capacity of the copy is the same as the capacity of the source map, unless the source map is empty, in which case
2157
+ // the copy is a placeholder.
2158
+ // Hence, this function does no rehashing.
2159
+ // Returns a the pointer to the copy, or NULL in the case of allocation failure.
2160
+ // That return value is cast to bool in the corresponding macro.
2161
+ static inline void *cc_map_init_clone(
2162
+ void *src,
2163
+ size_t bucket_size,
2164
+ void *( *realloc_ )( void *, size_t )
2165
+ )
2166
+ {
2167
+ if( cc_map_size( src ) == 0 ) // Also handles placeholder.
2168
+ return (void *)&cc_map_placeholder;
2169
+
2170
+ cc_map_hdr_ty *new_cntr = (cc_map_hdr_ty*)realloc_( NULL, sizeof( cc_map_hdr_ty ) + bucket_size * cc_map_cap( src ) );
2171
+ if( !new_cntr )
2172
+ return NULL;
2173
+
2174
+ memcpy( new_cntr, src, sizeof( cc_map_hdr_ty ) + bucket_size * cc_map_cap( src ) );
2175
+ return new_cntr;
2176
+ }
2177
+
2178
+ #define CC_MAP_INIT_CLONE( cntr, src ) \
2179
+ ( cntr = (CC_TYPEOF_XP( cntr ))cc_map_init_clone( src, CC_MAP_BUCKET_SIZE( cntr ), CC_GET_REALLOC ) ) \
2180
+
2181
+ // Shrinks map's capacity to the minimum possible without violating the max load factor associated with the key type.
2182
+ // If shrinking is necessary, then a complete rehash occurs.
2183
+ // Returns a cc_allocing_fn_result_ty containing the new container handle and a pointer that evaluates to true if the
2184
+ // operation was successful and false in the case of allocation failure.
2185
+ static inline cc_allocing_fn_result_ty cc_map_shrink(
2186
+ void *cntr,
2187
+ size_t bucket_size,
2188
+ size_t el_size,
2189
+ size_t key_offset,
2190
+ size_t key_size,
2191
+ size_t probelen_offset,
2192
+ int ( *cmpr )( void *, void * ),
2193
+ size_t ( *hash )( void * ),
2194
+ double max_load,
2195
+ void *( *realloc_ )( void *, size_t ),
2196
+ void ( *free_ )( void * )
2197
+ )
2198
+ {
2199
+ size_t cap = cc_map_min_cap_for_n_els( cc_map_size( cntr ), max_load );
2200
+
2201
+ if( cap == cc_map_cap( cntr ) ) // Shrink unnecessary.
2202
+ return cc_make_allocing_fn_result( cntr, cc_dummy_true_ptr );
2203
+
2204
+ if( cap == 0 ) // Restore placeholder.
2205
+ {
2206
+ if( !cc_map_is_placeholder( cntr ) )
2207
+ free_( cntr );
2208
+
2209
+ return cc_make_allocing_fn_result( (void *)&cc_map_placeholder, cc_dummy_true_ptr );
2210
+ }
2211
+
2212
+ void *new_cntr = cc_map_make_rehash(
2213
+ cntr,
2214
+ cap,
2215
+ bucket_size,
2216
+ el_size,
2217
+ key_offset,
2218
+ key_size,
2219
+ probelen_offset,
2220
+ cmpr,
2221
+ hash,
2222
+ realloc_
2223
+ );
2224
+ if( !new_cntr )
2225
+ return cc_make_allocing_fn_result( cntr, NULL );
2226
+
2227
+ if( !cc_map_is_placeholder( cntr ) )
2228
+ free_( cntr );
2229
+
2230
+ return cc_make_allocing_fn_result( new_cntr, cc_dummy_true_ptr );
2231
+ }
2232
+
2233
+ #define CC_MAP_SHRINK( cntr ) \
2234
+ ( \
2235
+ CC_POINT_HNDL_TO_ALLOCING_FN_RESULT( \
2236
+ cntr, \
2237
+ cc_map_shrink( \
2238
+ cntr, \
2239
+ CC_MAP_BUCKET_SIZE( cntr ), \
2240
+ CC_EL_SIZE( cntr ), \
2241
+ CC_MAP_KEY_OFFSET( cntr ), \
2242
+ CC_KEY_SIZE( cntr ), \
2243
+ CC_MAP_PROBELEN_OFFSET( cntr ), \
2244
+ CC_KEY_CMPR( cntr ), \
2245
+ CC_KEY_HASH( cntr ), \
2246
+ CC_KEY_LOAD( cntr ), \
2247
+ CC_GET_REALLOC, \
2248
+ CC_GET_FREE \
2249
+ ) \
2250
+ ), \
2251
+ (bool)CC_FIX_HNDL_AND_RETURN_OTHER_PTR( cntr ) \
2252
+ ) \
2253
+
2254
+ // Erases all elements, calling the destructors for the key and element types if necessary, without changing the map's
2255
+ // capacity.
2256
+ static inline void cc_map_clear(
2257
+ void *cntr,
2258
+ size_t bucket_size,
2259
+ size_t key_offset,
2260
+ size_t probelen_offset,
2261
+ void ( *key_dtor )( void * ),
2262
+ void ( *el_dtor )( void * )
2263
+ )
2264
+ {
2265
+ if( cc_map_size( cntr ) == 0 ) // Also handles placeholder map.
2266
+ return;
2267
+
2268
+ for( size_t i = 0; i < cc_map_hdr( cntr )->cap; ++i )
2269
+ if( *cc_map_probelen( cntr, i, bucket_size, probelen_offset ) )
2270
+ {
2271
+ if( key_dtor )
2272
+ key_dtor( cc_map_key( cntr, i, bucket_size, key_offset ) );
2273
+
2274
+ if( el_dtor )
2275
+ el_dtor( cc_map_el( cntr, i, bucket_size ) );
2276
+
2277
+ *cc_map_probelen( cntr, i, bucket_size, probelen_offset ) = 0;
2278
+ }
2279
+
2280
+ cc_map_hdr( cntr )->size = 0;
2281
+ }
2282
+
2283
+ #define CC_MAP_CLEAR( cntr ) \
2284
+ cc_map_clear( \
2285
+ cntr, \
2286
+ CC_MAP_BUCKET_SIZE( cntr ), \
2287
+ CC_MAP_KEY_OFFSET( cntr ), \
2288
+ CC_MAP_PROBELEN_OFFSET( cntr ), \
2289
+ CC_KEY_DTOR( cntr ), \
2290
+ CC_EL_DTOR( cntr ) \
2291
+ ) \
2292
+
2293
+ // Clears the map and frees its memory if is not placeholder.
2294
+ static inline void cc_map_cleanup(
2295
+ void *cntr,
2296
+ size_t bucket_size,
2297
+ size_t key_offset,
2298
+ size_t probelen_offset,
2299
+ void (*key_dtor)( void * ),
2300
+ void (*el_dtor)( void * ),
2301
+ void (*free_)( void * )
2302
+ )
2303
+ {
2304
+ cc_map_clear( cntr, bucket_size, key_offset, probelen_offset, key_dtor, el_dtor );
2305
+
2306
+ if( !cc_map_is_placeholder( cntr ) )
2307
+ free_( cntr );
2308
+ }
2309
+
2310
+ #define CC_MAP_CLEANUP( cntr ) \
2311
+ ( \
2312
+ cc_map_cleanup( \
2313
+ cntr, \
2314
+ CC_MAP_BUCKET_SIZE( cntr ), \
2315
+ CC_MAP_KEY_OFFSET( cntr ), \
2316
+ CC_MAP_PROBELEN_OFFSET( cntr ), \
2317
+ CC_KEY_DTOR( cntr ), \
2318
+ CC_EL_DTOR( cntr ), \
2319
+ CC_GET_FREE \
2320
+ ), \
2321
+ CC_MAP_INIT( cntr ) \
2322
+ ) \
2323
+
2324
+ // For maps, the container handle doubles up as r_end.
2325
+ static inline void *cc_map_r_end( void *cntr )
2326
+ {
2327
+ return cntr;
2328
+ }
2329
+
2330
+ // Returns a pointer-iterator to the end of the bucket array.
2331
+ static inline void *cc_map_end( void *cntr, size_t bucket_size )
2332
+ {
2333
+ return cc_map_el( cntr, cc_map_hdr( cntr )->cap, bucket_size );
2334
+ }
2335
+
2336
+ #define CC_MAP_END( cntr ) cc_map_end( cntr, CC_MAP_BUCKET_SIZE( cntr ) )
2337
+
2338
+ // Returns a pointer-iterator to the first element, or end if the map is empty.
2339
+ static inline void *cc_map_first( void *cntr, size_t bucket_size, size_t probelen_offset )
2340
+ {
2341
+ for( size_t i = 0; i < cc_map_hdr( cntr )->cap; ++i )
2342
+ if( *cc_map_probelen( cntr, i, bucket_size, probelen_offset ) )
2343
+ return cc_map_el( cntr, i, bucket_size );
2344
+
2345
+ return cc_map_end( cntr, bucket_size );
2346
+ }
2347
+
2348
+ #define CC_MAP_FIRST( cntr ) cc_map_first( cntr, CC_MAP_BUCKET_SIZE( cntr ), CC_MAP_PROBELEN_OFFSET( cntr ) )
2349
+
2350
+ // Returns a pointer-iterator to the last element, or r_end if the map is empty.
2351
+ static inline void *cc_map_last( void *cntr, size_t bucket_size, size_t probelen_offset )
2352
+ {
2353
+ for( size_t i = cc_map_hdr( cntr )->cap; i-- > 0; )
2354
+ if( *cc_map_probelen( cntr, i, bucket_size, probelen_offset ) )
2355
+ return cc_map_el( cntr, i, bucket_size );
2356
+
2357
+ return cc_map_r_end( cntr );
2358
+ }
2359
+
2360
+ #define CC_MAP_LAST( cntr ) cc_map_last( cntr, CC_MAP_BUCKET_SIZE( cntr ), CC_MAP_PROBELEN_OFFSET( cntr ) )
2361
+
2362
+ static inline void *cc_map_next( void *cntr, void *i, size_t bucket_size, size_t probelen_offset )
2363
+ {
2364
+ size_t j = ( (char *)i - (char *)cc_map_el( cntr, 0, bucket_size ) ) / bucket_size + 1;
2365
+
2366
+ while( j < cc_map_hdr( cntr )->cap && !*cc_map_probelen( cntr, j, bucket_size, probelen_offset ) )
2367
+ ++j;
2368
+
2369
+ return cc_map_el( cntr, j, bucket_size );
2370
+ }
2371
+
2372
+ #define CC_MAP_NEXT( cntr, i ) cc_map_next( cntr, i, CC_MAP_BUCKET_SIZE( cntr ), CC_MAP_PROBELEN_OFFSET( cntr ) )
2373
+
2374
+ static inline void *cc_map_prev( void *cntr, void *i, size_t bucket_size, size_t probelen_offset )
2375
+ {
2376
+ size_t j = ( (char *)i - (char *)cc_map_el( cntr, 0, bucket_size ) ) / bucket_size;
2377
+
2378
+ while( true )
2379
+ {
2380
+ if( j == 0 )
2381
+ return cc_map_r_end( cntr );
2382
+
2383
+ --j;
2384
+ if( *cc_map_probelen( cntr, j, bucket_size, probelen_offset ) )
2385
+ return cc_map_el( cntr, j, bucket_size );
2386
+ }
2387
+ }
2388
+
2389
+ #define CC_MAP_PREV( cntr, i ) cc_map_prev( cntr, i, CC_MAP_BUCKET_SIZE( cntr ), CC_MAP_PROBELEN_OFFSET( cntr ) )
2390
+
2391
+ /*--------------------------------------------------------------------------------------------------------------------*/
2392
+ /* Set */
2393
+ /*--------------------------------------------------------------------------------------------------------------------*/
2394
+
2395
+ // Set is implemented as a map where the key and element are merged into one space in memory.
2396
+ // Hence, it reuses the functions for map, except that the key offset passed in is zero and the element size passed in
2397
+ // is also zero to avoid double-memcpying.
2398
+ // For simplicity's sake, the idea here is to deviate as little from the code for map as possible.
2399
+ // Note that for set, CC_EL_TYPE and CC_KEY_TYPE are synonymous (as are CC_KEY_SIZE and CC_EL_SIZE).
2400
+
2401
+ #define CC_SET_PROBELEN_OFFSET( cntr ) CC_ROUND_UP( CC_EL_SIZE( cntr ), alignof( cc_probelen_ty ) )
2402
+
2403
+ #define CC_SET_BUCKET_SIZE( cntr ) \
2404
+ CC_ROUND_UP( CC_SET_PROBELEN_OFFSET( cntr ) + sizeof( cc_probelen_ty ), alignof( CC_EL_TY( cntr ) ) ) \
2405
+
2406
+ #define CC_SET_INIT CC_MAP_INIT
2407
+
2408
+ #define CC_SET_SIZE cc_map_size
2409
+
2410
+ #define CC_SET_CAP cc_map_cap
2411
+
2412
+ #define CC_SET_RESERVE( cntr, n ) \
2413
+ ( \
2414
+ CC_POINT_HNDL_TO_ALLOCING_FN_RESULT( \
2415
+ cntr, \
2416
+ cc_map_reserve( \
2417
+ cntr, \
2418
+ n, \
2419
+ CC_SET_BUCKET_SIZE( cntr ), \
2420
+ 0, /* zero el size */ \
2421
+ 0, /* zero key offset */ \
2422
+ CC_KEY_SIZE( cntr ), \
2423
+ CC_SET_PROBELEN_OFFSET( cntr ), \
2424
+ CC_KEY_CMPR( cntr ), \
2425
+ CC_KEY_HASH( cntr ), \
2426
+ CC_KEY_LOAD( cntr ), \
2427
+ CC_GET_REALLOC, \
2428
+ CC_GET_FREE \
2429
+ ) \
2430
+ ), \
2431
+ (bool)CC_FIX_HNDL_AND_RETURN_OTHER_PTR( cntr ) \
2432
+ ) \
2433
+
2434
+ #define CC_SET_INSERT( cntr, el, replace ) \
2435
+ ( \
2436
+ CC_POINT_HNDL_TO_ALLOCING_FN_RESULT( \
2437
+ cntr, \
2438
+ cc_map_insert( \
2439
+ cntr, \
2440
+ /* Copying el is a non-op, but we still \
2441
+ need to pass a valid pointer for memcpy. */ \
2442
+ cntr, \
2443
+ &CC_MAKE_LVAL_COPY( CC_KEY_TY( cntr ), el ), \
2444
+ replace, \
2445
+ CC_SET_BUCKET_SIZE( cntr ), \
2446
+ 0, /* Zero el size. */ \
2447
+ 0, /* Zero key offset. */ \
2448
+ CC_KEY_SIZE( cntr ), \
2449
+ CC_SET_PROBELEN_OFFSET( cntr ), \
2450
+ CC_KEY_CMPR( cntr ), \
2451
+ CC_KEY_HASH( cntr ), \
2452
+ CC_KEY_LOAD( cntr ), \
2453
+ CC_KEY_DTOR( cntr ), \
2454
+ NULL, /* Only need one dtor. */ \
2455
+ CC_GET_REALLOC, \
2456
+ CC_GET_FREE \
2457
+ ) \
2458
+ ), \
2459
+ CC_FIX_HNDL_AND_RETURN_OTHER_PTR( cntr ) \
2460
+ ) \
2461
+
2462
+ #define CC_SET_GET( cntr, el ) \
2463
+ cc_map_get( \
2464
+ cntr, \
2465
+ &CC_MAKE_LVAL_COPY( CC_KEY_TY( cntr ), el ), \
2466
+ CC_SET_BUCKET_SIZE( cntr ), \
2467
+ 0, /* Zero key offset. */ \
2468
+ CC_SET_PROBELEN_OFFSET( cntr ), \
2469
+ CC_KEY_CMPR( cntr ), \
2470
+ CC_KEY_HASH( cntr ) \
2471
+ ) \
2472
+
2473
+ #define CC_SET_ERASE_ITR( cntr, i ) \
2474
+ cc_map_erase_itr( \
2475
+ cntr, \
2476
+ i, \
2477
+ CC_SET_BUCKET_SIZE( cntr ), \
2478
+ 0, /* Zero el size. */ \
2479
+ 0, /* Zero key offset. */ \
2480
+ CC_KEY_SIZE( cntr ), \
2481
+ CC_SET_PROBELEN_OFFSET( cntr ), \
2482
+ CC_KEY_DTOR( cntr ), \
2483
+ NULL /* Only need one dtor */ \
2484
+ ) \
2485
+
2486
+ #define CC_SET_ERASE( cntr, key ) \
2487
+ cc_map_erase( \
2488
+ cntr, \
2489
+ &CC_MAKE_LVAL_COPY( CC_KEY_TY( cntr ), key ), \
2490
+ CC_SET_BUCKET_SIZE( cntr ), \
2491
+ 0, /* Zero el size. */ \
2492
+ 0, /* Zero key offset. */ \
2493
+ CC_KEY_SIZE( cntr ), \
2494
+ CC_SET_PROBELEN_OFFSET( cntr ), \
2495
+ CC_KEY_CMPR( cntr ), \
2496
+ CC_KEY_HASH( cntr ), \
2497
+ CC_KEY_DTOR( cntr ), \
2498
+ NULL /* Only need one dtor. */ \
2499
+ ) \
2500
+
2501
+ #define CC_SET_INIT_CLONE( cntr, src ) \
2502
+ ( cntr = (CC_TYPEOF_XP( cntr ))cc_map_init_clone( src, CC_SET_BUCKET_SIZE( cntr ), CC_GET_REALLOC ) ) \
2503
+
2504
+ #define CC_SET_SHRINK( cntr ) \
2505
+ ( \
2506
+ CC_POINT_HNDL_TO_ALLOCING_FN_RESULT( \
2507
+ cntr, \
2508
+ cc_map_shrink( \
2509
+ cntr, \
2510
+ CC_SET_BUCKET_SIZE( cntr ), \
2511
+ 0, /* Zero el size. */ \
2512
+ 0, /* Zero key offset. */ \
2513
+ CC_KEY_SIZE( cntr ), \
2514
+ CC_SET_PROBELEN_OFFSET( cntr ), \
2515
+ CC_KEY_CMPR( cntr ), \
2516
+ CC_KEY_HASH( cntr ), \
2517
+ CC_KEY_LOAD( cntr ), \
2518
+ CC_GET_REALLOC, \
2519
+ CC_GET_FREE \
2520
+ ) \
2521
+ ), \
2522
+ (bool)CC_FIX_HNDL_AND_RETURN_OTHER_PTR( cntr ) \
2523
+ ) \
2524
+
2525
+ #define CC_SET_CLEAR( cntr ) \
2526
+ cc_map_clear( \
2527
+ cntr, \
2528
+ CC_SET_BUCKET_SIZE( cntr ), \
2529
+ 0, /* Zero key offset. */ \
2530
+ CC_SET_PROBELEN_OFFSET( cntr ), \
2531
+ CC_KEY_DTOR( cntr ), \
2532
+ NULL /* Only need one dtor. */ \
2533
+ ) \
2534
+
2535
+ #define CC_SET_CLEANUP( cntr ) \
2536
+ ( \
2537
+ cc_map_cleanup( \
2538
+ cntr, \
2539
+ CC_SET_BUCKET_SIZE( cntr ), \
2540
+ 0, /* Zero key offset. */ \
2541
+ CC_SET_PROBELEN_OFFSET( cntr ), \
2542
+ CC_KEY_DTOR( cntr ), \
2543
+ NULL, /* Only need one dtor. */ \
2544
+ CC_GET_FREE \
2545
+ ), \
2546
+ CC_SET_INIT( cntr ) \
2547
+ ) \
2548
+
2549
+ #define CC_SET_R_END cc_map_r_end
2550
+
2551
+ #define CC_SET_END( cntr ) cc_map_end( cntr, CC_SET_BUCKET_SIZE( cntr ) )
2552
+
2553
+ #define CC_SET_FIRST( cntr ) cc_map_first( cntr, CC_SET_BUCKET_SIZE( cntr ), CC_SET_PROBELEN_OFFSET( cntr ) )
2554
+
2555
+ #define CC_SET_LAST( cntr ) cc_map_last( cntr, CC_SET_BUCKET_SIZE( cntr ), CC_SET_PROBELEN_OFFSET( cntr ) )
2556
+
2557
+ #define CC_SET_NEXT( cntr, i ) cc_map_next( cntr, i, CC_SET_BUCKET_SIZE( cntr ), CC_SET_PROBELEN_OFFSET( cntr ) )
2558
+
2559
+ #define CC_SET_PREV( cntr, i ) cc_map_prev( cntr, i, CC_SET_BUCKET_SIZE( cntr ), CC_SET_PROBELEN_OFFSET( cntr ) )
2560
+
2561
+ /*--------------------------------------------------------------------------------------------------------------------*/
2562
+ /* API */
2563
+ /*--------------------------------------------------------------------------------------------------------------------*/
2564
+
2565
+ // Generally, API macros need to do several things:
2566
+ // - For GCC and Clang, check the first argument - the pointer to the container handle - for potential duplicate side
2567
+ // effects and generate a compile-time warning if they exist.
2568
+ // Although this is only strictly necessary for macros that may cause reallocation operating on containers that store
2569
+ // their headers in the same block of memory as their elements, we extend this check to all API macros for the sake of
2570
+ // consistency.
2571
+ // - Check that the aforementioned pointer points to a container handle compatible with the macro.
2572
+ // - Convert the aforementioned pointer to the actual container handle (i.e. derference it).
2573
+ // While the internal macros take the container handle directly, API macros take a pointer to the handle so that it's
2574
+ // clear to the user that they may modify it.
2575
+ // - Call the correct container-specific function or macro.
2576
+ // - Provide dummy values as arguments to the non-called container-specific functions or macros to avoid compiler
2577
+ // errors.
2578
+ // - Cast the result of the container-specific function or macro, if it is a void pointer, to the correct pointer type
2579
+ // (usually the container's element type).
2580
+ // - For container-specific functions or macros that return a void pointer that actually denotes whether the operation
2581
+ // was successful, convert it to bool in the case of those containers.
2582
+ // Although these macros are long and ramose, the compiler should optimize away all the checks and irrelevant paths.
2583
+
2584
+ #define cc_init( cntr ) \
2585
+ ( \
2586
+ CC_WARN_DUPLICATE_SIDE_EFFECTS( cntr ), \
2587
+ CC_STATIC_ASSERT( \
2588
+ CC_CNTR_ID( *(cntr) ) == CC_VEC || \
2589
+ CC_CNTR_ID( *(cntr) ) == CC_LIST || \
2590
+ CC_CNTR_ID( *(cntr) ) == CC_MAP || \
2591
+ CC_CNTR_ID( *(cntr) ) == CC_SET \
2592
+ ), \
2593
+ CC_CNTR_ID( *(cntr) ) == CC_VEC ? CC_VEC_INIT( *(cntr) ) : \
2594
+ CC_CNTR_ID( *(cntr) ) == CC_LIST ? CC_LIST_INIT( *(cntr) ) : \
2595
+ CC_CNTR_ID( *(cntr) ) == CC_MAP ? CC_MAP_INIT( *(cntr) ) : \
2596
+ CC_CNTR_ID( *(cntr) ) == CC_SET ? CC_SET_INIT( *(cntr) ) : \
2597
+ (void)0 /* Unreachable. */ \
2598
+ ) \
2599
+
2600
+ #define cc_init_clone( cntr, src ) \
2601
+ CC_CAST_MAYBE_UNUSED( bool, ( \
2602
+ CC_WARN_DUPLICATE_SIDE_EFFECTS( cntr ), \
2603
+ CC_STATIC_ASSERT( CC_IS_SAME_TY( *(cntr), *(src) ) ), \
2604
+ CC_STATIC_ASSERT( \
2605
+ CC_CNTR_ID( *(cntr) ) == CC_VEC || \
2606
+ CC_CNTR_ID( *(cntr) ) == CC_LIST || \
2607
+ CC_CNTR_ID( *(cntr) ) == CC_MAP || \
2608
+ CC_CNTR_ID( *(cntr) ) == CC_SET \
2609
+ ), \
2610
+ CC_CNTR_ID( *(cntr) ) == CC_VEC ? CC_VEC_INIT_CLONE( *(cntr), *(src) ) : \
2611
+ CC_CNTR_ID( *(cntr) ) == CC_LIST ? CC_LIST_INIT_CLONE( *(cntr), *(src) ) : \
2612
+ CC_CNTR_ID( *(cntr) ) == CC_MAP ? CC_MAP_INIT_CLONE( *(cntr), *(src) ) : \
2613
+ CC_CNTR_ID( *(cntr) ) == CC_SET ? CC_SET_INIT_CLONE( *(cntr), *(src) ) : \
2614
+ NULL /* Unreachable. */ \
2615
+ ) ) \
2616
+
2617
+
2618
+ #define cc_size( cntr ) \
2619
+ ( \
2620
+ CC_WARN_DUPLICATE_SIDE_EFFECTS( cntr ), \
2621
+ CC_STATIC_ASSERT( \
2622
+ CC_CNTR_ID( *(cntr) ) == CC_VEC || \
2623
+ CC_CNTR_ID( *(cntr) ) == CC_LIST || \
2624
+ CC_CNTR_ID( *(cntr) ) == CC_MAP || \
2625
+ CC_CNTR_ID( *(cntr) ) == CC_SET \
2626
+ ), \
2627
+ CC_CNTR_ID( *(cntr) ) == CC_VEC ? cc_vec_size( *(cntr) ) : \
2628
+ CC_CNTR_ID( *(cntr) ) == CC_LIST ? cc_list_size( *(cntr) ) : \
2629
+ CC_CNTR_ID( *(cntr) ) == CC_MAP ? cc_map_size( *(cntr) ) : \
2630
+ CC_CNTR_ID( *(cntr) ) == CC_SET ? CC_SET_SIZE( *(cntr) ) : \
2631
+ 0 /* Unreachable. */ \
2632
+ ) \
2633
+
2634
+ #define cc_cap( cntr ) \
2635
+ ( \
2636
+ CC_WARN_DUPLICATE_SIDE_EFFECTS( cntr ), \
2637
+ CC_STATIC_ASSERT( \
2638
+ CC_CNTR_ID( *(cntr) ) == CC_VEC || \
2639
+ CC_CNTR_ID( *(cntr) ) == CC_MAP || \
2640
+ CC_CNTR_ID( *(cntr) ) == CC_SET \
2641
+ ), \
2642
+ CC_CNTR_ID( *(cntr) ) == CC_VEC ? cc_vec_cap( *(cntr) ) : \
2643
+ CC_CNTR_ID( *(cntr) ) == CC_MAP ? cc_map_cap( *(cntr) ) : \
2644
+ CC_CNTR_ID( *(cntr) ) == CC_SET ? CC_SET_CAP( *(cntr) ) : \
2645
+ 0 /* Unreachable. */ \
2646
+ ) \
2647
+
2648
+ #define cc_reserve( cntr, n ) \
2649
+ CC_CAST_MAYBE_UNUSED( bool, ( \
2650
+ CC_WARN_DUPLICATE_SIDE_EFFECTS( cntr ), \
2651
+ CC_STATIC_ASSERT( \
2652
+ CC_CNTR_ID( *(cntr) ) == CC_VEC || \
2653
+ CC_CNTR_ID( *(cntr) ) == CC_MAP || \
2654
+ CC_CNTR_ID( *(cntr) ) == CC_SET \
2655
+ ), \
2656
+ CC_CNTR_ID( *(cntr) ) == CC_VEC ? CC_VEC_RESERVE( *(cntr), (n) ) : \
2657
+ CC_CNTR_ID( *(cntr) ) == CC_MAP ? CC_MAP_RESERVE( *(cntr), (n) ) : \
2658
+ CC_CNTR_ID( *(cntr) ) == CC_SET ? CC_SET_RESERVE( *(cntr), (n) ) : \
2659
+ false /* Unreachable. */ \
2660
+ ) ) \
2661
+
2662
+ #define cc_resize( cntr, n ) \
2663
+ CC_CAST_MAYBE_UNUSED( bool, ( \
2664
+ CC_WARN_DUPLICATE_SIDE_EFFECTS( cntr ), \
2665
+ CC_STATIC_ASSERT( CC_CNTR_ID( *(cntr) ) == CC_VEC ), \
2666
+ CC_VEC_RESIZE( *(cntr), (n) ) \
2667
+ ) ) \
2668
+
2669
+ #define cc_shrink( cntr ) \
2670
+ CC_CAST_MAYBE_UNUSED( bool, ( \
2671
+ CC_WARN_DUPLICATE_SIDE_EFFECTS( cntr ), \
2672
+ CC_STATIC_ASSERT( \
2673
+ CC_CNTR_ID( *(cntr) ) == CC_VEC || \
2674
+ CC_CNTR_ID( *(cntr) ) == CC_MAP || \
2675
+ CC_CNTR_ID( *(cntr) ) == CC_SET \
2676
+ ), \
2677
+ CC_CNTR_ID( *(cntr) ) == CC_VEC ? CC_VEC_SHRINK( *(cntr) ) : \
2678
+ CC_CNTR_ID( *(cntr) ) == CC_MAP ? CC_MAP_SHRINK( *(cntr) ) : \
2679
+ CC_CNTR_ID( *(cntr) ) == CC_SET ? CC_SET_SHRINK( *(cntr) ) : \
2680
+ false /* Unreachable. */ \
2681
+ ) ) \
2682
+
2683
+ #define cc_insert( ... ) CC_SELECT_ON_NUM_ARGS( cc_insert, __VA_ARGS__ )
2684
+
2685
+ #define cc_insert_2( cntr, el ) \
2686
+ CC_CAST_MAYBE_UNUSED( CC_EL_TY( *(cntr) ) *, ( \
2687
+ CC_WARN_DUPLICATE_SIDE_EFFECTS( cntr ), \
2688
+ CC_STATIC_ASSERT( CC_CNTR_ID( *(cntr) ) == CC_SET ), \
2689
+ CC_SET_INSERT( *(cntr), (el), true ) \
2690
+ ) ) \
2691
+
2692
+ #define cc_insert_3( cntr, i, el ) \
2693
+ CC_CAST_MAYBE_UNUSED( CC_EL_TY( *(cntr) ) *, ( \
2694
+ CC_WARN_DUPLICATE_SIDE_EFFECTS( cntr ), \
2695
+ CC_STATIC_ASSERT( \
2696
+ CC_CNTR_ID( *(cntr) ) == CC_VEC || \
2697
+ CC_CNTR_ID( *(cntr) ) == CC_LIST || \
2698
+ CC_CNTR_ID( *(cntr) ) == CC_MAP \
2699
+ ), \
2700
+ CC_CNTR_ID( *(cntr) ) == CC_VEC ? \
2701
+ CC_VEC_INSERT( *(cntr), CC_IF_THEN_XP_ELSE_DUMMY( CC_CNTR_ID( *(cntr) ) == CC_VEC, (i), size_t ), (el) ) : \
2702
+ CC_CNTR_ID( *(cntr) ) == CC_LIST ? \
2703
+ CC_LIST_INSERT( \
2704
+ *(cntr), \
2705
+ CC_IF_THEN_XP_ELSE_DUMMY( CC_CNTR_ID( *(cntr) ) == CC_LIST, (i), CC_EL_TY( *(cntr) )* ), \
2706
+ (el) \
2707
+ ) : \
2708
+ CC_CNTR_ID( *(cntr) ) == CC_MAP ? \
2709
+ CC_MAP_INSERT( \
2710
+ *(cntr), \
2711
+ CC_IF_THEN_XP_ELSE_DUMMY( CC_CNTR_ID( *(cntr) ) == CC_MAP, (i), CC_KEY_TY( *(cntr) ) ), \
2712
+ (el), \
2713
+ true \
2714
+ ) : \
2715
+ NULL /* Unreachable. */ \
2716
+ ) ) \
2717
+
2718
+ #define cc_insert_n( cntr, i, els, n ) \
2719
+ CC_CAST_MAYBE_UNUSED( CC_EL_TY( *(cntr) ) *, ( \
2720
+ CC_WARN_DUPLICATE_SIDE_EFFECTS( cntr ), \
2721
+ CC_STATIC_ASSERT( CC_CNTR_ID( *(cntr) ) == CC_VEC ), \
2722
+ CC_VEC_INSERT_N( *(cntr), (i), (els), (n) ) \
2723
+ ) ) \
2724
+
2725
+ #define cc_push( cntr, el ) \
2726
+ CC_CAST_MAYBE_UNUSED( CC_EL_TY( *(cntr) ) *, ( \
2727
+ CC_WARN_DUPLICATE_SIDE_EFFECTS( cntr ), \
2728
+ CC_STATIC_ASSERT( \
2729
+ CC_CNTR_ID( *(cntr) ) == CC_VEC || \
2730
+ CC_CNTR_ID( *(cntr) ) == CC_LIST \
2731
+ ), \
2732
+ CC_CNTR_ID( *(cntr) ) == CC_VEC ? CC_VEC_PUSH( *(cntr), (el) ) : \
2733
+ CC_CNTR_ID( *(cntr) ) == CC_LIST ? CC_LIST_PUSH( *(cntr), (el) ) : \
2734
+ NULL /* Unreachable. */ \
2735
+ ) ) \
2736
+
2737
+ #define cc_push_n( cntr, els, n ) \
2738
+ CC_CAST_MAYBE_UNUSED( CC_EL_TY( *(cntr) ) *, ( \
2739
+ CC_WARN_DUPLICATE_SIDE_EFFECTS( cntr ), \
2740
+ CC_STATIC_ASSERT( CC_CNTR_ID( *(cntr) ) == CC_VEC ), \
2741
+ CC_VEC_PUSH_N( *(cntr), (els), (n) ) \
2742
+ ) ) \
2743
+
2744
+ #define cc_splice( cntr, i, src, src_i ) \
2745
+ CC_CAST_MAYBE_UNUSED( bool, ( \
2746
+ CC_WARN_DUPLICATE_SIDE_EFFECTS( cntr ), \
2747
+ CC_STATIC_ASSERT( CC_IS_SAME_TY( (cntr), (src) ) ), \
2748
+ CC_STATIC_ASSERT( CC_CNTR_ID( *(cntr) ) == CC_LIST ), \
2749
+ CC_LIST_SPLICE( *(cntr), (i), *(src), (src_i) ) \
2750
+ ) ) \
2751
+
2752
+ #define cc_get( cntr, i ) \
2753
+ CC_CAST_MAYBE_UNUSED( CC_EL_TY( *(cntr) ) *, ( \
2754
+ CC_WARN_DUPLICATE_SIDE_EFFECTS( cntr ), \
2755
+ CC_STATIC_ASSERT( \
2756
+ CC_CNTR_ID( *(cntr) ) == CC_VEC || \
2757
+ CC_CNTR_ID( *(cntr) ) == CC_MAP || \
2758
+ CC_CNTR_ID( *(cntr) ) == CC_SET \
2759
+ ), \
2760
+ CC_CNTR_ID( *(cntr) ) == CC_VEC ? \
2761
+ CC_VEC_GET( *(cntr), CC_IF_THEN_XP_ELSE_DUMMY( CC_CNTR_ID( *(cntr) ) == CC_VEC, (i), size_t ) ) : \
2762
+ CC_CNTR_ID( *(cntr) ) == CC_MAP ? \
2763
+ CC_MAP_GET( *(cntr), CC_IF_THEN_XP_ELSE_DUMMY( CC_CNTR_ID( *(cntr) ) == CC_MAP, (i), CC_KEY_TY( *(cntr) ) ) ) : \
2764
+ CC_CNTR_ID( *(cntr) ) == CC_SET ? \
2765
+ CC_SET_GET( *(cntr), CC_IF_THEN_XP_ELSE_DUMMY( CC_CNTR_ID( *(cntr) ) == CC_SET, (i), CC_KEY_TY( *(cntr) ) ) ) : \
2766
+ NULL /* Unreachable. */ \
2767
+ ) ) \
2768
+
2769
+ #define cc_get_or_insert( ... ) CC_SELECT_ON_NUM_ARGS( cc_get_or_insert, __VA_ARGS__ )
2770
+
2771
+ #define cc_get_or_insert_2( cntr, el ) \
2772
+ CC_CAST_MAYBE_UNUSED( CC_EL_TY( *(cntr) ) *, ( \
2773
+ CC_WARN_DUPLICATE_SIDE_EFFECTS( cntr ), \
2774
+ CC_STATIC_ASSERT( CC_CNTR_ID( *(cntr) ) == CC_SET ), \
2775
+ CC_SET_INSERT( *(cntr), (el), false ) \
2776
+ ) ) \
2777
+
2778
+ #define cc_get_or_insert_3( cntr, key, el ) \
2779
+ CC_CAST_MAYBE_UNUSED( CC_EL_TY( *(cntr) ) *, ( \
2780
+ CC_WARN_DUPLICATE_SIDE_EFFECTS( cntr ), \
2781
+ CC_STATIC_ASSERT( CC_CNTR_ID( *(cntr) ) == CC_MAP ), \
2782
+ CC_MAP_INSERT( *(cntr), (key), (el), false ) \
2783
+ ) ) \
2784
+
2785
+ #define cc_key_for( cntr, i ) \
2786
+ CC_CAST_MAYBE_UNUSED( const CC_KEY_TY( *(cntr) ) *, ( \
2787
+ CC_WARN_DUPLICATE_SIDE_EFFECTS( cntr ), \
2788
+ CC_STATIC_ASSERT( CC_CNTR_ID( *(cntr) ) == CC_MAP ), \
2789
+ CC_MAP_KEY_FOR( *(cntr), (i) ) \
2790
+ ) ) \
2791
+
2792
+ #define cc_erase( cntr, i ) \
2793
+ CC_IF_THEN_PTR_TO_BOOL_ELSE_PTR( CC_CNTR_ID( *(cntr) ) == CC_MAP || CC_CNTR_ID( *(cntr) ) == CC_SET, \
2794
+ CC_CAST_MAYBE_UNUSED( CC_EL_TY( *(cntr) ) *, ( \
2795
+ CC_WARN_DUPLICATE_SIDE_EFFECTS( cntr ), \
2796
+ CC_STATIC_ASSERT( \
2797
+ CC_CNTR_ID( *(cntr) ) == CC_VEC || \
2798
+ CC_CNTR_ID( *(cntr) ) == CC_LIST || \
2799
+ CC_CNTR_ID( *(cntr) ) == CC_MAP || \
2800
+ CC_CNTR_ID( *(cntr) ) == CC_SET \
2801
+ ), \
2802
+ CC_CNTR_ID( *(cntr) ) == CC_VEC ? \
2803
+ CC_VEC_ERASE( *(cntr), CC_IF_THEN_XP_ELSE_DUMMY( CC_CNTR_ID( *(cntr) ) == CC_VEC, (i), size_t ) ) : \
2804
+ CC_CNTR_ID( *(cntr) ) == CC_LIST ? \
2805
+ CC_LIST_ERASE( \
2806
+ *(cntr), \
2807
+ CC_IF_THEN_XP_ELSE_DUMMY( CC_CNTR_ID( *(cntr) ) == CC_LIST, (i), CC_EL_TY( *(cntr) ) * ) \
2808
+ ) : \
2809
+ CC_CNTR_ID( *(cntr) ) == CC_MAP ? \
2810
+ CC_MAP_ERASE( *(cntr), CC_IF_THEN_XP_ELSE_DUMMY( CC_CNTR_ID( *(cntr) ) == CC_MAP, (i), CC_KEY_TY( *(cntr) ) ) ) : \
2811
+ CC_CNTR_ID( *(cntr) ) == CC_SET ? \
2812
+ CC_SET_ERASE( *(cntr), CC_IF_THEN_XP_ELSE_DUMMY( CC_CNTR_ID( *(cntr) ) == CC_SET, (i), CC_KEY_TY( *(cntr) ) ) ) : \
2813
+ NULL /* Unreachable. */ \
2814
+ ) ) ) \
2815
+
2816
+ #define cc_erase_n( cntr, i, n ) \
2817
+ CC_CAST_MAYBE_UNUSED( CC_EL_TY( *(cntr) ) *, ( \
2818
+ CC_WARN_DUPLICATE_SIDE_EFFECTS( cntr ), \
2819
+ CC_STATIC_ASSERT( CC_CNTR_ID( *(cntr) ) == CC_VEC ), \
2820
+ CC_VEC_ERASE_N( *(cntr), (i), (n) ) \
2821
+ ) ) \
2822
+
2823
+ #define cc_erase_itr( cntr, i ) \
2824
+ ( \
2825
+ CC_WARN_DUPLICATE_SIDE_EFFECTS( cntr ), \
2826
+ CC_STATIC_ASSERT( \
2827
+ CC_CNTR_ID( *(cntr) ) == CC_MAP || \
2828
+ CC_CNTR_ID( *(cntr) ) == CC_SET \
2829
+ ), \
2830
+ CC_CNTR_ID( *(cntr) ) == CC_MAP ? CC_MAP_ERASE_ITR( *(cntr), (i) ) : \
2831
+ CC_CNTR_ID( *(cntr) ) == CC_SET ? CC_SET_ERASE_ITR( *(cntr), (i) ) : \
2832
+ (void)0 /* Unreachable. */ \
2833
+ ) \
2834
+
2835
+ #define cc_clear( cntr ) \
2836
+ ( \
2837
+ CC_WARN_DUPLICATE_SIDE_EFFECTS( cntr ), \
2838
+ CC_CNTR_ID( *(cntr) ) == CC_VEC ? CC_VEC_CLEAR( *(cntr) ) : \
2839
+ CC_CNTR_ID( *(cntr) ) == CC_LIST ? CC_LIST_CLEAR( *(cntr) ) : \
2840
+ CC_CNTR_ID( *(cntr) ) == CC_MAP ? CC_MAP_CLEAR( *(cntr) ) : \
2841
+ CC_CNTR_ID( *(cntr) ) == CC_SET ? CC_SET_CLEAR( *(cntr) ) : \
2842
+ (void)0 /* Unreachable. */ \
2843
+ ) \
2844
+
2845
+ #define cc_cleanup( cntr ) \
2846
+ ( \
2847
+ CC_WARN_DUPLICATE_SIDE_EFFECTS( cntr ), \
2848
+ CC_CNTR_ID( *(cntr) ) == CC_VEC ? CC_VEC_CLEANUP( *(cntr) ) : \
2849
+ CC_CNTR_ID( *(cntr) ) == CC_LIST ? CC_LIST_CLEANUP( *(cntr) ) : \
2850
+ CC_CNTR_ID( *(cntr) ) == CC_MAP ? CC_MAP_CLEANUP( *(cntr) ) : \
2851
+ CC_CNTR_ID( *(cntr) ) == CC_SET ? CC_SET_CLEANUP( *(cntr) ) : \
2852
+ (void)0 /* Unreachable. */ \
2853
+ ) \
2854
+
2855
+ #define cc_first( cntr ) \
2856
+ CC_CAST_MAYBE_UNUSED( CC_EL_TY( *(cntr) ) *, ( \
2857
+ CC_WARN_DUPLICATE_SIDE_EFFECTS( cntr ), \
2858
+ CC_STATIC_ASSERT( \
2859
+ CC_CNTR_ID( *(cntr) ) == CC_VEC || \
2860
+ CC_CNTR_ID( *(cntr) ) == CC_LIST || \
2861
+ CC_CNTR_ID( *(cntr) ) == CC_MAP || \
2862
+ CC_CNTR_ID( *(cntr) ) == CC_SET \
2863
+ ), \
2864
+ CC_CNTR_ID( *(cntr) ) == CC_VEC ? cc_vec_first( *(cntr) ) : \
2865
+ CC_CNTR_ID( *(cntr) ) == CC_LIST ? cc_list_first( *(cntr) ) : \
2866
+ CC_CNTR_ID( *(cntr) ) == CC_MAP ? CC_MAP_FIRST( *(cntr) ) : \
2867
+ CC_CNTR_ID( *(cntr) ) == CC_SET ? CC_SET_FIRST( *(cntr) ) : \
2868
+ NULL /* Unreachable. */ \
2869
+ ) ) \
2870
+
2871
+ #define cc_last( cntr ) \
2872
+ CC_CAST_MAYBE_UNUSED( CC_EL_TY( *(cntr) ) *, ( \
2873
+ CC_WARN_DUPLICATE_SIDE_EFFECTS( cntr ), \
2874
+ CC_STATIC_ASSERT( \
2875
+ CC_CNTR_ID( *(cntr) ) == CC_VEC || \
2876
+ CC_CNTR_ID( *(cntr) ) == CC_LIST || \
2877
+ CC_CNTR_ID( *(cntr) ) == CC_MAP || \
2878
+ CC_CNTR_ID( *(cntr) ) == CC_SET \
2879
+ ), \
2880
+ CC_CNTR_ID( *(cntr) ) == CC_VEC ? CC_VEC_LAST( *(cntr) ) : \
2881
+ CC_CNTR_ID( *(cntr) ) == CC_LIST ? cc_list_last( *(cntr) ) : \
2882
+ CC_CNTR_ID( *(cntr) ) == CC_MAP ? CC_MAP_LAST( *(cntr) ) : \
2883
+ CC_CNTR_ID( *(cntr) ) == CC_SET ? CC_SET_LAST( *(cntr) ) : \
2884
+ NULL /* Unreachable. */ \
2885
+ ) ) \
2886
+
2887
+ #define cc_r_end( cntr ) \
2888
+ CC_CAST_MAYBE_UNUSED( CC_EL_TY( *(cntr) ) *, ( \
2889
+ CC_WARN_DUPLICATE_SIDE_EFFECTS( cntr ), \
2890
+ CC_STATIC_ASSERT( \
2891
+ CC_CNTR_ID( *(cntr) ) == CC_LIST || \
2892
+ CC_CNTR_ID( *(cntr) ) == CC_MAP || \
2893
+ CC_CNTR_ID( *(cntr) ) == CC_SET \
2894
+ ), \
2895
+ CC_CNTR_ID( *(cntr) ) == CC_LIST ? cc_list_r_end( *(cntr) ) : \
2896
+ CC_CNTR_ID( *(cntr) ) == CC_MAP ? cc_map_r_end( *(cntr) ) : \
2897
+ CC_CNTR_ID( *(cntr) ) == CC_SET ? CC_SET_R_END( *(cntr) ) : \
2898
+ NULL /* Unreachable. */ \
2899
+ ) ) \
2900
+
2901
+ #define cc_end( cntr ) \
2902
+ CC_CAST_MAYBE_UNUSED( CC_EL_TY( *(cntr) ) *, ( \
2903
+ CC_WARN_DUPLICATE_SIDE_EFFECTS( cntr ), \
2904
+ CC_STATIC_ASSERT( \
2905
+ CC_CNTR_ID( *(cntr) ) == CC_VEC || \
2906
+ CC_CNTR_ID( *(cntr) ) == CC_LIST || \
2907
+ CC_CNTR_ID( *(cntr) ) == CC_MAP || \
2908
+ CC_CNTR_ID( *(cntr) ) == CC_SET \
2909
+ ), \
2910
+ CC_CNTR_ID( *(cntr) ) == CC_VEC ? CC_VEC_END( *(cntr) ) : \
2911
+ CC_CNTR_ID( *(cntr) ) == CC_LIST ? cc_list_end( *(cntr) ) : \
2912
+ CC_CNTR_ID( *(cntr) ) == CC_MAP ? CC_MAP_END( *(cntr) ) : \
2913
+ CC_CNTR_ID( *(cntr) ) == CC_SET ? CC_SET_END( *(cntr) ) : \
2914
+ NULL /* Unreachable. */ \
2915
+ ) ) \
2916
+
2917
+ #define cc_next( cntr, i ) \
2918
+ CC_CAST_MAYBE_UNUSED( CC_EL_TY( *(cntr) ) *, ( \
2919
+ CC_WARN_DUPLICATE_SIDE_EFFECTS( cntr ), \
2920
+ CC_STATIC_ASSERT( \
2921
+ CC_CNTR_ID( *(cntr) ) == CC_VEC || \
2922
+ CC_CNTR_ID( *(cntr) ) == CC_LIST || \
2923
+ CC_CNTR_ID( *(cntr) ) == CC_MAP || \
2924
+ CC_CNTR_ID( *(cntr) ) == CC_SET \
2925
+ ), \
2926
+ CC_CNTR_ID( *(cntr) ) == CC_VEC ? CC_VEC_NEXT( *(cntr), (i) ) : \
2927
+ CC_CNTR_ID( *(cntr) ) == CC_LIST ? cc_list_next( *(cntr), (i) ) : \
2928
+ CC_CNTR_ID( *(cntr) ) == CC_MAP ? CC_MAP_NEXT( *(cntr), (i) ) : \
2929
+ CC_CNTR_ID( *(cntr) ) == CC_SET ? CC_SET_NEXT( *(cntr), (i) ) : \
2930
+ NULL /* Unreachable. */ \
2931
+ ) ) \
2932
+
2933
+ #define cc_prev( cntr, i ) \
2934
+ CC_CAST_MAYBE_UNUSED( CC_EL_TY( *(cntr) ) *, ( \
2935
+ CC_WARN_DUPLICATE_SIDE_EFFECTS( cntr ), \
2936
+ CC_STATIC_ASSERT( \
2937
+ CC_CNTR_ID( *(cntr) ) == CC_LIST || \
2938
+ CC_CNTR_ID( *(cntr) ) == CC_MAP || \
2939
+ CC_CNTR_ID( *(cntr) ) == CC_SET \
2940
+ ), \
2941
+ CC_CNTR_ID( *(cntr) ) == CC_LIST ? cc_list_prev( *(cntr), (i) ) : \
2942
+ CC_CNTR_ID( *(cntr) ) == CC_MAP ? CC_MAP_PREV( *(cntr), (i) ) : \
2943
+ CC_CNTR_ID( *(cntr) ) == CC_SET ? CC_SET_PREV( *(cntr), (i) ) : \
2944
+ NULL /* Unreachable. */ \
2945
+ ) ) \
2946
+
2947
+ #define cc_for_each( ... ) CC_SELECT_ON_NUM_ARGS( cc_for_each, __VA_ARGS__ )
2948
+
2949
+ #define cc_for_each_2( cntr, i_name ) \
2950
+ for( CC_EL_TY( *(cntr) ) *i_name = cc_first( cntr ); i_name != cc_end( cntr ); i_name = cc_next( (cntr), i_name ) ) \
2951
+
2952
+ #define cc_for_each_3( cntr, key_ptr_name, i_name ) \
2953
+ for( CC_EL_TY( *(cntr) ) *i_name = cc_first( cntr ); i_name != cc_end( cntr ); i_name = cc_next( (cntr), i_name ) ) \
2954
+ for( const CC_KEY_TY( *(cntr) ) *key_ptr_name = cc_key_for( (cntr), i_name ); key_ptr_name; key_ptr_name = NULL ) \
2955
+
2956
+ #define cc_r_for_each( ... ) CC_SELECT_ON_NUM_ARGS( cc_r_for_each, __VA_ARGS__ )
2957
+
2958
+ #define cc_r_for_each_2( cntr, i_name ) \
2959
+ for( CC_EL_TY( *(cntr) ) *i_name = cc_last( cntr ); i_name != cc_r_end( cntr ); i_name = cc_prev( (cntr), i_name ) ) \
2960
+
2961
+ #define cc_r_for_each_3( cntr, key_ptr_name, i_name ) \
2962
+ for( CC_EL_TY( *(cntr) ) *i_name = cc_last( cntr ); i_name != cc_r_end( cntr ); i_name = cc_prev( (cntr), i_name ) ) \
2963
+ for( const CC_KEY_TY( *(cntr) ) *key_ptr_name = cc_key_for( (cntr), i ); key_ptr_name; key_ptr_name = NULL ) \
2964
+
2965
+ /*--------------------------------------------------------------------------------------------------------------------*/
2966
+ /* Destructor, comparison, and hash functions and custom load factors */
2967
+ /*--------------------------------------------------------------------------------------------------------------------*/
2968
+
2969
+ // Octal counters that support up to 511 of each function type and 511 load factors.
2970
+ #define CC_N_DTORS_D1 0 // D1 = digit 1, i.e. least significant digit.
2971
+ #define CC_N_DTORS_D2 0
2972
+ #define CC_N_DTORS_D3 0
2973
+ #define CC_N_CMPRS_D1 0
2974
+ #define CC_N_CMPRS_D2 0
2975
+ #define CC_N_CMPRS_D3 0
2976
+ #define CC_N_HASHS_D1 0
2977
+ #define CC_N_HASHS_D2 0
2978
+ #define CC_N_HASHS_D3 0
2979
+ #define CC_N_LOADS_D1 0
2980
+ #define CC_N_LOADS_D2 0
2981
+ #define CC_N_LOADS_D3 0
2982
+
2983
+ #define CC_CAT_3_( a, b, c ) a##b##c
2984
+ #define CC_CAT_3( a, b, c ) CC_CAT_3_( a, b, c )
2985
+ #define CC_CAT_4_( a, b, c, d ) a##b##c##d
2986
+ #define CC_CAT_4( a, b, c, d ) CC_CAT_4_( a, b, c, d )
2987
+
2988
+ // Macros that provide the current value of each counter as a three-digit octal number preceded by 0.
2989
+ // These numbers are used to form unique type and function names to plug into CC_EL_DTOR, CC_KEY_DTOR, CC_KEY_CMPR, etc.
2990
+ #define CC_N_DTORS CC_CAT_4( 0, CC_N_DTORS_D3, CC_N_DTORS_D2, CC_N_DTORS_D1 )
2991
+ #define CC_N_CMPRS CC_CAT_4( 0, CC_N_CMPRS_D3, CC_N_CMPRS_D2, CC_N_CMPRS_D1 )
2992
+ #define CC_N_HASHS CC_CAT_4( 0, CC_N_HASHS_D3, CC_N_HASHS_D2, CC_N_HASHS_D1 )
2993
+ #define CC_N_LOADS CC_CAT_4( 0, CC_N_LOADS_D3, CC_N_LOADS_D2, CC_N_LOADS_D1 )
2994
+
2995
+ // CC_FOR_EACH_XXX macros that call macro m with the first argument n, where n = [0, counter XXX ),
2996
+ // and the second argument arg.
2997
+ // These are used to construct _Generic or ternary expressions that select the correct function (or load factor) for a
2998
+ // container's key or element type (see below).
2999
+
3000
+ #define CC_CALL_MACRO( m, arg, n ) m( n, arg )
3001
+ #define CC_R1_0( m, arg, d3, d2 )
3002
+ #define CC_R1_1( m, arg, d3, d2 ) CC_CALL_MACRO( m, arg, CC_CAT_4( 0, d3, d2, 0 ) )
3003
+ #define CC_R1_2( m, arg, d3, d2 ) CC_CALL_MACRO( m, arg, CC_CAT_4( 0, d3, d2, 1 ) ) CC_R1_1( m, arg, d3, d2 )
3004
+ #define CC_R1_3( m, arg, d3, d2 ) CC_CALL_MACRO( m, arg, CC_CAT_4( 0, d3, d2, 2 ) ) CC_R1_2( m, arg, d3, d2 )
3005
+ #define CC_R1_4( m, arg, d3, d2 ) CC_CALL_MACRO( m, arg, CC_CAT_4( 0, d3, d2, 3 ) ) CC_R1_3( m, arg, d3, d2 )
3006
+ #define CC_R1_5( m, arg, d3, d2 ) CC_CALL_MACRO( m, arg, CC_CAT_4( 0, d3, d2, 4 ) ) CC_R1_4( m, arg, d3, d2 )
3007
+ #define CC_R1_6( m, arg, d3, d2 ) CC_CALL_MACRO( m, arg, CC_CAT_4( 0, d3, d2, 5 ) ) CC_R1_5( m, arg, d3, d2 )
3008
+ #define CC_R1_7( m, arg, d3, d2 ) CC_CALL_MACRO( m, arg, CC_CAT_4( 0, d3, d2, 6 ) ) CC_R1_6( m, arg, d3, d2 )
3009
+ #define CC_R1_8( m, arg, d3, d2 ) CC_CALL_MACRO( m, arg, CC_CAT_4( 0, d3, d2, 7 ) ) CC_R1_7( m, arg, d3, d2 )
3010
+ #define CC_R2_0( m, arg, d3 )
3011
+ #define CC_R2_1( m, arg, d3 ) CC_R1_8( m, arg, d3, 0 )
3012
+ #define CC_R2_2( m, arg, d3 ) CC_R1_8( m, arg, d3, 1 ) CC_R2_1( m, arg, d3 )
3013
+ #define CC_R2_3( m, arg, d3 ) CC_R1_8( m, arg, d3, 2 ) CC_R2_2( m, arg, d3 )
3014
+ #define CC_R2_4( m, arg, d3 ) CC_R1_8( m, arg, d3, 3 ) CC_R2_3( m, arg, d3 )
3015
+ #define CC_R2_5( m, arg, d3 ) CC_R1_8( m, arg, d3, 4 ) CC_R2_4( m, arg, d3 )
3016
+ #define CC_R2_6( m, arg, d3 ) CC_R1_8( m, arg, d3, 5 ) CC_R2_5( m, arg, d3 )
3017
+ #define CC_R2_7( m, arg, d3 ) CC_R1_8( m, arg, d3, 6 ) CC_R2_6( m, arg, d3 )
3018
+ #define CC_R2_8( m, arg, d3 ) CC_R1_8( m, arg, d3, 7 ) CC_R2_7( m, arg, d3 )
3019
+ #define CC_R3_0( m, arg )
3020
+ #define CC_R3_1( m, arg ) CC_R2_8( m, arg, 0 )
3021
+ #define CC_R3_2( m, arg ) CC_R2_8( m, arg, 1 ) CC_R3_1( m, arg )
3022
+ #define CC_R3_3( m, arg ) CC_R2_8( m, arg, 2 ) CC_R3_2( m, arg )
3023
+ #define CC_R3_4( m, arg ) CC_R2_8( m, arg, 3 ) CC_R3_3( m, arg )
3024
+ #define CC_R3_5( m, arg ) CC_R2_8( m, arg, 4 ) CC_R3_4( m, arg )
3025
+ #define CC_R3_6( m, arg ) CC_R2_8( m, arg, 5 ) CC_R3_5( m, arg )
3026
+ #define CC_R3_7( m, arg ) CC_R2_8( m, arg, 6 ) CC_R3_6( m, arg )
3027
+
3028
+ #define CC_FOR_OCT_COUNT( m, arg, d3, d2, d1 ) \
3029
+ CC_CAT( CC_R1_, d1 )( m, arg, d3, d2 ) \
3030
+ CC_CAT( CC_R2_, d2 )( m, arg, d3 ) \
3031
+ CC_CAT( CC_R3_, d3 )( m, arg ) \
3032
+
3033
+ #define CC_FOR_EACH_DTOR( m, arg ) CC_FOR_OCT_COUNT( m, arg, CC_N_DTORS_D3, CC_N_DTORS_D2, CC_N_DTORS_D1 )
3034
+ #define CC_FOR_EACH_CMPR( m, arg ) CC_FOR_OCT_COUNT( m, arg, CC_N_CMPRS_D3, CC_N_CMPRS_D2, CC_N_CMPRS_D1 )
3035
+ #define CC_FOR_EACH_HASH( m, arg ) CC_FOR_OCT_COUNT( m, arg, CC_N_HASHS_D3, CC_N_HASHS_D2, CC_N_HASHS_D1 )
3036
+ #define CC_FOR_EACH_LOAD( m, arg ) CC_FOR_OCT_COUNT( m, arg, CC_N_LOADS_D3, CC_N_LOADS_D2, CC_N_LOADS_D1 )
3037
+
3038
+ // Macros for inferring the destructor, comparison, or hash function or load factor associated with a container's
3039
+ // key or element type, as well as for determining whether a comparison or hash function exists for a type.
3040
+ // In C, we use the CC_FOR_EACH_XXXX macros above to create _Generic expressions that select the correct user-defined
3041
+ // function or load factor for the container's key or element types.
3042
+ // For comparison and hash functions, the list of user-defined functions is followed by a nested _Generic statement
3043
+ // containing the default functions for integer types and NULL-terminated strings, which allows the user to overwrite
3044
+ // the default functions.
3045
+ // In C++, we use the same macros combined with std::is_same and ternary expressions to emulate _Generic statements.
3046
+ // Unfortunately, the behavior is not identical because the C++ versions won't generate compile errors if the user
3047
+ // defines multiple functions (e.g. multiple destructors) for the same type.
3048
+ // Hence, it is up to the user to make sure they are not doing that if they are compiling for C++.
3049
+
3050
+ #ifdef __cplusplus
3051
+
3052
+ #define CC_EL_DTOR_SLOT( n, arg ) std::is_same<arg, cc_dtor_##n##_ty>::value ? cc_dtor_##n##_fn :
3053
+ #define CC_EL_DTOR( cntr ) \
3054
+ ( \
3055
+ CC_FOR_EACH_DTOR( CC_EL_DTOR_SLOT, CC_EL_TY( cntr ) ) \
3056
+ (void (*)( void * ))NULL \
3057
+ ) \
3058
+
3059
+ #define CC_KEY_DTOR_SLOT( n, arg ) \
3060
+ std::is_same< \
3061
+ CC_TYPEOF_XP(**arg), \
3062
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( arg ), cc_dtor_##n##_ty ) \
3063
+ >::value ? cc_dtor_##n##_fn : \
3064
+
3065
+ #define CC_KEY_DTOR( cntr ) \
3066
+ ( \
3067
+ CC_FOR_EACH_DTOR( CC_KEY_DTOR_SLOT, cntr ) \
3068
+ (void (*)( void * ))NULL \
3069
+ ) \
3070
+
3071
+ #define CC_KEY_CMPR_SLOT( n, arg ) \
3072
+ std::is_same<CC_TYPEOF_XP(**arg), CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( arg ), cc_cmpr_##n##_ty ) >::value ? \
3073
+ cc_cmpr_##n##_fn : \
3074
+
3075
+ #define CC_KEY_CMPR( cntr ) \
3076
+ ( \
3077
+ CC_FOR_EACH_CMPR( CC_KEY_CMPR_SLOT, cntr ) \
3078
+ std::is_same<CC_TYPEOF_XP(**cntr), CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), char )>::value ? \
3079
+ cc_cmpr_char : \
3080
+ std::is_same<CC_TYPEOF_XP(**cntr), CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), unsigned char )>::value ? \
3081
+ cc_cmpr_unsigned_char : \
3082
+ std::is_same<CC_TYPEOF_XP(**cntr), CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), signed char )>::value ? \
3083
+ cc_cmpr_signed_char : \
3084
+ std::is_same<CC_TYPEOF_XP(**cntr), CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), unsigned short )>::value ? \
3085
+ cc_cmpr_unsigned_short : \
3086
+ std::is_same<CC_TYPEOF_XP(**cntr), CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), short )>::value ? \
3087
+ cc_cmpr_short : \
3088
+ std::is_same<CC_TYPEOF_XP(**cntr), CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), unsigned int )>::value ? \
3089
+ cc_cmpr_unsigned_int : \
3090
+ std::is_same<CC_TYPEOF_XP(**cntr), CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), int )>::value ? \
3091
+ cc_cmpr_int : \
3092
+ std::is_same<CC_TYPEOF_XP(**cntr), CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), unsigned long )>::value ? \
3093
+ cc_cmpr_unsigned_long : \
3094
+ std::is_same<CC_TYPEOF_XP(**cntr), CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), long )>::value ? \
3095
+ cc_cmpr_long : \
3096
+ std::is_same<CC_TYPEOF_XP(**cntr), CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), unsigned long long )>::value ? \
3097
+ cc_cmpr_unsigned_long_long : \
3098
+ std::is_same<CC_TYPEOF_XP(**cntr), CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), long long )>::value ? \
3099
+ cc_cmpr_long_long : \
3100
+ std::is_same<CC_TYPEOF_XP(**cntr), CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), size_t )>::value ? \
3101
+ cc_cmpr_size_t : \
3102
+ std::is_same<CC_TYPEOF_XP(**cntr), CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), char * )>::value ? \
3103
+ cc_cmpr_c_string : \
3104
+ (int (*)( void *, void *))NULL \
3105
+ ) \
3106
+
3107
+ #define CC_KEY_HASH_SLOT( n, arg ) \
3108
+ std::is_same< \
3109
+ CC_TYPEOF_XP(**arg), \
3110
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( arg ), cc_hash_##n##_ty ) \
3111
+ >::value ? cc_hash_##n##_fn : \
3112
+
3113
+ #define CC_KEY_HASH( cntr ) \
3114
+ ( \
3115
+ CC_FOR_EACH_HASH( CC_KEY_HASH_SLOT, cntr ) \
3116
+ std::is_same<CC_TYPEOF_XP(**cntr), CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), char )>::value ? \
3117
+ cc_hash_char : \
3118
+ std::is_same<CC_TYPEOF_XP(**cntr), CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), unsigned char )>::value ? \
3119
+ cc_hash_unsigned_char : \
3120
+ std::is_same<CC_TYPEOF_XP(**cntr), CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), signed char )>::value ? \
3121
+ cc_hash_signed_char : \
3122
+ std::is_same<CC_TYPEOF_XP(**cntr), CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), unsigned short )>::value ? \
3123
+ cc_hash_unsigned_short : \
3124
+ std::is_same<CC_TYPEOF_XP(**cntr), CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), short )>::value ? \
3125
+ cc_hash_short : \
3126
+ std::is_same<CC_TYPEOF_XP(**cntr), CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), unsigned int )>::value ? \
3127
+ cc_hash_unsigned_int : \
3128
+ std::is_same<CC_TYPEOF_XP(**cntr), CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), int )>::value ? \
3129
+ cc_hash_int : \
3130
+ std::is_same<CC_TYPEOF_XP(**cntr), CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), unsigned long )>::value ? \
3131
+ cc_hash_unsigned_long : \
3132
+ std::is_same<CC_TYPEOF_XP(**cntr), CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), long )>::value ? \
3133
+ cc_hash_long : \
3134
+ std::is_same<CC_TYPEOF_XP(**cntr), CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), unsigned long long )>::value ? \
3135
+ cc_hash_unsigned_long_long : \
3136
+ std::is_same<CC_TYPEOF_XP(**cntr), CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), long long )>::value ? \
3137
+ cc_hash_long_long : \
3138
+ std::is_same<CC_TYPEOF_XP(**cntr), CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), size_t )>::value ? \
3139
+ cc_hash_size_t : \
3140
+ std::is_same<CC_TYPEOF_XP(**cntr), CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), char * )>::value ? \
3141
+ cc_hash_c_string : \
3142
+ (size_t (*)( void *))NULL \
3143
+ ) \
3144
+
3145
+ #define CC_HAS_CMPR_SLOT( n, arg ) std::is_same<arg, cc_cmpr_##n##_ty>::value ? true :
3146
+ #define CC_HAS_CMPR( ty ) \
3147
+ ( \
3148
+ std::is_same<ty, char>::value ? true : \
3149
+ std::is_same<ty, unsigned char>::value ? true : \
3150
+ std::is_same<ty, signed char>::value ? true : \
3151
+ std::is_same<ty, unsigned short>::value ? true : \
3152
+ std::is_same<ty, signed short>::value ? true : \
3153
+ std::is_same<ty, unsigned int>::value ? true : \
3154
+ std::is_same<ty, signed int>::value ? true : \
3155
+ std::is_same<ty, unsigned long>::value ? true : \
3156
+ std::is_same<ty, signed long>::value ? true : \
3157
+ std::is_same<ty, unsigned long long>::value ? true : \
3158
+ std::is_same<ty, signed long long>::value ? true : \
3159
+ std::is_same<ty, size_t>::value ? true : \
3160
+ std::is_same<ty, char *>::value ? true : \
3161
+ CC_FOR_EACH_CMPR( CC_HAS_CMPR_SLOT, ty ) \
3162
+ false \
3163
+ ) \
3164
+
3165
+ #define CC_HAS_HASH_SLOT( n, arg ) std::is_same<arg, cc_hash_##n##_ty>::value ? true :
3166
+ #define CC_HAS_HASH( ty ) \
3167
+ ( \
3168
+ std::is_same<ty, char>::value ? true : \
3169
+ std::is_same<ty, unsigned char>::value ? true : \
3170
+ std::is_same<ty, signed char>::value ? true : \
3171
+ std::is_same<ty, unsigned short>::value ? true : \
3172
+ std::is_same<ty, signed short>::value ? true : \
3173
+ std::is_same<ty, unsigned int>::value ? true : \
3174
+ std::is_same<ty, signed int>::value ? true : \
3175
+ std::is_same<ty, unsigned long>::value ? true : \
3176
+ std::is_same<ty, signed long>::value ? true : \
3177
+ std::is_same<ty, unsigned long long>::value ? true : \
3178
+ std::is_same<ty, signed long long>::value ? true : \
3179
+ std::is_same<ty, size_t>::value ? true : \
3180
+ std::is_same<ty, char *>::value ? true : \
3181
+ CC_FOR_EACH_HASH( CC_HAS_HASH_SLOT, ty ) \
3182
+ false \
3183
+ ) \
3184
+
3185
+ #define CC_KEY_LOAD_SLOT( n, arg ) \
3186
+ std::is_same< \
3187
+ CC_TYPEOF_XP(**arg), \
3188
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( arg ), cc_load_##n##_ty ) \
3189
+ >::value ? cc_load_##n##_val : \
3190
+
3191
+ #define CC_KEY_LOAD( cntr ) \
3192
+ ( \
3193
+ CC_FOR_EACH_LOAD( CC_KEY_LOAD_SLOT, cntr ) \
3194
+ CC_DEFAULT_LOAD \
3195
+ ) \
3196
+
3197
+ #else
3198
+
3199
+ #define CC_EL_DTOR_SLOT( n, arg ) cc_dtor_##n##_ty: cc_dtor_##n##_fn,
3200
+ #define CC_EL_DTOR( cntr ) \
3201
+ _Generic( (CC_EL_TY( cntr )){ 0 }, \
3202
+ CC_FOR_EACH_DTOR( CC_EL_DTOR_SLOT, ) \
3203
+ default: (void (*)( void * ))NULL \
3204
+ ) \
3205
+
3206
+ #define CC_KEY_DTOR_SLOT( n, arg ) CC_MAKE_BASE_FNPTR_TY( arg, cc_dtor_##n##_ty ): cc_dtor_##n##_fn,
3207
+ #define CC_KEY_DTOR( cntr ) \
3208
+ _Generic( (**cntr), \
3209
+ CC_FOR_EACH_DTOR( CC_KEY_DTOR_SLOT, CC_EL_TY( cntr ) ) \
3210
+ default: (void (*)( void * ))NULL \
3211
+ ) \
3212
+
3213
+ #define CC_KEY_CMPR_SLOT( n, arg ) CC_MAKE_BASE_FNPTR_TY( arg, cc_cmpr_##n##_ty ): cc_cmpr_##n##_fn,
3214
+ #define CC_KEY_CMPR( cntr ) \
3215
+ _Generic( (**cntr), \
3216
+ CC_FOR_EACH_CMPR( CC_KEY_CMPR_SLOT, CC_EL_TY( cntr ) ) \
3217
+ default: _Generic( (**cntr), \
3218
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), char ): cc_cmpr_char, \
3219
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), unsigned char ): cc_cmpr_unsigned_char, \
3220
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), signed char ): cc_cmpr_signed_char, \
3221
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), unsigned short ): cc_cmpr_unsigned_short, \
3222
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), short ): cc_cmpr_short, \
3223
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), unsigned int ): cc_cmpr_unsigned_int, \
3224
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), int ): cc_cmpr_int, \
3225
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), unsigned long ): cc_cmpr_unsigned_long, \
3226
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), long ): cc_cmpr_long, \
3227
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), unsigned long long ): cc_cmpr_unsigned_long_long, \
3228
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), long long ): cc_cmpr_long_long, \
3229
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), cc_maybe_size_t ): cc_cmpr_size_t, \
3230
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), char * ): cc_cmpr_c_string, \
3231
+ default: (int (*)( void *, void *))NULL \
3232
+ ) \
3233
+ ) \
3234
+
3235
+ #define CC_KEY_HASH_SLOT( n, arg ) CC_MAKE_BASE_FNPTR_TY( arg, cc_hash_##n##_ty ): cc_hash_##n##_fn,
3236
+ #define CC_KEY_HASH( cntr ) \
3237
+ _Generic( (**cntr), \
3238
+ CC_FOR_EACH_HASH( CC_KEY_HASH_SLOT, CC_EL_TY( cntr ) ) \
3239
+ default: _Generic( (**cntr), \
3240
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), char ): cc_hash_char, \
3241
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), unsigned char ): cc_hash_unsigned_char, \
3242
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), signed char ): cc_hash_signed_char, \
3243
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), unsigned short ): cc_hash_unsigned_short, \
3244
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), short ): cc_hash_short, \
3245
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), unsigned int ): cc_hash_unsigned_int, \
3246
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), int ): cc_hash_int, \
3247
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), unsigned long ): cc_hash_unsigned_long, \
3248
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), long ): cc_hash_long, \
3249
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), unsigned long long ): cc_hash_unsigned_long_long, \
3250
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), long long ): cc_hash_long_long, \
3251
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), cc_maybe_size_t ): cc_hash_size_t, \
3252
+ CC_MAKE_BASE_FNPTR_TY( CC_EL_TY( cntr ), char * ): cc_hash_c_string, \
3253
+ default: (size_t (*)( void *))NULL \
3254
+ ) \
3255
+ ) \
3256
+
3257
+ #define CC_HAS_CMPR_SLOT( n, arg ) cc_cmpr_##n##_ty: true,
3258
+ #define CC_HAS_CMPR( ty ) \
3259
+ _Generic( (ty){ 0 }, \
3260
+ CC_FOR_EACH_CMPR( CC_HAS_CMPR_SLOT, ) \
3261
+ default: _Generic( (ty){ 0 }, \
3262
+ char: true, \
3263
+ unsigned char: true, \
3264
+ signed char: true, \
3265
+ unsigned short: true, \
3266
+ short: true, \
3267
+ unsigned int: true, \
3268
+ int: true, \
3269
+ unsigned long: true, \
3270
+ long: true, \
3271
+ unsigned long long: true, \
3272
+ long long: true, \
3273
+ cc_maybe_size_t: true, \
3274
+ char *: true, \
3275
+ default: false \
3276
+ ) \
3277
+ ) \
3278
+
3279
+ #define CC_HAS_HASH_SLOT( n, arg ) cc_hash_##n##_ty: true,
3280
+ #define CC_HAS_HASH( ty ) \
3281
+ _Generic( (ty){ 0 }, \
3282
+ CC_FOR_EACH_HASH( CC_HAS_HASH_SLOT, ) \
3283
+ default: _Generic( (ty){ 0 }, \
3284
+ char: true, \
3285
+ unsigned char: true, \
3286
+ signed char: true, \
3287
+ unsigned short: true, \
3288
+ short: true, \
3289
+ unsigned int: true, \
3290
+ int: true, \
3291
+ unsigned long: true, \
3292
+ long: true, \
3293
+ unsigned long long: true, \
3294
+ long long: true, \
3295
+ cc_maybe_size_t: true, \
3296
+ char *: true, \
3297
+ default: false \
3298
+ ) \
3299
+ ) \
3300
+
3301
+ #define CC_KEY_LOAD_SLOT( n, arg ) CC_MAKE_BASE_FNPTR_TY( arg, cc_load_##n##_ty ): cc_load_##n##_val,
3302
+ #define CC_KEY_LOAD( cntr ) \
3303
+ _Generic( (**cntr), \
3304
+ CC_FOR_EACH_LOAD( CC_KEY_LOAD_SLOT, CC_EL_TY( cntr ) ) \
3305
+ default: CC_DEFAULT_LOAD \
3306
+ ) \
3307
+
3308
+ #endif
3309
+
3310
+ // Macros for extracting the type and function body or load factor from user-defined DTOR, CMPR, HASH, and LOAD macros.
3311
+ #define CC_1ST_ARG_( _1, ... ) _1
3312
+ #define CC_1ST_ARG( ... ) CC_1ST_ARG_( __VA_ARGS__ )
3313
+ #define CC_OTHER_ARGS_( _1, ... ) __VA_ARGS__
3314
+ #define CC_OTHER_ARGS( ... ) CC_OTHER_ARGS_( __VA_ARGS__ )
3315
+
3316
+ // Default hash and comparison functions for fundamental types.
3317
+
3318
+ // Integer types.
3319
+
3320
+ static inline int cc_cmpr_char( void *void_val_1, void *void_val_2 )
3321
+ {
3322
+ return ( *(char *)void_val_1 > *(char *)void_val_2 ) - ( *(char *)void_val_1 < *(char *)void_val_2 );
3323
+ }
3324
+
3325
+ static inline size_t cc_hash_char( void *void_val )
3326
+ {
3327
+ return *(char *)void_val;
3328
+ }
3329
+
3330
+ static inline int cc_cmpr_unsigned_char( void *void_val_1, void *void_val_2 )
3331
+ {
3332
+ return ( *(unsigned char *)void_val_1 > *(unsigned char *)void_val_2 ) -
3333
+ ( *(unsigned char *)void_val_1 < *(unsigned char *)void_val_2 );
3334
+ }
3335
+
3336
+ static inline size_t cc_hash_unsigned_char( void *void_val )
3337
+ {
3338
+ return *(unsigned char *)void_val;
3339
+ }
3340
+
3341
+ static inline int cc_cmpr_signed_char( void *void_val_1, void *void_val_2 )
3342
+ {
3343
+ return ( *(signed char *)void_val_1 > *(signed char *)void_val_2 ) -
3344
+ ( *(signed char *)void_val_1 < *(signed char *)void_val_2 );
3345
+ }
3346
+
3347
+ static inline size_t cc_hash_signed_char( void *void_val )
3348
+ {
3349
+ return *(signed char *)void_val;
3350
+ }
3351
+
3352
+ static inline int cc_cmpr_unsigned_short( void *void_val_1, void *void_val_2 )
3353
+ {
3354
+ return ( *(unsigned short *)void_val_1 > *(unsigned short *)void_val_2 ) -
3355
+ ( *(unsigned short *)void_val_1 < *(unsigned short *)void_val_2 );
3356
+ }
3357
+
3358
+ static inline size_t cc_hash_unsigned_short( void *void_val )
3359
+ {
3360
+ return *(unsigned short *)void_val * 2654435761ull;
3361
+ }
3362
+
3363
+ static inline int cc_cmpr_short( void *void_val_1, void *void_val_2 )
3364
+ {
3365
+ return ( *(short *)void_val_1 > *(short *)void_val_2 ) - ( *(short *)void_val_1 < *(short *)void_val_2 );
3366
+ }
3367
+
3368
+ static inline size_t cc_hash_short( void *void_val )
3369
+ {
3370
+ return *(short *)void_val * 2654435761ull;
3371
+ }
3372
+
3373
+ static inline int cc_cmpr_unsigned_int( void *void_val_1, void *void_val_2 )
3374
+ {
3375
+ return ( *(unsigned int *)void_val_1 > *(unsigned int *)void_val_2 ) -
3376
+ ( *(unsigned int *)void_val_1 < *(unsigned int *)void_val_2 );
3377
+ }
3378
+
3379
+ static inline size_t cc_hash_unsigned_int( void *void_val )
3380
+ {
3381
+ return *(unsigned int *)void_val * 2654435761ull;
3382
+ }
3383
+
3384
+ static inline int cc_cmpr_int( void *void_val_1, void *void_val_2 )
3385
+ {
3386
+ return ( *(int *)void_val_1 > *(int *)void_val_2 ) - ( *(int *)void_val_1 < *(int *)void_val_2 );
3387
+ }
3388
+
3389
+ static inline size_t cc_hash_int( void *void_val )
3390
+ {
3391
+ return *(int *)void_val * 2654435761ull;
3392
+ }
3393
+
3394
+ static inline int cc_cmpr_unsigned_long( void *void_val_1, void *void_val_2 )
3395
+ {
3396
+ return ( *(unsigned long *)void_val_1 > *(unsigned long *)void_val_2 ) -
3397
+ ( *(unsigned long *)void_val_1 < *(unsigned long *)void_val_2 );
3398
+ }
3399
+
3400
+ static inline size_t cc_hash_unsigned_long( void *void_val )
3401
+ {
3402
+ return *(unsigned long *)void_val * 2654435761ull;
3403
+ }
3404
+
3405
+ static inline int cc_cmpr_long( void *void_val_1, void *void_val_2 )
3406
+ {
3407
+ return ( *(long *)void_val_1 > *(long *)void_val_2 ) - ( *(long *)void_val_1 < *(long *)void_val_2 );
3408
+ }
3409
+
3410
+ static inline size_t cc_hash_long( void *void_val )
3411
+ {
3412
+ return *(long *)void_val * 2654435761ull;
3413
+ }
3414
+
3415
+ static inline int cc_cmpr_unsigned_long_long( void *void_val_1, void *void_val_2 )
3416
+ {
3417
+ return ( *(unsigned long long *)void_val_1 > *(unsigned long long *)void_val_2 ) -
3418
+ ( *(unsigned long long *)void_val_1 < *(unsigned long long *)void_val_2 );
3419
+ }
3420
+
3421
+ static inline size_t cc_hash_unsigned_long_long( void *void_val )
3422
+ {
3423
+ return *(unsigned long long *)void_val * 2654435761ull;
3424
+ }
3425
+
3426
+ static inline int cc_cmpr_long_long( void *void_val_1, void *void_val_2 )
3427
+ {
3428
+ return ( *(long long *)void_val_1 > *(long long *)void_val_2 ) -
3429
+ ( *(long long *)void_val_1 < *(long long *)void_val_2 );
3430
+ }
3431
+
3432
+ static inline size_t cc_hash_long_long( void *void_val )
3433
+ {
3434
+ return *(long long *)void_val * 2654435761ull;
3435
+ }
3436
+
3437
+ // size_t could be an alias for a fundamental integer type or a distinct type.
3438
+ // Hence, in C we have to handle it as a special case so that it doesn't clash with another type in _Generic statements.
3439
+ // If size_t is an alias, cc_maybe_size_t will be a dummy type used in no other context.
3440
+ // Otherwise, cc_maybe_size_t will be an alias for size_t.
3441
+
3442
+ #ifndef __cplusplus
3443
+
3444
+ typedef struct { char nothing; } cc_size_t_dummy;
3445
+
3446
+ typedef CC_TYPEOF_XP(
3447
+ _Generic( (size_t){ 0 },
3448
+ unsigned short: (cc_size_t_dummy){ 0 },
3449
+ short: (cc_size_t_dummy){ 0 },
3450
+ unsigned int: (cc_size_t_dummy){ 0 },
3451
+ int: (cc_size_t_dummy){ 0 },
3452
+ unsigned long: (cc_size_t_dummy){ 0 },
3453
+ long: (cc_size_t_dummy){ 0 },
3454
+ unsigned long long: (cc_size_t_dummy){ 0 },
3455
+ long long: (cc_size_t_dummy){ 0 },
3456
+ default: (size_t){ 0 }
3457
+ )
3458
+ ) cc_maybe_size_t;
3459
+
3460
+ #endif
3461
+
3462
+ static inline int cc_cmpr_size_t( void *void_val_1, void *void_val_2 )
3463
+ {
3464
+ return ( *(size_t *)void_val_1 > *(size_t *)void_val_2 ) - ( *(size_t *)void_val_1 < *(size_t *)void_val_2 );
3465
+ }
3466
+
3467
+ static inline size_t cc_hash_size_t( void *void_val )
3468
+ {
3469
+ return *(size_t *)void_val * 2654435761ull;
3470
+ }
3471
+
3472
+ // Null-terminated C strings.
3473
+ // We use FNV-1a because newer, faster alternatives that process word-sized chunks require prior knowledge of the
3474
+ // string's length.
3475
+
3476
+ static inline int cc_cmpr_c_string( void *void_val_1, void *void_val_2 )
3477
+ {
3478
+ return strcmp( *(char **)void_val_1, *(char **)void_val_2 );
3479
+ }
3480
+
3481
+ #if SIZE_MAX == 0xFFFFFFFF // 32-bit size_t.
3482
+
3483
+ static inline size_t cc_hash_c_string( void *void_val )
3484
+ {
3485
+ char *val = *(char **)void_val;
3486
+ size_t hash = 0x01000193;
3487
+ while( *val )
3488
+ hash = ( (unsigned char)*val++ ^ hash ) * 0x811c9dc5;
3489
+
3490
+ return hash;
3491
+ }
3492
+
3493
+ #elif SIZE_MAX == 0xFFFFFFFFFFFFFFFF // 64-bit size_t.
3494
+
3495
+ static inline size_t cc_hash_c_string( void *void_val )
3496
+ {
3497
+ char *val = *(char **)void_val;
3498
+ size_t hash = 0xcbf29ce484222325;
3499
+ while( *val )
3500
+ hash = ( (unsigned char)*val++ ^ hash ) * 0x100000001b3;
3501
+
3502
+ return hash;
3503
+ }
3504
+
3505
+ #else // Strange size_t.
3506
+
3507
+ static inline size_t cc_hash_c_string( void *void_val )
3508
+ {
3509
+ char *val = *(char **)void_val;
3510
+ size_t hash = 0;
3511
+ while( *val )
3512
+ hash = hash * 131 + (unsigned char)*val++;
3513
+
3514
+ return hash;
3515
+ }
3516
+
3517
+ #endif
3518
+
3519
+ #endif
3520
+ #else/*---------------------------------------------------------------------------------------------------------------*/
3521
+ /* */
3522
+ /* DEFINING DESTRUCTOR, COMPARISON, OR HASH FUNCTION OR LOAD FACTOR MODE */
3523
+ /* */
3524
+ /*--------------------------------------------------------------------------------------------------------------------*/
3525
+
3526
+ #ifdef CC_DTOR
3527
+
3528
+ // Convert the user-defined CC_DTOR macro into a cc_dtor_XXXX_ty and cc_dtor_XXXX_fn pair that can be pluged into the
3529
+ // CC_GET_EL_DTOR and CC_GET_KEY_DTOR macros above.
3530
+
3531
+ typedef CC_TYPEOF_TY( CC_1ST_ARG( CC_DTOR ) ) CC_CAT_3( cc_dtor_, CC_N_DTORS, _ty );
3532
+
3533
+ static inline void CC_CAT_3( cc_dtor_, CC_N_DTORS, _fn )( void *void_val )
3534
+ {
3535
+ CC_CAT_3( cc_dtor_, CC_N_DTORS, _ty ) val = *(CC_CAT_3( cc_dtor_, CC_N_DTORS, _ty ) *)void_val;
3536
+ CC_OTHER_ARGS( CC_DTOR )
3537
+ }
3538
+
3539
+ // Increment DTOR counter.
3540
+ #if CC_N_DTORS_D1 == 0
3541
+ #undef CC_N_DTORS_D1
3542
+ #define CC_N_DTORS_D1 1
3543
+ #elif CC_N_DTORS_D1 == 1
3544
+ #undef CC_N_DTORS_D1
3545
+ #define CC_N_DTORS_D1 2
3546
+ #elif CC_N_DTORS_D1 == 2
3547
+ #undef CC_N_DTORS_D1
3548
+ #define CC_N_DTORS_D1 3
3549
+ #elif CC_N_DTORS_D1 == 3
3550
+ #undef CC_N_DTORS_D1
3551
+ #define CC_N_DTORS_D1 4
3552
+ #elif CC_N_DTORS_D1 == 4
3553
+ #undef CC_N_DTORS_D1
3554
+ #define CC_N_DTORS_D1 5
3555
+ #elif CC_N_DTORS_D1 == 5
3556
+ #undef CC_N_DTORS_D1
3557
+ #define CC_N_DTORS_D1 6
3558
+ #elif CC_N_DTORS_D1 == 6
3559
+ #undef CC_N_DTORS_D1
3560
+ #define CC_N_DTORS_D1 7
3561
+ #elif CC_N_DTORS_D1 == 7
3562
+ #undef CC_N_DTORS_D1
3563
+ #define CC_N_DTORS_D1 0
3564
+ #if CC_N_DTORS_D2 == 0
3565
+ #undef CC_N_DTORS_D2
3566
+ #define CC_N_DTORS_D2 1
3567
+ #elif CC_N_DTORS_D2 == 1
3568
+ #undef CC_N_DTORS_D2
3569
+ #define CC_N_DTORS_D2 2
3570
+ #elif CC_N_DTORS_D2 == 2
3571
+ #undef CC_N_DTORS_D2
3572
+ #define CC_N_DTORS_D2 3
3573
+ #elif CC_N_DTORS_D2 == 3
3574
+ #undef CC_N_DTORS_D2
3575
+ #define CC_N_DTORS_D2 4
3576
+ #elif CC_N_DTORS_D2 == 4
3577
+ #undef CC_N_DTORS_D2
3578
+ #define CC_N_DTORS_D2 5
3579
+ #elif CC_N_DTORS_D2 == 5
3580
+ #undef CC_N_DTORS_D2
3581
+ #define CC_N_DTORS_D2 6
3582
+ #elif CC_N_DTORS_D2 == 6
3583
+ #undef CC_N_DTORS_D2
3584
+ #define CC_N_DTORS_D2 7
3585
+ #elif CC_N_DTORS_D2 == 7
3586
+ #undef CC_N_DTORS_D2
3587
+ #define CC_N_DTORS_D2 0
3588
+ #if CC_N_DTORS_D3 == 0
3589
+ #undef CC_N_DTORS_D3
3590
+ #define CC_N_DTORS_D3 1
3591
+ #elif CC_N_DTORS_D3 == 1
3592
+ #undef CC_N_DTORS_D3
3593
+ #define CC_N_DTORS_D3 2
3594
+ #elif CC_N_DTORS_D3 == 2
3595
+ #undef CC_N_DTORS_D3
3596
+ #define CC_N_DTORS_D3 3
3597
+ #elif CC_N_DTORS_D3 == 3
3598
+ #undef CC_N_DTORS_D3
3599
+ #define CC_N_DTORS_D3 4
3600
+ #elif CC_N_DTORS_D3 == 4
3601
+ #undef CC_N_DTORS_D3
3602
+ #define CC_N_DTORS_D3 5
3603
+ #elif CC_N_DTORS_D3 == 5
3604
+ #undef CC_N_DTORS_D3
3605
+ #define CC_N_DTORS_D3 6
3606
+ #elif CC_N_DTORS_D3 == 6
3607
+ #undef CC_N_DTORS_D3
3608
+ #define CC_N_DTORS_D3 7
3609
+ #elif CC_N_DTORS_D3 == 7
3610
+ #error Sorry, number of destructor functions is limited to 511.
3611
+ #endif
3612
+ #endif
3613
+ #endif
3614
+
3615
+ #undef CC_DTOR
3616
+ #endif
3617
+
3618
+ #ifdef CC_CMPR
3619
+
3620
+ typedef CC_TYPEOF_TY( CC_1ST_ARG( CC_CMPR ) ) CC_CAT_3( cc_cmpr_, CC_N_CMPRS, _ty );
3621
+
3622
+ static inline int CC_CAT_3( cc_cmpr_, CC_N_CMPRS, _fn )( void *void_val_1, void *void_val_2 )
3623
+ {
3624
+ CC_CAT_3( cc_cmpr_, CC_N_CMPRS, _ty ) val_1 = *(CC_CAT_3( cc_cmpr_, CC_N_CMPRS, _ty ) *)void_val_1;
3625
+ CC_CAT_3( cc_cmpr_, CC_N_CMPRS, _ty ) val_2 = *(CC_CAT_3( cc_cmpr_, CC_N_CMPRS, _ty ) *)void_val_2;
3626
+ CC_OTHER_ARGS( CC_CMPR )
3627
+ }
3628
+
3629
+ #if CC_N_CMPRS_D1 == 0
3630
+ #undef CC_N_CMPRS_D1
3631
+ #define CC_N_CMPRS_D1 1
3632
+ #elif CC_N_CMPRS_D1 == 1
3633
+ #undef CC_N_CMPRS_D1
3634
+ #define CC_N_CMPRS_D1 2
3635
+ #elif CC_N_CMPRS_D1 == 2
3636
+ #undef CC_N_CMPRS_D1
3637
+ #define CC_N_CMPRS_D1 3
3638
+ #elif CC_N_CMPRS_D1 == 3
3639
+ #undef CC_N_CMPRS_D1
3640
+ #define CC_N_CMPRS_D1 4
3641
+ #elif CC_N_CMPRS_D1 == 4
3642
+ #undef CC_N_CMPRS_D1
3643
+ #define CC_N_CMPRS_D1 5
3644
+ #elif CC_N_CMPRS_D1 == 5
3645
+ #undef CC_N_CMPRS_D1
3646
+ #define CC_N_CMPRS_D1 6
3647
+ #elif CC_N_CMPRS_D1 == 6
3648
+ #undef CC_N_CMPRS_D1
3649
+ #define CC_N_CMPRS_D1 7
3650
+ #elif CC_N_CMPRS_D1 == 7
3651
+ #undef CC_N_CMPRS_D1
3652
+ #define CC_N_CMPRS_D1 0
3653
+ #if CC_N_CMPRS_D2 == 0
3654
+ #undef CC_N_CMPRS_D2
3655
+ #define CC_N_CMPRS_D2 1
3656
+ #elif CC_N_CMPRS_D2 == 1
3657
+ #undef CC_N_CMPRS_D2
3658
+ #define CC_N_CMPRS_D2 2
3659
+ #elif CC_N_CMPRS_D2 == 2
3660
+ #undef CC_N_CMPRS_D2
3661
+ #define CC_N_CMPRS_D2 3
3662
+ #elif CC_N_CMPRS_D2 == 3
3663
+ #undef CC_N_CMPRS_D2
3664
+ #define CC_N_CMPRS_D2 4
3665
+ #elif CC_N_CMPRS_D2 == 4
3666
+ #undef CC_N_CMPRS_D2
3667
+ #define CC_N_CMPRS_D2 5
3668
+ #elif CC_N_CMPRS_D2 == 5
3669
+ #undef CC_N_CMPRS_D2
3670
+ #define CC_N_CMPRS_D2 6
3671
+ #elif CC_N_CMPRS_D2 == 6
3672
+ #undef CC_N_CMPRS_D2
3673
+ #define CC_N_CMPRS_D2 7
3674
+ #elif CC_N_CMPRS_D2 == 7
3675
+ #undef CC_N_CMPRS_D2
3676
+ #define CC_N_CMPRS_D2 0
3677
+ #if CC_N_CMPRS_D3 == 0
3678
+ #undef CC_N_CMPRS_D3
3679
+ #define CC_N_CMPRS_D3 1
3680
+ #elif CC_N_CMPRS_D3 == 1
3681
+ #undef CC_N_CMPRS_D3
3682
+ #define CC_N_CMPRS_D3 2
3683
+ #elif CC_N_CMPRS_D3 == 2
3684
+ #undef CC_N_CMPRS_D3
3685
+ #define CC_N_CMPRS_D3 3
3686
+ #elif CC_N_CMPRS_D3 == 3
3687
+ #undef CC_N_CMPRS_D3
3688
+ #define CC_N_CMPRS_D3 4
3689
+ #elif CC_N_CMPRS_D3 == 4
3690
+ #undef CC_N_CMPRS_D3
3691
+ #define CC_N_CMPRS_D3 5
3692
+ #elif CC_N_CMPRS_D3 == 5
3693
+ #undef CC_N_CMPRS_D3
3694
+ #define CC_N_CMPRS_D3 6
3695
+ #elif CC_N_CMPRS_D3 == 6
3696
+ #undef CC_N_CMPRS_D3
3697
+ #define CC_N_CMPRS_D3 7
3698
+ #elif CC_N_CMPRS_D3 == 7
3699
+ #error Sorry, number of comparison functions is limited to 511.
3700
+ #endif
3701
+ #endif
3702
+ #endif
3703
+
3704
+ #undef CC_CMPR
3705
+ #endif
3706
+
3707
+ #ifdef CC_HASH
3708
+
3709
+ typedef CC_TYPEOF_TY( CC_1ST_ARG( CC_HASH ) ) CC_CAT_3( cc_hash_, CC_N_HASHS, _ty );
3710
+
3711
+ static inline size_t CC_CAT_3( cc_hash_, CC_N_HASHS, _fn )( void *void_val )
3712
+ {
3713
+ CC_CAT_3( cc_hash_, CC_N_HASHS, _ty ) val = *(CC_CAT_3( cc_hash_, CC_N_HASHS, _ty ) *)void_val;
3714
+ CC_OTHER_ARGS( CC_HASH )
3715
+ }
3716
+
3717
+ #if CC_N_HASHS_D1 == 0
3718
+ #undef CC_N_HASHS_D1
3719
+ #define CC_N_HASHS_D1 1
3720
+ #elif CC_N_HASHS_D1 == 1
3721
+ #undef CC_N_HASHS_D1
3722
+ #define CC_N_HASHS_D1 2
3723
+ #elif CC_N_HASHS_D1 == 2
3724
+ #undef CC_N_HASHS_D1
3725
+ #define CC_N_HASHS_D1 3
3726
+ #elif CC_N_HASHS_D1 == 3
3727
+ #undef CC_N_HASHS_D1
3728
+ #define CC_N_HASHS_D1 4
3729
+ #elif CC_N_HASHS_D1 == 4
3730
+ #undef CC_N_HASHS_D1
3731
+ #define CC_N_HASHS_D1 5
3732
+ #elif CC_N_HASHS_D1 == 5
3733
+ #undef CC_N_HASHS_D1
3734
+ #define CC_N_HASHS_D1 6
3735
+ #elif CC_N_HASHS_D1 == 6
3736
+ #undef CC_N_HASHS_D1
3737
+ #define CC_N_HASHS_D1 7
3738
+ #elif CC_N_HASHS_D1 == 7
3739
+ #undef CC_N_HASHS_D1
3740
+ #define CC_N_HASHS_D1 0
3741
+ #if CC_N_HASHS_D2 == 0
3742
+ #undef CC_N_HASHS_D2
3743
+ #define CC_N_HASHS_D2 1
3744
+ #elif CC_N_HASHS_D2 == 1
3745
+ #undef CC_N_HASHS_D2
3746
+ #define CC_N_HASHS_D2 2
3747
+ #elif CC_N_HASHS_D2 == 2
3748
+ #undef CC_N_HASHS_D2
3749
+ #define CC_N_HASHS_D2 3
3750
+ #elif CC_N_HASHS_D2 == 3
3751
+ #undef CC_N_HASHS_D2
3752
+ #define CC_N_HASHS_D2 4
3753
+ #elif CC_N_HASHS_D2 == 4
3754
+ #undef CC_N_HASHS_D2
3755
+ #define CC_N_HASHS_D2 5
3756
+ #elif CC_N_HASHS_D2 == 5
3757
+ #undef CC_N_HASHS_D2
3758
+ #define CC_N_HASHS_D2 6
3759
+ #elif CC_N_HASHS_D2 == 6
3760
+ #undef CC_N_HASHS_D2
3761
+ #define CC_N_HASHS_D2 7
3762
+ #elif CC_N_HASHS_D2 == 7
3763
+ #undef CC_N_HASHS_D2
3764
+ #define CC_N_HASHS_D2 0
3765
+ #if CC_N_HASHS_D3 == 0
3766
+ #undef CC_N_HASHS_D3
3767
+ #define CC_N_HASHS_D3 1
3768
+ #elif CC_N_HASHS_D3 == 1
3769
+ #undef CC_N_HASHS_D3
3770
+ #define CC_N_HASHS_D3 2
3771
+ #elif CC_N_HASHS_D3 == 2
3772
+ #undef CC_N_HASHS_D3
3773
+ #define CC_N_HASHS_D3 3
3774
+ #elif CC_N_HASHS_D3 == 3
3775
+ #undef CC_N_HASHS_D3
3776
+ #define CC_N_HASHS_D3 4
3777
+ #elif CC_N_HASHS_D3 == 4
3778
+ #undef CC_N_HASHS_D3
3779
+ #define CC_N_HASHS_D3 5
3780
+ #elif CC_N_HASHS_D3 == 5
3781
+ #undef CC_N_HASHS_D3
3782
+ #define CC_N_HASHS_D3 6
3783
+ #elif CC_N_HASHS_D3 == 6
3784
+ #undef CC_N_HASHS_D3
3785
+ #define CC_N_HASHS_D3 7
3786
+ #elif CC_N_HASHS_D3 == 7
3787
+ #error Sorry, number of hash functions is limited to 511.
3788
+ #endif
3789
+ #endif
3790
+ #endif
3791
+
3792
+ #undef CC_HASH
3793
+ #endif
3794
+
3795
+ #ifdef CC_LOAD
3796
+
3797
+ typedef CC_TYPEOF_TY( CC_1ST_ARG( CC_LOAD ) ) CC_CAT_3( cc_load_, CC_N_LOADS, _ty );
3798
+
3799
+ const double CC_CAT_3( cc_load_, CC_N_LOADS, _val ) = CC_OTHER_ARGS( CC_LOAD );
3800
+
3801
+ #if CC_N_LOADS_D1 == 0
3802
+ #undef CC_N_LOADS_D1
3803
+ #define CC_N_LOADS_D1 1
3804
+ #elif CC_N_LOADS_D1 == 1
3805
+ #undef CC_N_LOADS_D1
3806
+ #define CC_N_LOADS_D1 2
3807
+ #elif CC_N_LOADS_D1 == 2
3808
+ #undef CC_N_LOADS_D1
3809
+ #define CC_N_LOADS_D1 3
3810
+ #elif CC_N_LOADS_D1 == 3
3811
+ #undef CC_N_LOADS_D1
3812
+ #define CC_N_LOADS_D1 4
3813
+ #elif CC_N_LOADS_D1 == 4
3814
+ #undef CC_N_LOADS_D1
3815
+ #define CC_N_LOADS_D1 5
3816
+ #elif CC_N_LOADS_D1 == 5
3817
+ #undef CC_N_LOADS_D1
3818
+ #define CC_N_LOADS_D1 6
3819
+ #elif CC_N_LOADS_D1 == 6
3820
+ #undef CC_N_LOADS_D1
3821
+ #define CC_N_LOADS_D1 7
3822
+ #elif CC_N_LOADS_D1 == 7
3823
+ #undef CC_N_LOADS_D1
3824
+ #define CC_N_LOADS_D1 0
3825
+ #if CC_N_LOADS_D2 == 0
3826
+ #undef CC_N_LOADS_D2
3827
+ #define CC_N_LOADS_D2 1
3828
+ #elif CC_N_LOADS_D2 == 1
3829
+ #undef CC_N_LOADS_D2
3830
+ #define CC_N_LOADS_D2 2
3831
+ #elif CC_N_LOADS_D2 == 2
3832
+ #undef CC_N_LOADS_D2
3833
+ #define CC_N_LOADS_D2 3
3834
+ #elif CC_N_LOADS_D2 == 3
3835
+ #undef CC_N_LOADS_D2
3836
+ #define CC_N_LOADS_D2 4
3837
+ #elif CC_N_LOADS_D2 == 4
3838
+ #undef CC_N_LOADS_D2
3839
+ #define CC_N_LOADS_D2 5
3840
+ #elif CC_N_LOADS_D2 == 5
3841
+ #undef CC_N_LOADS_D2
3842
+ #define CC_N_LOADS_D2 6
3843
+ #elif CC_N_LOADS_D2 == 6
3844
+ #undef CC_N_LOADS_D2
3845
+ #define CC_N_LOADS_D2 7
3846
+ #elif CC_N_LOADS_D2 == 7
3847
+ #undef CC_N_LOADS_D2
3848
+ #define CC_N_LOADS_D2 0
3849
+ #if CC_N_LOADS_D3 == 0
3850
+ #undef CC_N_LOADS_D3
3851
+ #define CC_N_LOADS_D3 1
3852
+ #elif CC_N_LOADS_D3 == 1
3853
+ #undef CC_N_LOADS_D3
3854
+ #define CC_N_LOADS_D3 2
3855
+ #elif CC_N_LOADS_D3 == 2
3856
+ #undef CC_N_LOADS_D3
3857
+ #define CC_N_LOADS_D3 3
3858
+ #elif CC_N_LOADS_D3 == 3
3859
+ #undef CC_N_LOADS_D3
3860
+ #define CC_N_LOADS_D3 4
3861
+ #elif CC_N_LOADS_D3 == 4
3862
+ #undef CC_N_LOADS_D3
3863
+ #define CC_N_LOADS_D3 5
3864
+ #elif CC_N_LOADS_D3 == 5
3865
+ #undef CC_N_LOADS_D3
3866
+ #define CC_N_LOADS_D3 6
3867
+ #elif CC_N_LOADS_D3 == 6
3868
+ #undef CC_N_LOADS_D3
3869
+ #define CC_N_LOADS_D3 7
3870
+ #elif CC_N_LOADS_D3 == 7
3871
+ #error Sorry, number of load factors is limited to 511.
3872
+ #endif
3873
+ #endif
3874
+ #endif
3875
+
3876
+ #undef CC_LOAD
3877
+ #endif
3878
+
3879
+ #endif