Thu, 23 May 2024 20:29:28 +0200
fix members inherited by macro or include are not documented
1.1 --- a/CHANGELOG Thu May 23 19:29:14 2024 +0200 1.2 +++ b/CHANGELOG Thu May 23 20:29:28 2024 +0200 1.3 @@ -11,7 +11,7 @@ 1.4 * adds cx_sprintf() and several more variants 1.5 * adds runtime constants to read out the actual SBO sizes 1.6 * adds improved version of UCX 2 Test framework (now a self-contained header) 1.7 - * the cx_compare_func symbol is now also declared by compare.h 1.8 + * the cx_compare_func symbol is now declared by compare.h 1.9 * fixes wrong link from UCX 2 documentation to UCX 3 documentation 1.10 * fixes critical bug that produced wrong results when comparing lists of different type but same size 1.11 * removes flag_removal function from iterator (unfortunately breaks binary compatibility)
2.1 --- a/docs/src/features.md Thu May 23 19:29:14 2024 +0200 2.2 +++ b/docs/src/features.md Thu May 23 20:29:28 2024 +0200 2.3 @@ -187,7 +187,7 @@ 2.4 `slot` and `kv_data` fields (for example when iterating over maps). 2.5 2.6 If the predefined fields are insufficient for your use case, you can alternatively create your own iterator structure 2.7 -and place the `CX_ITERATOR_BASE` macro inside. 2.8 +and place the `CX_ITERATOR_BASE` macro as first member of that structure. 2.9 2.10 Usually an iterator is not mutating the collection it is iterating over. 2.11 In some programming languages it is even disallowed to change the collection while iterating with foreach. 2.12 @@ -204,10 +204,10 @@ 2.13 2.14 Collections in UCX 3 have several common features. 2.15 If you want to implement an own collection data type that uses the same features, you can use the 2.16 -`CX_COLLECTION_MEMBERS` macro at the beginning of your struct to roll out all members a usual UCX collection has. 2.17 +`CX_COLLECTION_BASE` macro at the beginning of your struct to roll out all members a usual UCX collection has. 2.18 ```c 2.19 struct my_fancy_collection_s { 2.20 - CX_COLLECTION_MEMBERS 2.21 + CX_COLLECTION_BASE; 2.22 struct my_collection_data_s *data; 2.23 }; 2.24 ``` 2.25 @@ -225,21 +225,11 @@ 2.26 2.27 *Header file:* [list.h](api/list_8h.html) 2.28 2.29 -This header defines a common interface for all list implementations, which is basically as simple as the following 2.30 -structure. 2.31 -```c 2.32 -struct cx_list_s { 2.33 - CX_COLLECTION_MEMBERS // size, capacity, etc. 2.34 - cx_list_class const *cl; // The list class definition 2.35 -}; 2.36 -``` 2.37 -The actual structure contains one more class pointer that is used when wrapping a list into a pointer-aware list 2.38 -with `cxListStorePointers()`. What this means, is that - if you want to implement your own list structure - you 2.39 -only need to cover the case where the list is storing copies of your objects. 2.40 +This header defines a common interface for all list implementations. 2.41 2.42 -UCX comes with two common list implementations (linked list and array list) that should cover most use cases. 2.43 -But if you feel the need to implement an own list, the only thing you need to do is to define a struct where 2.44 -`struct cx_list_s`, and set an appropriate list class that implements the functionality. 2.45 +UCX already comes with two common list implementations (linked list and array list) that should cover most use cases. 2.46 +But if you feel the need to implement an own list, the only thing you need to do is to define a struct with a 2.47 +`struct cx_list_s` as first member, and set an appropriate list class that implements the functionality. 2.48 It is strongly recommended that this class is shared among all instances of the same list type, because otherwise 2.49 the `cxListCompare` function cannot use the optimized implementation of your class and will instead fall back to 2.50 using iterators to compare the contents element-wise.
3.1 --- a/src/Makefile Thu May 23 19:29:14 2024 +0200 3.2 +++ b/src/Makefile Thu May 23 20:29:28 2024 +0200 3.3 @@ -67,7 +67,8 @@ 3.4 $(CC) -o $@ $(CFLAGS) -c $< 3.5 3.6 $(build_dir)/array_list$(OBJ_EXT): array_list.c cx/array_list.h cx/list.h \ 3.7 - cx/common.h cx/collection.h cx/allocator.h cx/iterator.h cx/compare.h 3.8 + cx/common.h cx/collection.h cx/allocator.h cx/iterator.h cx/compare.h \ 3.9 + cx/compare.h 3.10 @echo "Compiling $<" 3.11 $(CC) -o $@ $(CFLAGS) -c $< 3.12 3.13 @@ -85,8 +86,8 @@ 3.14 $(CC) -o $@ $(CFLAGS) -c $< 3.15 3.16 $(build_dir)/hash_map$(OBJ_EXT): hash_map.c cx/hash_map.h cx/map.h \ 3.17 - cx/common.h cx/collection.h cx/allocator.h cx/iterator.h cx/string.h \ 3.18 - cx/hash_key.h cx/utils.h 3.19 + cx/common.h cx/collection.h cx/allocator.h cx/iterator.h cx/compare.h \ 3.20 + cx/string.h cx/hash_key.h cx/utils.h 3.21 @echo "Compiling $<" 3.22 $(CC) -o $@ $(CFLAGS) -c $< 3.23 3.24 @@ -96,17 +97,17 @@ 3.25 3.26 $(build_dir)/linked_list$(OBJ_EXT): linked_list.c cx/linked_list.h \ 3.27 cx/common.h cx/list.h cx/collection.h cx/allocator.h cx/iterator.h \ 3.28 - cx/utils.h cx/compare.h 3.29 + cx/compare.h cx/utils.h cx/compare.h 3.30 @echo "Compiling $<" 3.31 $(CC) -o $@ $(CFLAGS) -c $< 3.32 3.33 $(build_dir)/list$(OBJ_EXT): list.c cx/list.h cx/common.h cx/collection.h \ 3.34 - cx/allocator.h cx/iterator.h 3.35 + cx/allocator.h cx/iterator.h cx/compare.h 3.36 @echo "Compiling $<" 3.37 $(CC) -o $@ $(CFLAGS) -c $< 3.38 3.39 $(build_dir)/map$(OBJ_EXT): map.c cx/map.h cx/common.h cx/collection.h \ 3.40 - cx/allocator.h cx/iterator.h cx/string.h cx/hash_key.h 3.41 + cx/allocator.h cx/iterator.h cx/compare.h cx/string.h cx/hash_key.h 3.42 @echo "Compiling $<" 3.43 $(CC) -o $@ $(CFLAGS) -c $< 3.44 3.45 @@ -130,7 +131,7 @@ 3.46 $(CC) -o $@ $(CFLAGS) -c $< 3.47 3.48 $(build_dir)/tree$(OBJ_EXT): tree.c cx/tree.h cx/common.h cx/iterator.h \ 3.49 - cx/array_list.h cx/list.h cx/collection.h cx/allocator.h 3.50 + cx/array_list.h cx/list.h cx/collection.h cx/allocator.h cx/compare.h 3.51 @echo "Compiling $<" 3.52 $(CC) -o $@ $(CFLAGS) -c $< 3.53
4.1 --- a/src/array_list.c Thu May 23 19:29:14 2024 +0200 4.2 +++ b/src/array_list.c Thu May 23 20:29:28 2024 +0200 4.3 @@ -191,21 +191,21 @@ 4.4 4.5 char *ptr = arl->data; 4.6 4.7 - if (list->simple_destructor) { 4.8 - for (size_t i = 0; i < list->size; i++) { 4.9 + if (list->base.simple_destructor) { 4.10 + for (size_t i = 0; i < list->base.size; i++) { 4.11 cx_invoke_simple_destructor(list, ptr); 4.12 - ptr += list->item_size; 4.13 + ptr += list->base.item_size; 4.14 } 4.15 } 4.16 - if (list->advanced_destructor) { 4.17 - for (size_t i = 0; i < list->size; i++) { 4.18 + if (list->base.advanced_destructor) { 4.19 + for (size_t i = 0; i < list->base.size; i++) { 4.20 cx_invoke_advanced_destructor(list, ptr); 4.21 - ptr += list->item_size; 4.22 + ptr += list->base.item_size; 4.23 } 4.24 } 4.25 4.26 - cxFree(list->allocator, arl->data); 4.27 - cxFree(list->allocator, list); 4.28 + cxFree(list->base.allocator, arl->data); 4.29 + cxFree(list->base.allocator, list); 4.30 } 4.31 4.32 static size_t cx_arl_insert_array( 4.33 @@ -215,25 +215,25 @@ 4.34 size_t n 4.35 ) { 4.36 // out of bounds and special case check 4.37 - if (index > list->size || n == 0) return 0; 4.38 + if (index > list->base.size || n == 0) return 0; 4.39 4.40 // get a correctly typed pointer to the list 4.41 cx_array_list *arl = (cx_array_list *) list; 4.42 4.43 // do we need to move some elements? 4.44 - if (index < list->size) { 4.45 + if (index < list->base.size) { 4.46 char const *first_to_move = (char const *) arl->data; 4.47 - first_to_move += index * list->item_size; 4.48 - size_t elems_to_move = list->size - index; 4.49 + first_to_move += index * list->base.item_size; 4.50 + size_t elems_to_move = list->base.size - index; 4.51 size_t start_of_moved = index + n; 4.52 4.53 if (CX_ARRAY_SUCCESS != cx_array_copy( 4.54 &arl->data, 4.55 - &list->size, 4.56 + &list->base.size, 4.57 &arl->capacity, 4.58 start_of_moved, 4.59 first_to_move, 4.60 - list->item_size, 4.61 + list->base.item_size, 4.62 elems_to_move, 4.63 &arl->reallocator 4.64 )) { 4.65 @@ -249,11 +249,11 @@ 4.66 // place the new elements 4.67 if (CX_ARRAY_SUCCESS == cx_array_copy( 4.68 &arl->data, 4.69 - &list->size, 4.70 + &list->base.size, 4.71 &arl->capacity, 4.72 index, 4.73 array, 4.74 - list->item_size, 4.75 + list->base.item_size, 4.76 n, 4.77 &arl->reallocator 4.78 )) { 4.79 @@ -278,7 +278,7 @@ 4.80 int prepend 4.81 ) { 4.82 struct cx_list_s *list = iter->src_handle.m; 4.83 - if (iter->index < list->size) { 4.84 + if (iter->index < list->base.size) { 4.85 int result = cx_arl_insert_element( 4.86 list, 4.87 iter->index + 1 - prepend, 4.88 @@ -286,12 +286,12 @@ 4.89 ); 4.90 if (result == 0 && prepend != 0) { 4.91 iter->index++; 4.92 - iter->elem_handle = ((char *) iter->elem_handle) + list->item_size; 4.93 + iter->elem_handle = ((char *) iter->elem_handle) + list->base.item_size; 4.94 } 4.95 return result; 4.96 } else { 4.97 - int result = cx_arl_insert_element(list, list->size, elem); 4.98 - iter->index = list->size; 4.99 + int result = cx_arl_insert_element(list, list->base.size, elem); 4.100 + iter->index = list->base.size; 4.101 return result; 4.102 } 4.103 } 4.104 @@ -303,28 +303,28 @@ 4.105 cx_array_list *arl = (cx_array_list *) list; 4.106 4.107 // out-of-bounds check 4.108 - if (index >= list->size) { 4.109 + if (index >= list->base.size) { 4.110 return 1; 4.111 } 4.112 4.113 // content destruction 4.114 - cx_invoke_destructor(list, ((char *) arl->data) + index * list->item_size); 4.115 + cx_invoke_destructor(list, ((char *) arl->data) + index * list->base.item_size); 4.116 4.117 // short-circuit removal of last element 4.118 - if (index == list->size - 1) { 4.119 - list->size--; 4.120 + if (index == list->base.size - 1) { 4.121 + list->base.size--; 4.122 return 0; 4.123 } 4.124 4.125 // just move the elements starting at index to the left 4.126 int result = cx_array_copy( 4.127 &arl->data, 4.128 - &list->size, 4.129 + &list->base.size, 4.130 &arl->capacity, 4.131 index, 4.132 - ((char *) arl->data) + (index + 1) * list->item_size, 4.133 - list->item_size, 4.134 - list->size - index - 1, 4.135 + ((char *) arl->data) + (index + 1) * list->base.item_size, 4.136 + list->base.item_size, 4.137 + list->base.size - index - 1, 4.138 &arl->reallocator 4.139 ); 4.140 4.141 @@ -332,32 +332,32 @@ 4.142 assert(result == 0); 4.143 4.144 // decrease the size 4.145 - list->size--; 4.146 + list->base.size--; 4.147 4.148 return 0; 4.149 } 4.150 4.151 static void cx_arl_clear(struct cx_list_s *list) { 4.152 - if (list->size == 0) return; 4.153 + if (list->base.size == 0) return; 4.154 4.155 cx_array_list *arl = (cx_array_list *) list; 4.156 char *ptr = arl->data; 4.157 4.158 - if (list->simple_destructor) { 4.159 - for (size_t i = 0; i < list->size; i++) { 4.160 + if (list->base.simple_destructor) { 4.161 + for (size_t i = 0; i < list->base.size; i++) { 4.162 cx_invoke_simple_destructor(list, ptr); 4.163 - ptr += list->item_size; 4.164 + ptr += list->base.item_size; 4.165 } 4.166 } 4.167 - if (list->advanced_destructor) { 4.168 - for (size_t i = 0; i < list->size; i++) { 4.169 + if (list->base.advanced_destructor) { 4.170 + for (size_t i = 0; i < list->base.size; i++) { 4.171 cx_invoke_advanced_destructor(list, ptr); 4.172 - ptr += list->item_size; 4.173 + ptr += list->base.item_size; 4.174 } 4.175 } 4.176 4.177 - memset(arl->data, 0, list->size * list->item_size); 4.178 - list->size = 0; 4.179 + memset(arl->data, 0, list->base.size * list->base.item_size); 4.180 + list->base.size = 0; 4.181 } 4.182 4.183 static int cx_arl_swap( 4.184 @@ -365,9 +365,9 @@ 4.185 size_t i, 4.186 size_t j 4.187 ) { 4.188 - if (i >= list->size || j >= list->size) return 1; 4.189 + if (i >= list->base.size || j >= list->base.size) return 1; 4.190 cx_array_list *arl = (cx_array_list *) list; 4.191 - cx_array_swap(arl->data, list->item_size, i, j); 4.192 + cx_array_swap(arl->data, list->base.item_size, i, j); 4.193 return 0; 4.194 } 4.195 4.196 @@ -375,10 +375,10 @@ 4.197 struct cx_list_s const *list, 4.198 size_t index 4.199 ) { 4.200 - if (index < list->size) { 4.201 + if (index < list->base.size) { 4.202 cx_array_list const *arl = (cx_array_list const *) list; 4.203 char *space = arl->data; 4.204 - return space + index * list->item_size; 4.205 + return space + index * list->base.item_size; 4.206 } else { 4.207 return NULL; 4.208 } 4.209 @@ -389,12 +389,12 @@ 4.210 void const *elem, 4.211 bool remove 4.212 ) { 4.213 - assert(list->cmpfunc != NULL); 4.214 - assert(list->size < SIZE_MAX / 2); 4.215 + assert(list->base.cmpfunc != NULL); 4.216 + assert(list->base.size < SIZE_MAX / 2); 4.217 char *cur = ((cx_array_list const *) list)->data; 4.218 4.219 - for (ssize_t i = 0; i < (ssize_t) list->size; i++) { 4.220 - if (0 == list->cmpfunc(elem, cur)) { 4.221 + for (ssize_t i = 0; i < (ssize_t) list->base.size; i++) { 4.222 + if (0 == list->base.cmpfunc(elem, cur)) { 4.223 if (remove) { 4.224 if (0 == cx_arl_remove(list, i)) { 4.225 return i; 4.226 @@ -405,18 +405,18 @@ 4.227 return i; 4.228 } 4.229 } 4.230 - cur += list->item_size; 4.231 + cur += list->base.item_size; 4.232 } 4.233 4.234 return -1; 4.235 } 4.236 4.237 static void cx_arl_sort(struct cx_list_s *list) { 4.238 - assert(list->cmpfunc != NULL); 4.239 + assert(list->base.cmpfunc != NULL); 4.240 qsort(((cx_array_list *) list)->data, 4.241 - list->size, 4.242 - list->item_size, 4.243 - list->cmpfunc 4.244 + list->base.size, 4.245 + list->base.item_size, 4.246 + list->base.cmpfunc 4.247 ); 4.248 } 4.249 4.250 @@ -424,37 +424,37 @@ 4.251 struct cx_list_s const *list, 4.252 struct cx_list_s const *other 4.253 ) { 4.254 - assert(list->cmpfunc != NULL); 4.255 - if (list->size == other->size) { 4.256 + assert(list->base.cmpfunc != NULL); 4.257 + if (list->base.size == other->base.size) { 4.258 char const *left = ((cx_array_list const *) list)->data; 4.259 char const *right = ((cx_array_list const *) other)->data; 4.260 - for (size_t i = 0; i < list->size; i++) { 4.261 - int d = list->cmpfunc(left, right); 4.262 + for (size_t i = 0; i < list->base.size; i++) { 4.263 + int d = list->base.cmpfunc(left, right); 4.264 if (d != 0) { 4.265 return d; 4.266 } 4.267 - left += list->item_size; 4.268 - right += other->item_size; 4.269 + left += list->base.item_size; 4.270 + right += other->base.item_size; 4.271 } 4.272 return 0; 4.273 } else { 4.274 - return list->size < other->size ? -1 : 1; 4.275 + return list->base.size < other->base.size ? -1 : 1; 4.276 } 4.277 } 4.278 4.279 static void cx_arl_reverse(struct cx_list_s *list) { 4.280 - if (list->size < 2) return; 4.281 + if (list->base.size < 2) return; 4.282 void *data = ((cx_array_list const *) list)->data; 4.283 - size_t half = list->size / 2; 4.284 + size_t half = list->base.size / 2; 4.285 for (size_t i = 0; i < half; i++) { 4.286 - cx_array_swap(data, list->item_size, i, list->size - 1 - i); 4.287 + cx_array_swap(data, list->base.item_size, i, list->base.size - 1 - i); 4.288 } 4.289 } 4.290 4.291 static bool cx_arl_iter_valid(void const *it) { 4.292 struct cx_iterator_s const *iter = it; 4.293 struct cx_list_s const *list = iter->src_handle.c; 4.294 - return iter->index < list->size; 4.295 + return iter->index < list->base.size; 4.296 } 4.297 4.298 static void *cx_arl_iter_current(void const *it) { 4.299 @@ -464,28 +464,28 @@ 4.300 4.301 static void cx_arl_iter_next(void *it) { 4.302 struct cx_iterator_s *iter = it; 4.303 - if (iter->remove) { 4.304 - iter->remove = false; 4.305 + if (iter->base.remove) { 4.306 + iter->base.remove = false; 4.307 cx_arl_remove(iter->src_handle.m, iter->index); 4.308 } else { 4.309 iter->index++; 4.310 iter->elem_handle = 4.311 ((char *) iter->elem_handle) 4.312 - + ((struct cx_list_s const *) iter->src_handle.c)->item_size; 4.313 + + ((struct cx_list_s const *) iter->src_handle.c)->base.item_size; 4.314 } 4.315 } 4.316 4.317 static void cx_arl_iter_prev(void *it) { 4.318 struct cx_iterator_s *iter = it; 4.319 cx_array_list const* list = iter->src_handle.c; 4.320 - if (iter->remove) { 4.321 - iter->remove = false; 4.322 + if (iter->base.remove) { 4.323 + iter->base.remove = false; 4.324 cx_arl_remove(iter->src_handle.m, iter->index); 4.325 } 4.326 iter->index--; 4.327 - if (iter->index < list->base.size) { 4.328 + if (iter->index < list->base.base.size) { 4.329 iter->elem_handle = ((char *) list->data) 4.330 - + iter->index * list->base.item_size; 4.331 + + iter->index * list->base.base.item_size; 4.332 } 4.333 } 4.334 4.335 @@ -500,13 +500,13 @@ 4.336 iter.index = index; 4.337 iter.src_handle.c = list; 4.338 iter.elem_handle = cx_arl_at(list, index); 4.339 - iter.elem_size = list->item_size; 4.340 - iter.elem_count = list->size; 4.341 - iter.valid = cx_arl_iter_valid; 4.342 - iter.current = cx_arl_iter_current; 4.343 - iter.next = backwards ? cx_arl_iter_prev : cx_arl_iter_next; 4.344 - iter.remove = false; 4.345 - iter.mutating = false; 4.346 + iter.elem_size = list->base.item_size; 4.347 + iter.elem_count = list->base.size; 4.348 + iter.base.valid = cx_arl_iter_valid; 4.349 + iter.base.current = cx_arl_iter_current; 4.350 + iter.base.next = backwards ? cx_arl_iter_prev : cx_arl_iter_next; 4.351 + iter.base.remove = false; 4.352 + iter.base.mutating = false; 4.353 4.354 return iter; 4.355 } 4.356 @@ -541,15 +541,15 @@ 4.357 if (list == NULL) return NULL; 4.358 4.359 list->base.cl = &cx_array_list_class; 4.360 - list->base.allocator = allocator; 4.361 + list->base.base.allocator = allocator; 4.362 list->capacity = initial_capacity; 4.363 4.364 if (item_size > 0) { 4.365 - list->base.item_size = item_size; 4.366 - list->base.cmpfunc = comparator; 4.367 + list->base.base.item_size = item_size; 4.368 + list->base.base.cmpfunc = comparator; 4.369 } else { 4.370 item_size = sizeof(void *); 4.371 - list->base.cmpfunc = comparator == NULL ? cx_cmp_ptr : comparator; 4.372 + list->base.base.cmpfunc = comparator == NULL ? cx_cmp_ptr : comparator; 4.373 cxListStorePointers((CxList *) list); 4.374 } 4.375
5.1 --- a/src/cx/collection.h Thu May 23 19:29:14 2024 +0200 5.2 +++ b/src/cx/collection.h Thu May 23 20:29:28 2024 +0200 5.3 @@ -38,6 +38,7 @@ 5.4 5.5 #include "allocator.h" 5.6 #include "iterator.h" 5.7 +#include "compare.h" 5.8 5.9 #ifdef __cplusplus 5.10 extern "C" { 5.11 @@ -48,60 +49,55 @@ 5.12 */ 5.13 #define CX_STORE_POINTERS 0 5.14 5.15 -#ifndef CX_COMPARE_FUNC_DEFINED 5.16 -#define CX_COMPARE_FUNC_DEFINED 5.17 /** 5.18 - * A comparator function comparing two collection elements. 5.19 + * Base attributes of a collection. 5.20 */ 5.21 -typedef int(*cx_compare_func)( 5.22 - void const *left, 5.23 - void const *right 5.24 -); 5.25 -#endif // CX_COMPARE_FUNC_DEFINED 5.26 +struct cx_collection_s { 5.27 + /** 5.28 + * The allocator to use. 5.29 + */ 5.30 + CxAllocator const *allocator; 5.31 + /** 5.32 + * The comparator function for the elements. 5.33 + */ 5.34 + cx_compare_func cmpfunc; 5.35 + /** 5.36 + * The size of each element. 5.37 + */ 5.38 + size_t item_size; 5.39 + /** 5.40 + * The number of currently stored elements. 5.41 + */ 5.42 + size_t size; 5.43 + /** 5.44 + * An optional simple destructor for the collection's elements. 5.45 + * 5.46 + * @attention Read the documentation of the particular collection implementation 5.47 + * whether this destructor shall only destroy the contents or also free the memory. 5.48 + */ 5.49 + cx_destructor_func simple_destructor; 5.50 + /** 5.51 + * An optional advanced destructor for the collection's elements. 5.52 + * 5.53 + * @attention Read the documentation of the particular collection implementation 5.54 + * whether this destructor shall only destroy the contents or also free the memory. 5.55 + */ 5.56 + cx_destructor_func2 advanced_destructor; 5.57 + /** 5.58 + * The pointer to additional data that is passed to the advanced destructor. 5.59 + */ 5.60 + void *destructor_data; 5.61 + /** 5.62 + * Indicates if this list is supposed to store pointers 5.63 + * instead of copies of the actual objects. 5.64 + */ 5.65 + bool store_pointer; 5.66 +}; 5.67 5.68 /** 5.69 * Use this macro to declare common members for a collection structure. 5.70 */ 5.71 -#define CX_COLLECTION_MEMBERS \ 5.72 - /** \ 5.73 - * The allocator to use. \ 5.74 - */ \ 5.75 - CxAllocator const *allocator; \ 5.76 - /** \ 5.77 - * The comparator function for the elements. \ 5.78 - */ \ 5.79 - cx_compare_func cmpfunc; \ 5.80 - /** \ 5.81 - * The size of each element. \ 5.82 - */ \ 5.83 - size_t item_size; \ 5.84 - /** \ 5.85 - * The number of currently stored elements. \ 5.86 - */ \ 5.87 - size_t size; \ 5.88 - /** \ 5.89 - * An optional simple destructor for the collection's elements. \ 5.90 - * \ 5.91 - * @attention Read the documentation of the particular collection implementation \ 5.92 - * whether this destructor shall only destroy the contents or also free the memory. \ 5.93 - */ \ 5.94 - cx_destructor_func simple_destructor; \ 5.95 - /** \ 5.96 - * An optional advanced destructor for the collection's elements. \ 5.97 - * \ 5.98 - * @attention Read the documentation of the particular collection implementation \ 5.99 - * whether this destructor shall only destroy the contents or also free the memory. \ 5.100 - */ \ 5.101 - cx_destructor_func2 advanced_destructor; \ 5.102 - /** \ 5.103 - * The pointer to additional data that is passed to the advanced destructor. \ 5.104 - */ \ 5.105 - void *destructor_data; \ 5.106 - /** \ 5.107 - * Indicates if this instance of a collection is supposed to store pointers \ 5.108 - * instead of copies of the actual objects. \ 5.109 - */ \ 5.110 - bool store_pointer; 5.111 +#define CX_COLLECTION_BASE struct cx_collection_s base 5.112 5.113 /** 5.114 * Invokes the simple destructor function for a specific element. 5.115 @@ -113,7 +109,7 @@ 5.116 * @param e the element 5.117 */ 5.118 #define cx_invoke_simple_destructor(c, e) \ 5.119 - (c)->simple_destructor((c)->store_pointer ? (*((void **) (e))) : (e)) 5.120 + (c)->base.simple_destructor((c)->base.store_pointer ? (*((void **) (e))) : (e)) 5.121 5.122 /** 5.123 * Invokes the advanced destructor function for a specific element. 5.124 @@ -125,8 +121,8 @@ 5.125 * @param e the element 5.126 */ 5.127 #define cx_invoke_advanced_destructor(c, e) \ 5.128 - (c)->advanced_destructor((c)->destructor_data, \ 5.129 - (c)->store_pointer ? (*((void **) (e))) : (e)) 5.130 + (c)->base.advanced_destructor((c)->base.destructor_data, \ 5.131 + (c)->base.store_pointer ? (*((void **) (e))) : (e)) 5.132 5.133 5.134 /** 5.135 @@ -139,8 +135,8 @@ 5.136 * @param e the element 5.137 */ 5.138 #define cx_invoke_destructor(c, e) \ 5.139 - if ((c)->simple_destructor) cx_invoke_simple_destructor(c,e); \ 5.140 - if ((c)->advanced_destructor) cx_invoke_advanced_destructor(c,e) 5.141 + if ((c)->base.simple_destructor) cx_invoke_simple_destructor(c,e); \ 5.142 + if ((c)->base.advanced_destructor) cx_invoke_advanced_destructor(c,e) 5.143 5.144 #ifdef __cplusplus 5.145 } // extern "C"
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/src/cx/collection_base.h Thu May 23 20:29:28 2024 +0200 6.3 @@ -0,0 +1,35 @@ 6.4 +/* 6.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 6.6 + * 6.7 + * Copyright 2024 Mike Becker, Olaf Wintermann All rights reserved. 6.8 + * 6.9 + * Redistribution and use in source and binary forms, with or without 6.10 + * modification, are permitted provided that the following conditions are met: 6.11 + * 6.12 + * 1. Redistributions of source code must retain the above copyright 6.13 + * notice, this list of conditions and the following disclaimer. 6.14 + * 6.15 + * 2. Redistributions in binary form must reproduce the above copyright 6.16 + * notice, this list of conditions and the following disclaimer in the 6.17 + * documentation and/or other materials provided with the distribution. 6.18 + * 6.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 6.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 6.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 6.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 6.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 6.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 6.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 6.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 6.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 6.29 + * POSSIBILITY OF SUCH DAMAGE. 6.30 + */ 6.31 +/** 6.32 + * \file collection_base.h 6.33 + * \brief Include this file in your collection struct to declare common members. 6.34 + * \author Mike Becker 6.35 + * \author Olaf Wintermann 6.36 + * \copyright 2-Clause BSD License 6.37 + */ 6.38 +
7.1 --- a/src/cx/iterator.h Thu May 23 19:29:14 2024 +0200 7.2 +++ b/src/cx/iterator.h Thu May 23 20:29:28 2024 +0200 7.3 @@ -38,45 +38,54 @@ 7.4 7.5 #include "common.h" 7.6 7.7 -#define CX_ITERATOR_BASE \ 7.8 - /** \ 7.9 - * True iff the iterator points to valid data. \ 7.10 - */ \ 7.11 - __attribute__ ((__nonnull__)) \ 7.12 - bool (*valid)(void const *); \ 7.13 - /** \ 7.14 - * Returns a pointer to the current element. \ 7.15 - * \ 7.16 - * When valid returns false, the behavior of this function is undefined. \ 7.17 - */ \ 7.18 - __attribute__ ((__nonnull__)) \ 7.19 - void *(*current)(void const *); \ 7.20 - /** \ 7.21 - * Original implementation in case the function needs to be wrapped. \ 7.22 - */ \ 7.23 - __attribute__ ((__nonnull__)) \ 7.24 - void *(*current_impl)(void const *); \ 7.25 - /** \ 7.26 - * Advances the iterator. \ 7.27 - * \ 7.28 - * When valid returns false, the behavior of this function is undefined. \ 7.29 - */ \ 7.30 - __attribute__ ((__nonnull__)) \ 7.31 - void (*next)(void *); \ 7.32 - /** \ 7.33 - * Indicates whether this iterator may remove elements. \ 7.34 - */ \ 7.35 - bool mutating; \ 7.36 - /** \ 7.37 - * Internal flag for removing the current element when advancing. \ 7.38 - */ \ 7.39 +struct cx_iterator_base_s { 7.40 + /** 7.41 + * True iff the iterator points to valid data. 7.42 + */ 7.43 + __attribute__ ((__nonnull__)) 7.44 + bool (*valid)(void const *); 7.45 + 7.46 + /** 7.47 + * Returns a pointer to the current element. 7.48 + * 7.49 + * When valid returns false, the behavior of this function is undefined. 7.50 + */ 7.51 + __attribute__ ((__nonnull__)) 7.52 + void *(*current)(void const *); 7.53 + 7.54 + /** 7.55 + * Original implementation in case the function needs to be wrapped. 7.56 + */ 7.57 + __attribute__ ((__nonnull__)) 7.58 + void *(*current_impl)(void const *); 7.59 + 7.60 + /** 7.61 + * Advances the iterator. 7.62 + * 7.63 + * When valid returns false, the behavior of this function is undefined. 7.64 + */ 7.65 + __attribute__ ((__nonnull__)) 7.66 + void (*next)(void *); 7.67 + /** 7.68 + * Indicates whether this iterator may remove elements. 7.69 + */ 7.70 + bool mutating; 7.71 + /** 7.72 + * Internal flag for removing the current element when advancing. 7.73 + */ 7.74 bool remove; 7.75 +}; 7.76 + 7.77 +/** 7.78 + * Declares base attributes for an iterator. 7.79 + */ 7.80 +#define CX_ITERATOR_BASE struct cx_iterator_base_s base 7.81 7.82 /** 7.83 * Internal iterator struct - use CxIterator. 7.84 */ 7.85 struct cx_iterator_s { 7.86 - CX_ITERATOR_BASE 7.87 + CX_ITERATOR_BASE; 7.88 7.89 /** 7.90 * Handle for the current element. 7.91 @@ -157,7 +166,7 @@ 7.92 * @param iter the iterator 7.93 * @return true iff the iterator points to valid data 7.94 */ 7.95 -#define cxIteratorValid(iter) (iter).valid(&(iter)) 7.96 +#define cxIteratorValid(iter) (iter).base.valid(&(iter)) 7.97 7.98 /** 7.99 * Returns a pointer to the current element. 7.100 @@ -167,21 +176,21 @@ 7.101 * @param iter the iterator 7.102 * @return a pointer to the current element 7.103 */ 7.104 -#define cxIteratorCurrent(iter) (iter).current(&iter) 7.105 +#define cxIteratorCurrent(iter) (iter).base.current(&iter) 7.106 7.107 /** 7.108 * Advances the iterator to the next element. 7.109 * 7.110 * @param iter the iterator 7.111 */ 7.112 -#define cxIteratorNext(iter) (iter).next(&iter) 7.113 +#define cxIteratorNext(iter) (iter).base.next(&iter) 7.114 7.115 /** 7.116 * Flags the current element for removal, if this iterator is mutating. 7.117 * 7.118 * @param iter the iterator 7.119 */ 7.120 -#define cxIteratorFlagRemoval(iter) (iter).remove |= (iter).mutating 7.121 +#define cxIteratorFlagRemoval(iter) (iter).base.remove |= (iter).base.mutating 7.122 7.123 /** 7.124 * Loops over an iterator.
8.1 --- a/src/cx/list.h Thu May 23 19:29:14 2024 +0200 8.2 +++ b/src/cx/list.h Thu May 23 20:29:28 2024 +0200 8.3 @@ -52,7 +52,7 @@ 8.4 * Structure for holding the base data of a list. 8.5 */ 8.6 struct cx_list_s { 8.7 - CX_COLLECTION_MEMBERS 8.8 + CX_COLLECTION_BASE; 8.9 /** 8.10 * The list class definition. 8.11 */ 8.12 @@ -213,7 +213,7 @@ 8.13 */ 8.14 __attribute__((__nonnull__)) 8.15 static inline bool cxListIsStoringPointers(CxList const *list) { 8.16 - return list->store_pointer; 8.17 + return list->base.store_pointer; 8.18 } 8.19 8.20 /** 8.21 @@ -224,7 +224,7 @@ 8.22 */ 8.23 __attribute__((__nonnull__)) 8.24 static inline size_t cxListSize(CxList const *list) { 8.25 - return list->size; 8.26 + return list->base.size; 8.27 } 8.28 8.29 /** 8.30 @@ -240,7 +240,7 @@ 8.31 CxList *list, 8.32 void const *elem 8.33 ) { 8.34 - return list->cl->insert_element(list, list->size, elem); 8.35 + return list->cl->insert_element(list, list->base.size, elem); 8.36 } 8.37 8.38 /** 8.39 @@ -265,7 +265,7 @@ 8.40 void const *array, 8.41 size_t n 8.42 ) { 8.43 - return list->cl->insert_array(list, list->size, array, n); 8.44 + return list->cl->insert_array(list, list->base.size, array, n); 8.45 } 8.46 8.47 /** 8.48 @@ -547,7 +547,7 @@ 8.49 */ 8.50 __attribute__((__nonnull__, __warn_unused_result__)) 8.51 static inline CxIterator cxListBackwardsIterator(CxList const *list) { 8.52 - return list->cl->iterator(list, list->size - 1, true); 8.53 + return list->cl->iterator(list, list->base.size - 1, true); 8.54 } 8.55 8.56 /** 8.57 @@ -562,7 +562,7 @@ 8.58 */ 8.59 __attribute__((__nonnull__, __warn_unused_result__)) 8.60 static inline CxIterator cxListMutBackwardsIterator(CxList *list) { 8.61 - return cxListMutBackwardsIteratorAt(list, list->size - 1); 8.62 + return cxListMutBackwardsIteratorAt(list, list->base.size - 1); 8.63 } 8.64 8.65 /**
9.1 --- a/src/cx/map.h Thu May 23 19:29:14 2024 +0200 9.2 +++ b/src/cx/map.h Thu May 23 20:29:28 2024 +0200 9.3 @@ -56,7 +56,10 @@ 9.4 9.5 /** Structure for the UCX map. */ 9.6 struct cx_map_s { 9.7 - CX_COLLECTION_MEMBERS 9.8 + /** 9.9 + * Base attributes. 9.10 + */ 9.11 + CX_COLLECTION_BASE; 9.12 /** The map class definition. */ 9.13 cx_map_class *cl; 9.14 }; 9.15 @@ -163,7 +166,7 @@ 9.16 */ 9.17 __attribute__((__nonnull__)) 9.18 static inline void cxMapStoreObjects(CxMap *map) { 9.19 - map->store_pointer = false; 9.20 + map->base.store_pointer = false; 9.21 } 9.22 9.23 /** 9.24 @@ -180,8 +183,8 @@ 9.25 */ 9.26 __attribute__((__nonnull__)) 9.27 static inline void cxMapStorePointers(CxMap *map) { 9.28 - map->store_pointer = true; 9.29 - map->item_size = sizeof(void *); 9.30 + map->base.store_pointer = true; 9.31 + map->base.item_size = sizeof(void *); 9.32 } 9.33 9.34 9.35 @@ -1050,7 +1053,7 @@ 9.36 CxMap *map, 9.37 CxHashKey key 9.38 ) { 9.39 - return map->cl->remove(map, key, !map->store_pointer); 9.40 + return map->cl->remove(map, key, !map->base.store_pointer); 9.41 } 9.42 9.43 /** 9.44 @@ -1066,7 +1069,7 @@ 9.45 CxMap *map, 9.46 cxstring key 9.47 ) { 9.48 - return map->cl->remove(map, cx_hash_key_cxstr(key), !map->store_pointer); 9.49 + return map->cl->remove(map, cx_hash_key_cxstr(key), !map->base.store_pointer); 9.50 } 9.51 9.52 /** 9.53 @@ -1082,7 +1085,7 @@ 9.54 CxMap *map, 9.55 cxmutstr key 9.56 ) { 9.57 - return map->cl->remove(map, cx_hash_key_cxstr(key), !map->store_pointer); 9.58 + return map->cl->remove(map, cx_hash_key_cxstr(key), !map->base.store_pointer); 9.59 } 9.60 9.61 /** 9.62 @@ -1098,7 +1101,7 @@ 9.63 CxMap *map, 9.64 char const *key 9.65 ) { 9.66 - return map->cl->remove(map, cx_hash_key_str(key), !map->store_pointer); 9.67 + return map->cl->remove(map, cx_hash_key_str(key), !map->base.store_pointer); 9.68 } 9.69 9.70 /**
10.1 --- a/src/cx/tree.h Thu May 23 19:29:14 2024 +0200 10.2 +++ b/src/cx/tree.h Thu May 23 20:29:28 2024 +0200 10.3 @@ -58,7 +58,10 @@ 10.4 * @see CxIterator 10.5 */ 10.6 typedef struct cx_tree_iterator_s { 10.7 - CX_ITERATOR_BASE 10.8 + /** 10.9 + * Base members. 10.10 + */ 10.11 + CX_ITERATOR_BASE; 10.12 /** 10.13 * Indicates whether the subtree below the current node shall be skipped. 10.14 */ 10.15 @@ -154,7 +157,10 @@ 10.16 * @see CxIterator 10.17 */ 10.18 typedef struct cx_tree_visitor_s { 10.19 - CX_ITERATOR_BASE 10.20 + /** 10.21 + * Base members. 10.22 + */ 10.23 + CX_ITERATOR_BASE; 10.24 /** 10.25 * Indicates whether the subtree below the current node shall be skipped. 10.26 */
11.1 --- a/src/hash_map.c Thu May 23 19:29:14 2024 +0200 11.2 +++ b/src/hash_map.c Thu May 23 20:29:28 2024 +0200 11.3 @@ -53,9 +53,9 @@ 11.4 // invoke the destructor 11.5 cx_invoke_destructor(map, elem->data); 11.6 // free the key data 11.7 - cxFree(map->allocator, (void *) elem->key.data); 11.8 + cxFree(map->base.allocator, (void *) elem->key.data); 11.9 // free the node 11.10 - cxFree(map->allocator, elem); 11.11 + cxFree(map->base.allocator, elem); 11.12 // proceed 11.13 elem = next; 11.14 } while (elem != NULL); 11.15 @@ -64,7 +64,7 @@ 11.16 hash_map->buckets[i] = NULL; 11.17 } 11.18 } 11.19 - map->size = 0; 11.20 + map->base.size = 0; 11.21 } 11.22 11.23 static void cx_hash_map_destructor(struct cx_map_s *map) { 11.24 @@ -72,10 +72,10 @@ 11.25 11.26 // free the buckets 11.27 cx_hash_map_clear(map); 11.28 - cxFree(map->allocator, hash_map->buckets); 11.29 + cxFree(map->base.allocator, hash_map->buckets); 11.30 11.31 // free the map structure 11.32 - cxFree(map->allocator, map); 11.33 + cxFree(map->base.allocator, map); 11.34 } 11.35 11.36 static int cx_hash_map_put( 11.37 @@ -84,7 +84,7 @@ 11.38 void *value 11.39 ) { 11.40 struct cx_hash_map_s *hash_map = (struct cx_hash_map_s *) map; 11.41 - CxAllocator const *allocator = map->allocator; 11.42 + CxAllocator const *allocator = map->base.allocator; 11.43 11.44 unsigned hash = key.hash; 11.45 if (hash == 0) { 11.46 @@ -104,26 +104,26 @@ 11.47 if (elm != NULL && elm->key.hash == hash && elm->key.len == key.len && 11.48 memcmp(elm->key.data, key.data, key.len) == 0) { 11.49 // overwrite existing element 11.50 - if (map->store_pointer) { 11.51 + if (map->base.store_pointer) { 11.52 memcpy(elm->data, &value, sizeof(void *)); 11.53 } else { 11.54 - memcpy(elm->data, value, map->item_size); 11.55 + memcpy(elm->data, value, map->base.item_size); 11.56 } 11.57 } else { 11.58 // allocate new element 11.59 struct cx_hash_map_element_s *e = cxMalloc( 11.60 allocator, 11.61 - sizeof(struct cx_hash_map_element_s) + map->item_size 11.62 + sizeof(struct cx_hash_map_element_s) + map->base.item_size 11.63 ); 11.64 if (e == NULL) { 11.65 return -1; 11.66 } 11.67 11.68 // write the value 11.69 - if (map->store_pointer) { 11.70 + if (map->base.store_pointer) { 11.71 memcpy(e->data, &value, sizeof(void *)); 11.72 } else { 11.73 - memcpy(e->data, value, map->item_size); 11.74 + memcpy(e->data, value, map->base.item_size); 11.75 } 11.76 11.77 // copy the key 11.78 @@ -145,7 +145,7 @@ 11.79 e->next = elm; 11.80 11.81 // increase the size 11.82 - map->size++; 11.83 + map->base.size++; 11.84 } 11.85 11.86 return 0; 11.87 @@ -164,10 +164,10 @@ 11.88 prev->next = elm->next; 11.89 } 11.90 // free element 11.91 - cxFree(hash_map->base.allocator, (void *) elm->key.data); 11.92 - cxFree(hash_map->base.allocator, elm); 11.93 + cxFree(hash_map->base.base.allocator, (void *) elm->key.data); 11.94 + cxFree(hash_map->base.base.allocator, elm); 11.95 // decrease size 11.96 - hash_map->base.size--; 11.97 + hash_map->base.base.size--; 11.98 } 11.99 11.100 /** 11.101 @@ -203,7 +203,7 @@ 11.102 if (destroy) { 11.103 cx_invoke_destructor(map, elm->data); 11.104 } else { 11.105 - if (map->store_pointer) { 11.106 + if (map->base.store_pointer) { 11.107 data = *(void **) elm->data; 11.108 } else { 11.109 data = elm->data; 11.110 @@ -254,7 +254,7 @@ 11.111 struct cx_iterator_s const *iter = it; 11.112 struct cx_hash_map_s const *map = iter->src_handle.c; 11.113 struct cx_hash_map_element_s *elm = iter->elem_handle; 11.114 - if (map->base.store_pointer) { 11.115 + if (map->base.base.store_pointer) { 11.116 return *(void **) elm->data; 11.117 } else { 11.118 return elm->data; 11.119 @@ -272,10 +272,10 @@ 11.120 struct cx_hash_map_s *map = iter->src_handle.m; 11.121 11.122 // remove current element, if asked 11.123 - if (iter->remove) { 11.124 + if (iter->base.remove) { 11.125 11.126 // clear the flag 11.127 - iter->remove = false; 11.128 + iter->base.remove = false; 11.129 11.130 // determine the next element 11.131 struct cx_hash_map_element_s *next = elm->next; 11.132 @@ -315,7 +315,7 @@ 11.133 iter->kv_data.value = NULL; 11.134 } else { 11.135 iter->kv_data.key = &elm->key; 11.136 - if (map->base.store_pointer) { 11.137 + if (map->base.base.store_pointer) { 11.138 iter->kv_data.value = *(void **) elm->data; 11.139 } else { 11.140 iter->kv_data.value = elm->data; 11.141 @@ -330,34 +330,34 @@ 11.142 CxIterator iter; 11.143 11.144 iter.src_handle.c = map; 11.145 - iter.elem_count = map->size; 11.146 + iter.elem_count = map->base.size; 11.147 11.148 switch (type) { 11.149 case CX_MAP_ITERATOR_PAIRS: 11.150 iter.elem_size = sizeof(CxMapEntry); 11.151 - iter.current = cx_hash_map_iter_current_entry; 11.152 + iter.base.current = cx_hash_map_iter_current_entry; 11.153 break; 11.154 case CX_MAP_ITERATOR_KEYS: 11.155 iter.elem_size = sizeof(CxHashKey); 11.156 - iter.current = cx_hash_map_iter_current_key; 11.157 + iter.base.current = cx_hash_map_iter_current_key; 11.158 break; 11.159 case CX_MAP_ITERATOR_VALUES: 11.160 - iter.elem_size = map->item_size; 11.161 - iter.current = cx_hash_map_iter_current_value; 11.162 + iter.elem_size = map->base.item_size; 11.163 + iter.base.current = cx_hash_map_iter_current_value; 11.164 break; 11.165 default: 11.166 assert(false); 11.167 } 11.168 11.169 - iter.valid = cx_hash_map_iter_valid; 11.170 - iter.next = cx_hash_map_iter_next; 11.171 - iter.remove = false; 11.172 - iter.mutating = false; 11.173 + iter.base.valid = cx_hash_map_iter_valid; 11.174 + iter.base.next = cx_hash_map_iter_next; 11.175 + iter.base.remove = false; 11.176 + iter.base.mutating = false; 11.177 11.178 iter.slot = 0; 11.179 iter.index = 0; 11.180 11.181 - if (map->size > 0) { 11.182 + if (map->base.size > 0) { 11.183 struct cx_hash_map_s *hash_map = (struct cx_hash_map_s *) map; 11.184 struct cx_hash_map_element_s *elm = hash_map->buckets[0]; 11.185 while (elm == NULL) { 11.186 @@ -365,7 +365,7 @@ 11.187 } 11.188 iter.elem_handle = elm; 11.189 iter.kv_data.key = &elm->key; 11.190 - if (map->store_pointer) { 11.191 + if (map->base.store_pointer) { 11.192 iter.kv_data.value = *(void **) elm->data; 11.193 } else { 11.194 iter.kv_data.value = elm->data; 11.195 @@ -413,14 +413,14 @@ 11.196 11.197 // initialize base members 11.198 map->base.cl = &cx_hash_map_class; 11.199 - map->base.allocator = allocator; 11.200 + map->base.base.allocator = allocator; 11.201 11.202 if (itemsize > 0) { 11.203 - map->base.store_pointer = false; 11.204 - map->base.item_size = itemsize; 11.205 + map->base.base.store_pointer = false; 11.206 + map->base.base.item_size = itemsize; 11.207 } else { 11.208 - map->base.store_pointer = true; 11.209 - map->base.item_size = sizeof(void *); 11.210 + map->base.base.store_pointer = true; 11.211 + map->base.base.item_size = sizeof(void *); 11.212 } 11.213 11.214 return (CxMap *) map; 11.215 @@ -428,11 +428,11 @@ 11.216 11.217 int cxMapRehash(CxMap *map) { 11.218 struct cx_hash_map_s *hash_map = (struct cx_hash_map_s *) map; 11.219 - if (map->size > ((hash_map->bucket_count * 3) >> 2)) { 11.220 + if (map->base.size > ((hash_map->bucket_count * 3) >> 2)) { 11.221 11.222 - size_t new_bucket_count = (map->size * 5) >> 1; 11.223 + size_t new_bucket_count = (map->base.size * 5) >> 1; 11.224 struct cx_hash_map_element_s **new_buckets = cxCalloc( 11.225 - map->allocator, 11.226 + map->base.allocator, 11.227 new_bucket_count, sizeof(struct cx_hash_map_element_s *) 11.228 ); 11.229 11.230 @@ -472,7 +472,7 @@ 11.231 11.232 // assign result to the map 11.233 hash_map->bucket_count = new_bucket_count; 11.234 - cxFree(map->allocator, hash_map->buckets); 11.235 + cxFree(map->base.allocator, hash_map->buckets); 11.236 hash_map->buckets = new_buckets; 11.237 } 11.238 return 0;
12.1 --- a/src/iterator.c Thu May 23 19:29:14 2024 +0200 12.2 +++ b/src/iterator.c Thu May 23 20:29:28 2024 +0200 12.3 @@ -42,8 +42,8 @@ 12.4 12.5 static void cx_iter_next_fast(void *it) { 12.6 struct cx_iterator_s *iter = it; 12.7 - if (iter->remove) { 12.8 - iter->remove = false; 12.9 + if (iter->base.remove) { 12.10 + iter->base.remove = false; 12.11 iter->elem_count--; 12.12 // only move the last element when we are not currently aiming 12.13 // at the last element already 12.14 @@ -60,8 +60,8 @@ 12.15 12.16 static void cx_iter_next_slow(void *it) { 12.17 struct cx_iterator_s *iter = it; 12.18 - if (iter->remove) { 12.19 - iter->remove = false; 12.20 + if (iter->base.remove) { 12.21 + iter->base.remove = false; 12.22 iter->elem_count--; 12.23 12.24 // number of elements to move 12.25 @@ -92,11 +92,11 @@ 12.26 iter.elem_handle = array; 12.27 iter.elem_size = elem_size; 12.28 iter.elem_count = array == NULL ? 0 : elem_count; 12.29 - iter.valid = cx_iter_valid; 12.30 - iter.current = cx_iter_current; 12.31 - iter.next = remove_keeps_order ? cx_iter_next_slow : cx_iter_next_fast; 12.32 - iter.remove = false; 12.33 - iter.mutating = true; 12.34 + iter.base.valid = cx_iter_valid; 12.35 + iter.base.current = cx_iter_current; 12.36 + iter.base.next = remove_keeps_order ? cx_iter_next_slow : cx_iter_next_fast; 12.37 + iter.base.remove = false; 12.38 + iter.base.mutating = true; 12.39 12.40 return iter; 12.41 } 12.42 @@ -107,6 +107,6 @@ 12.43 size_t elem_count 12.44 ) { 12.45 CxIterator iter = cxMutIterator((void*)array, elem_size, elem_count, false); 12.46 - iter.mutating = false; 12.47 + iter.base.mutating = false; 12.48 return iter; 12.49 }
13.1 --- a/src/linked_list.c Thu May 23 19:29:14 2024 +0200 13.2 +++ b/src/linked_list.c Thu May 23 20:29:28 2024 +0200 13.3 @@ -501,10 +501,10 @@ 13.4 cx_linked_list const *list, 13.5 size_t index 13.6 ) { 13.7 - if (index >= list->base.size) { 13.8 + if (index >= list->base.base.size) { 13.9 return NULL; 13.10 - } else if (index > list->base.size / 2) { 13.11 - return cx_linked_list_at(list->end, list->base.size - 1, CX_LL_LOC_PREV, index); 13.12 + } else if (index > list->base.base.size / 2) { 13.13 + return cx_linked_list_at(list->end, list->base.base.size - 1, CX_LL_LOC_PREV, index); 13.14 } else { 13.15 return cx_linked_list_at(list->begin, 0, CX_LL_LOC_NEXT, index); 13.16 } 13.17 @@ -517,15 +517,15 @@ 13.18 ) { 13.19 13.20 // create the new new_node 13.21 - cx_linked_list_node *new_node = cxMalloc(list->allocator, 13.22 - sizeof(cx_linked_list_node) + list->item_size); 13.23 + cx_linked_list_node *new_node = cxMalloc(list->base.allocator, 13.24 + sizeof(cx_linked_list_node) + list->base.item_size); 13.25 13.26 // sortir if failed 13.27 if (new_node == NULL) return 1; 13.28 13.29 // initialize new new_node 13.30 new_node->prev = new_node->next = NULL; 13.31 - memcpy(new_node->payload, elem, list->item_size); 13.32 + memcpy(new_node->payload, elem, list->base.item_size); 13.33 13.34 // insert 13.35 cx_linked_list *ll = (cx_linked_list *) list; 13.36 @@ -536,7 +536,7 @@ 13.37 ); 13.38 13.39 // increase the size and return 13.40 - list->size++; 13.41 + list->base.size++; 13.42 return 0; 13.43 } 13.44 13.45 @@ -547,7 +547,7 @@ 13.46 size_t n 13.47 ) { 13.48 // out-of bounds and corner case check 13.49 - if (index > list->size || n == 0) return 0; 13.50 + if (index > list->base.size || n == 0) return 0; 13.51 13.52 // find position efficiently 13.53 cx_linked_list_node *node = index == 0 ? NULL : cx_ll_node_at((cx_linked_list *) list, index - 1); 13.54 @@ -566,7 +566,7 @@ 13.55 // we can add the remaining nodes and immedately advance to the inserted node 13.56 char const *source = array; 13.57 for (size_t i = 1; i < n; i++) { 13.58 - source += list->item_size; 13.59 + source += list->base.item_size; 13.60 if (0 != cx_ll_insert_at(list, node, source)) { 13.61 return i; 13.62 } 13.63 @@ -601,27 +601,27 @@ 13.64 CX_LL_LOC_PREV, CX_LL_LOC_NEXT, node); 13.65 13.66 // adjust size 13.67 - list->size--; 13.68 + list->base.size--; 13.69 13.70 // free and return 13.71 - cxFree(list->allocator, node); 13.72 + cxFree(list->base.allocator, node); 13.73 13.74 return 0; 13.75 } 13.76 13.77 static void cx_ll_clear(struct cx_list_s *list) { 13.78 - if (list->size == 0) return; 13.79 + if (list->base.size == 0) return; 13.80 13.81 cx_linked_list *ll = (cx_linked_list *) list; 13.82 cx_linked_list_node *node = ll->begin; 13.83 while (node != NULL) { 13.84 cx_invoke_destructor(list, node->payload); 13.85 cx_linked_list_node *next = node->next; 13.86 - cxFree(list->allocator, node); 13.87 + cxFree(list->base.allocator, node); 13.88 node = next; 13.89 } 13.90 ll->begin = ll->end = NULL; 13.91 - list->size = 0; 13.92 + list->base.size = 0; 13.93 } 13.94 13.95 #ifndef CX_LINKED_LIST_SWAP_SBO_SIZE 13.96 @@ -634,12 +634,12 @@ 13.97 size_t i, 13.98 size_t j 13.99 ) { 13.100 - if (i >= list->size || j >= list->size) return 1; 13.101 + if (i >= list->base.size || j >= list->base.size) return 1; 13.102 if (i == j) return 0; 13.103 13.104 // perform an optimized search that finds both elements in one run 13.105 cx_linked_list *ll = (cx_linked_list *) list; 13.106 - size_t mid = list->size / 2; 13.107 + size_t mid = list->base.size / 2; 13.108 size_t left, right; 13.109 if (i < j) { 13.110 left = i; 13.111 @@ -671,7 +671,7 @@ 13.112 // chose the closest to begin / end 13.113 size_t closest; 13.114 size_t other; 13.115 - size_t diff2boundary = list->size - right - 1; 13.116 + size_t diff2boundary = list->base.size - right - 1; 13.117 if (left <= diff2boundary) { 13.118 closest = left; 13.119 other = right; 13.120 @@ -707,7 +707,7 @@ 13.121 } 13.122 } 13.123 13.124 - if (list->item_size > CX_LINKED_LIST_SWAP_SBO_SIZE) { 13.125 + if (list->base.item_size > CX_LINKED_LIST_SWAP_SBO_SIZE) { 13.126 cx_linked_list_node *prev = nleft->prev; 13.127 cx_linked_list_node *next = nright->next; 13.128 cx_linked_list_node *midstart = nleft->next; 13.129 @@ -739,9 +739,9 @@ 13.130 } else { 13.131 // swap payloads to avoid relinking 13.132 char buf[CX_LINKED_LIST_SWAP_SBO_SIZE]; 13.133 - memcpy(buf, nleft->payload, list->item_size); 13.134 - memcpy(nleft->payload, nright->payload, list->item_size); 13.135 - memcpy(nright->payload, buf, list->item_size); 13.136 + memcpy(buf, nleft->payload, list->base.item_size); 13.137 + memcpy(nleft->payload, nright->payload, list->base.item_size); 13.138 + memcpy(nright->payload, buf, list->base.item_size); 13.139 } 13.140 13.141 return 0; 13.142 @@ -768,21 +768,21 @@ 13.143 (void **) &node, 13.144 ll->begin, 13.145 CX_LL_LOC_NEXT, CX_LL_LOC_DATA, 13.146 - list->cmpfunc, elem 13.147 + list->base.cmpfunc, elem 13.148 ); 13.149 if (node != NULL) { 13.150 cx_invoke_destructor(list, node->payload); 13.151 cx_linked_list_remove((void **) &ll->begin, (void **) &ll->end, 13.152 CX_LL_LOC_PREV, CX_LL_LOC_NEXT, node); 13.153 - list->size--; 13.154 - cxFree(list->allocator, node); 13.155 + list->base.size--; 13.156 + cxFree(list->base.allocator, node); 13.157 } 13.158 return index; 13.159 } else { 13.160 return cx_linked_list_find( 13.161 ((cx_linked_list *) list)->begin, 13.162 CX_LL_LOC_NEXT, CX_LL_LOC_DATA, 13.163 - list->cmpfunc, elem 13.164 + list->base.cmpfunc, elem 13.165 ); 13.166 } 13.167 } 13.168 @@ -791,7 +791,7 @@ 13.169 cx_linked_list *ll = (cx_linked_list *) list; 13.170 cx_linked_list_sort((void **) &ll->begin, (void **) &ll->end, 13.171 CX_LL_LOC_PREV, CX_LL_LOC_NEXT, CX_LL_LOC_DATA, 13.172 - list->cmpfunc); 13.173 + list->base.cmpfunc); 13.174 } 13.175 13.176 static void cx_ll_reverse(struct cx_list_s *list) { 13.177 @@ -807,7 +807,7 @@ 13.178 cx_linked_list *right = (cx_linked_list *) other; 13.179 return cx_linked_list_compare(left->begin, right->begin, 13.180 CX_LL_LOC_NEXT, CX_LL_LOC_DATA, 13.181 - list->cmpfunc); 13.182 + list->base.cmpfunc); 13.183 } 13.184 13.185 static bool cx_ll_iter_valid(void const *it) { 13.186 @@ -817,8 +817,8 @@ 13.187 13.188 static void cx_ll_iter_next(void *it) { 13.189 struct cx_iterator_s *iter = it; 13.190 - if (iter->remove) { 13.191 - iter->remove = false; 13.192 + if (iter->base.remove) { 13.193 + iter->base.remove = false; 13.194 struct cx_list_s *list = iter->src_handle.m; 13.195 cx_linked_list *ll = iter->src_handle.m; 13.196 cx_linked_list_node *node = iter->elem_handle; 13.197 @@ -826,8 +826,8 @@ 13.198 cx_invoke_destructor(list, node->payload); 13.199 cx_linked_list_remove((void **) &ll->begin, (void **) &ll->end, 13.200 CX_LL_LOC_PREV, CX_LL_LOC_NEXT, node); 13.201 - list->size--; 13.202 - cxFree(list->allocator, node); 13.203 + list->base.size--; 13.204 + cxFree(list->base.allocator, node); 13.205 } else { 13.206 iter->index++; 13.207 cx_linked_list_node *node = iter->elem_handle; 13.208 @@ -837,8 +837,8 @@ 13.209 13.210 static void cx_ll_iter_prev(void *it) { 13.211 struct cx_iterator_s *iter = it; 13.212 - if (iter->remove) { 13.213 - iter->remove = false; 13.214 + if (iter->base.remove) { 13.215 + iter->base.remove = false; 13.216 struct cx_list_s *list = iter->src_handle.m; 13.217 cx_linked_list *ll = iter->src_handle.m; 13.218 cx_linked_list_node *node = iter->elem_handle; 13.219 @@ -847,8 +847,8 @@ 13.220 cx_invoke_destructor(list, node->payload); 13.221 cx_linked_list_remove((void **) &ll->begin, (void **) &ll->end, 13.222 CX_LL_LOC_PREV, CX_LL_LOC_NEXT, node); 13.223 - list->size--; 13.224 - cxFree(list->allocator, node); 13.225 + list->base.size--; 13.226 + cxFree(list->base.allocator, node); 13.227 } else { 13.228 iter->index--; 13.229 cx_linked_list_node *node = iter->elem_handle; 13.230 @@ -871,13 +871,13 @@ 13.231 iter.index = index; 13.232 iter.src_handle.c = list; 13.233 iter.elem_handle = cx_ll_node_at((cx_linked_list const *) list, index); 13.234 - iter.elem_size = list->item_size; 13.235 - iter.elem_count = list->size; 13.236 - iter.valid = cx_ll_iter_valid; 13.237 - iter.current = cx_ll_iter_current; 13.238 - iter.next = backwards ? cx_ll_iter_prev : cx_ll_iter_next; 13.239 - iter.mutating = false; 13.240 - iter.remove = false; 13.241 + iter.elem_size = list->base.item_size; 13.242 + iter.elem_count = list->base.size; 13.243 + iter.base.valid = cx_ll_iter_valid; 13.244 + iter.base.current = cx_ll_iter_current; 13.245 + iter.base.next = backwards ? cx_ll_iter_prev : cx_ll_iter_next; 13.246 + iter.base.mutating = false; 13.247 + iter.base.remove = false; 13.248 return iter; 13.249 } 13.250 13.251 @@ -895,8 +895,8 @@ 13.252 iter->index += prepend * (0 == result); 13.253 return result; 13.254 } else { 13.255 - int result = cx_ll_insert_element(list, list->size, elem); 13.256 - iter->index = list->size; 13.257 + int result = cx_ll_insert_element(list, list->base.size, elem); 13.258 + iter->index = list->base.size; 13.259 return result; 13.260 } 13.261 } 13.262 @@ -908,11 +908,11 @@ 13.263 while (node) { 13.264 cx_invoke_destructor(list, node->payload); 13.265 void *next = node->next; 13.266 - cxFree(list->allocator, node); 13.267 + cxFree(list->base.allocator, node); 13.268 node = next; 13.269 } 13.270 13.271 - cxFree(list->allocator, list); 13.272 + cxFree(list->base.allocator, list); 13.273 } 13.274 13.275 static cx_list_class cx_linked_list_class = { 13.276 @@ -944,13 +944,13 @@ 13.277 if (list == NULL) return NULL; 13.278 13.279 list->base.cl = &cx_linked_list_class; 13.280 - list->base.allocator = allocator; 13.281 + list->base.base.allocator = allocator; 13.282 13.283 if (item_size > 0) { 13.284 - list->base.item_size = item_size; 13.285 - list->base.cmpfunc = comparator; 13.286 + list->base.base.item_size = item_size; 13.287 + list->base.base.cmpfunc = comparator; 13.288 } else { 13.289 - list->base.cmpfunc = comparator == NULL ? cx_cmp_ptr : comparator; 13.290 + list->base.base.cmpfunc = comparator == NULL ? cx_cmp_ptr : comparator; 13.291 cxListStorePointers((CxList *) list); 13.292 } 13.293
14.1 --- a/src/list.c Thu May 23 19:29:14 2024 +0200 14.2 +++ b/src/list.c Thu May 23 20:29:28 2024 +0200 14.3 @@ -47,14 +47,14 @@ 14.4 14.5 static void cx_pl_hack_cmpfunc(struct cx_list_s const *list) { 14.6 // cast away const - this is the hacky thing 14.7 - struct cx_list_s *l = (struct cx_list_s *) list; 14.8 + struct cx_collection_s *l = (struct cx_collection_s*) &list->base; 14.9 cx_pl_cmpfunc_impl = l->cmpfunc; 14.10 l->cmpfunc = cx_pl_cmpfunc; 14.11 } 14.12 14.13 static void cx_pl_unhack_cmpfunc(struct cx_list_s const *list) { 14.14 // cast away const - this is the hacky thing 14.15 - struct cx_list_s *l = (struct cx_list_s *) list; 14.16 + struct cx_collection_s *l = (struct cx_collection_s*) &list->base; 14.17 l->cmpfunc = cx_pl_cmpfunc_impl; 14.18 } 14.19 14.20 @@ -148,7 +148,7 @@ 14.21 14.22 static void *cx_pl_iter_current(void const *it) { 14.23 struct cx_iterator_s const *iter = it; 14.24 - void **ptr = iter->current_impl(it); 14.25 + void **ptr = iter->base.current_impl(it); 14.26 return ptr == NULL ? NULL : *ptr; 14.27 } 14.28 14.29 @@ -158,8 +158,8 @@ 14.30 bool backwards 14.31 ) { 14.32 struct cx_iterator_s iter = list->climpl->iterator(list, index, backwards); 14.33 - iter.current_impl = iter.current; 14.34 - iter.current = cx_pl_iter_current; 14.35 + iter.base.current_impl = iter.base.current; 14.36 + iter.base.current = cx_pl_iter_current; 14.37 return iter; 14.38 } 14.39 14.40 @@ -180,7 +180,7 @@ 14.41 }; 14.42 14.43 void cxListStoreObjects(CxList *list) { 14.44 - list->store_pointer = false; 14.45 + list->base.store_pointer = false; 14.46 if (list->climpl != NULL) { 14.47 list->cl = list->climpl; 14.48 list->climpl = NULL; 14.49 @@ -188,8 +188,8 @@ 14.50 } 14.51 14.52 void cxListStorePointers(CxList *list) { 14.53 - list->item_size = sizeof(void *); 14.54 - list->store_pointer = true; 14.55 + list->base.item_size = sizeof(void *); 14.56 + list->base.store_pointer = true; 14.57 list->climpl = list->cl; 14.58 list->cl = &cx_pointer_list_class; 14.59 } 14.60 @@ -221,7 +221,7 @@ 14.61 __attribute__((__unused__)) struct cx_list_s const *list, 14.62 struct cx_list_s const *other 14.63 ) { 14.64 - if (other->size == 0) return 0; 14.65 + if (other->base.size == 0) return 0; 14.66 return -1; 14.67 } 14.68 14.69 @@ -237,7 +237,7 @@ 14.70 CxIterator iter = {0}; 14.71 iter.src_handle.c = list; 14.72 iter.index = index; 14.73 - iter.valid = cx_emptyl_iter_valid; 14.74 + iter.base.valid = cx_emptyl_iter_valid; 14.75 return iter; 14.76 } 14.77 14.78 @@ -258,14 +258,16 @@ 14.79 }; 14.80 14.81 CxList cx_empty_list = { 14.82 - NULL, 14.83 - NULL, 14.84 - 0, 14.85 - 0, 14.86 - NULL, 14.87 - NULL, 14.88 - NULL, 14.89 - false, 14.90 + { 14.91 + NULL, 14.92 + NULL, 14.93 + 0, 14.94 + 0, 14.95 + NULL, 14.96 + NULL, 14.97 + NULL, 14.98 + false 14.99 + }, 14.100 &cx_empty_list_class, 14.101 NULL 14.102 }; 14.103 @@ -284,7 +286,7 @@ 14.104 ) { 14.105 if ( 14.106 // if one is storing pointers but the other is not 14.107 - (list->store_pointer ^ other->store_pointer) || 14.108 + (list->base.store_pointer ^ other->base.store_pointer) || 14.109 14.110 // if one class is wrapped but the other is not 14.111 ((list->climpl == NULL) ^ (other->climpl == NULL)) || 14.112 @@ -294,13 +296,13 @@ 14.113 (other->climpl != NULL ? other->climpl->compare : other->cl->compare)) 14.114 ) { 14.115 // lists are definitely different - cannot use internal compare function 14.116 - if (list->size == other->size) { 14.117 + if (list->base.size == other->base.size) { 14.118 CxIterator left = list->cl->iterator(list, 0, false); 14.119 CxIterator right = other->cl->iterator(other, 0, false); 14.120 - for (size_t i = 0; i < list->size; i++) { 14.121 + for (size_t i = 0; i < list->base.size; i++) { 14.122 void *leftValue = cxIteratorCurrent(left); 14.123 void *rightValue = cxIteratorCurrent(right); 14.124 - int d = list->cmpfunc(leftValue, rightValue); 14.125 + int d = list->base.cmpfunc(leftValue, rightValue); 14.126 if (d != 0) { 14.127 return d; 14.128 } 14.129 @@ -309,7 +311,7 @@ 14.130 } 14.131 return 0; 14.132 } else { 14.133 - return list->size < other->size ? -1 : 1; 14.134 + return list->base.size < other->base.size ? -1 : 1; 14.135 } 14.136 } else { 14.137 // lists are compatible 14.138 @@ -322,7 +324,7 @@ 14.139 size_t index 14.140 ) { 14.141 CxIterator it = list->cl->iterator(list, index, false); 14.142 - it.mutating = true; 14.143 + it.base.mutating = true; 14.144 return it; 14.145 } 14.146 14.147 @@ -331,6 +333,6 @@ 14.148 size_t index 14.149 ) { 14.150 CxIterator it = list->cl->iterator(list, index, true); 14.151 - it.mutating = true; 14.152 + it.base.mutating = true; 14.153 return it; 14.154 }
15.1 --- a/src/map.c Thu May 23 19:29:14 2024 +0200 15.2 +++ b/src/map.c Thu May 23 20:29:28 2024 +0200 15.3 @@ -52,7 +52,7 @@ 15.4 ) { 15.5 CxIterator iter = {0}; 15.6 iter.src_handle.c = map; 15.7 - iter.valid = cx_empty_map_iter_valid; 15.8 + iter.base.valid = cx_empty_map_iter_valid; 15.9 return iter; 15.10 } 15.11 15.12 @@ -66,14 +66,16 @@ 15.13 }; 15.14 15.15 CxMap cx_empty_map = { 15.16 - NULL, 15.17 - NULL, 15.18 - 0, 15.19 - 0, 15.20 - NULL, 15.21 - NULL, 15.22 - NULL, 15.23 - false, 15.24 + { 15.25 + NULL, 15.26 + NULL, 15.27 + 0, 15.28 + 0, 15.29 + NULL, 15.30 + NULL, 15.31 + NULL, 15.32 + false 15.33 + }, 15.34 &cx_empty_map_class 15.35 }; 15.36 15.37 @@ -83,18 +85,18 @@ 15.38 15.39 CxIterator cxMapMutIteratorValues(CxMap *map) { 15.40 CxIterator it = map->cl->iterator(map, CX_MAP_ITERATOR_VALUES); 15.41 - it.mutating = true; 15.42 + it.base.mutating = true; 15.43 return it; 15.44 } 15.45 15.46 CxIterator cxMapMutIteratorKeys(CxMap *map) { 15.47 CxIterator it = map->cl->iterator(map, CX_MAP_ITERATOR_KEYS); 15.48 - it.mutating = true; 15.49 + it.base.mutating = true; 15.50 return it; 15.51 } 15.52 15.53 CxIterator cxMapMutIterator(CxMap *map) { 15.54 CxIterator it = map->cl->iterator(map, CX_MAP_ITERATOR_PAIRS); 15.55 - it.mutating = true; 15.56 + it.base.mutating = true; 15.57 return it; 15.58 }
16.1 --- a/src/tree.c Thu May 23 19:29:14 2024 +0200 16.2 +++ b/src/tree.c Thu May 23 20:29:28 2024 +0200 16.3 @@ -280,12 +280,12 @@ 16.4 iter.skip = false; 16.5 16.6 // assign base iterator functions 16.7 - iter.mutating = false; 16.8 - iter.remove = false; 16.9 - iter.current_impl = NULL; 16.10 - iter.valid = cx_tree_iter_valid; 16.11 - iter.next = cx_tree_iter_next; 16.12 - iter.current = cx_tree_iter_current; 16.13 + iter.base.mutating = false; 16.14 + iter.base.remove = false; 16.15 + iter.base.current_impl = NULL; 16.16 + iter.base.valid = cx_tree_iter_valid; 16.17 + iter.base.next = cx_tree_iter_next; 16.18 + iter.base.current = cx_tree_iter_current; 16.19 16.20 return iter; 16.21 } 16.22 @@ -389,12 +389,12 @@ 16.23 iter.queue_last = NULL; 16.24 16.25 // assign base iterator functions 16.26 - iter.mutating = false; 16.27 - iter.remove = false; 16.28 - iter.current_impl = NULL; 16.29 - iter.valid = cx_tree_visitor_valid; 16.30 - iter.next = cx_tree_visitor_next; 16.31 - iter.current = cx_tree_visitor_current; 16.32 + iter.base.mutating = false; 16.33 + iter.base.remove = false; 16.34 + iter.base.current_impl = NULL; 16.35 + iter.base.valid = cx_tree_visitor_valid; 16.36 + iter.base.next = cx_tree_visitor_next; 16.37 + iter.base.current = cx_tree_visitor_current; 16.38 16.39 return iter; 16.40 }
17.1 --- a/tests/Makefile Thu May 23 19:29:14 2024 +0200 17.2 +++ b/tests/Makefile Thu May 23 20:29:28 2024 +0200 17.3 @@ -73,8 +73,8 @@ 17.4 $(TEST_DIR)/test_hash_map$(OBJ_EXT): test_hash_map.c ../src/cx/test.h \ 17.5 util_allocator.h ../src/cx/allocator.h ../src/cx/common.h \ 17.6 ../src/cx/hash_map.h ../src/cx/map.h ../src/cx/collection.h \ 17.7 - ../src/cx/allocator.h ../src/cx/iterator.h ../src/cx/string.h \ 17.8 - ../src/cx/hash_key.h 17.9 + ../src/cx/allocator.h ../src/cx/iterator.h ../src/cx/compare.h \ 17.10 + ../src/cx/string.h ../src/cx/hash_key.h 17.11 @echo "Compiling $<" 17.12 $(CC) -o $@ $(CFLAGS) -c $< 17.13 17.14 @@ -87,7 +87,7 @@ 17.15 util_allocator.h ../src/cx/allocator.h ../src/cx/common.h \ 17.16 ../src/cx/compare.h ../src/cx/utils.h ../src/cx/array_list.h \ 17.17 ../src/cx/list.h ../src/cx/collection.h ../src/cx/allocator.h \ 17.18 - ../src/cx/iterator.h ../src/cx/linked_list.h 17.19 + ../src/cx/iterator.h ../src/cx/compare.h ../src/cx/linked_list.h 17.20 @echo "Compiling $<" 17.21 $(CC) -o $@ $(CFLAGS) -c $< 17.22
18.1 --- a/tests/test_hash_map.c Thu May 23 19:29:14 2024 +0200 18.2 +++ b/tests/test_hash_map.c Thu May 23 20:29:28 2024 +0200 18.3 @@ -42,19 +42,19 @@ 18.4 for(size_t i = 0 ; i < hmap->bucket_count ; i++) { 18.5 CX_TEST_ASSERT(hmap->buckets[i] == NULL); 18.6 } 18.7 - CX_TEST_ASSERT(map->item_size == 1); 18.8 - CX_TEST_ASSERT(map->size == 0); 18.9 - CX_TEST_ASSERT(map->allocator == allocator); 18.10 - CX_TEST_ASSERT(!map->store_pointer); 18.11 - CX_TEST_ASSERT(map->cmpfunc == NULL); 18.12 - CX_TEST_ASSERT(map->simple_destructor == NULL); 18.13 - CX_TEST_ASSERT(map->advanced_destructor == NULL); 18.14 - CX_TEST_ASSERT(map->destructor_data == NULL); 18.15 + CX_TEST_ASSERT(map->base.item_size == 1); 18.16 + CX_TEST_ASSERT(map->base.size == 0); 18.17 + CX_TEST_ASSERT(map->base.allocator == allocator); 18.18 + CX_TEST_ASSERT(!map->base.store_pointer); 18.19 + CX_TEST_ASSERT(map->base.cmpfunc == NULL); 18.20 + CX_TEST_ASSERT(map->base.simple_destructor == NULL); 18.21 + CX_TEST_ASSERT(map->base.advanced_destructor == NULL); 18.22 + CX_TEST_ASSERT(map->base.destructor_data == NULL); 18.23 cxMapStorePointers(map); 18.24 - CX_TEST_ASSERT(map->store_pointer); 18.25 - CX_TEST_ASSERT(map->item_size == sizeof(void *)); 18.26 + CX_TEST_ASSERT(map->base.store_pointer); 18.27 + CX_TEST_ASSERT(map->base.item_size == sizeof(void *)); 18.28 cxMapStoreObjects(map); 18.29 - CX_TEST_ASSERT(!map->store_pointer); 18.30 + CX_TEST_ASSERT(!map->base.store_pointer); 18.31 18.32 cxMapDestroy(map); 18.33 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 18.34 @@ -73,10 +73,10 @@ 18.35 for (size_t i = 0; i < hmap->bucket_count; i++) { 18.36 CX_TEST_ASSERT(hmap->buckets[i] == NULL); 18.37 } 18.38 - CX_TEST_ASSERT(map->size == 0); 18.39 - CX_TEST_ASSERT(map->allocator == allocator); 18.40 - CX_TEST_ASSERT(map->store_pointer); 18.41 - CX_TEST_ASSERT(map->item_size == sizeof(void *)); 18.42 + CX_TEST_ASSERT(map->base.size == 0); 18.43 + CX_TEST_ASSERT(map->base.allocator == allocator); 18.44 + CX_TEST_ASSERT(map->base.store_pointer); 18.45 + CX_TEST_ASSERT(map->base.item_size == sizeof(void *)); 18.46 18.47 cxMapDestroy(map); 18.48 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 18.49 @@ -106,7 +106,7 @@ 18.50 int result = cxMapRehash(map); 18.51 CX_TEST_ASSERT(result == 0); 18.52 CX_TEST_ASSERT(((struct cx_hash_map_s *)map)->bucket_count == 25); 18.53 - CX_TEST_ASSERT(map->size == 10); 18.54 + CX_TEST_ASSERT(map->base.size == 10); 18.55 18.56 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "key 1"), "val 1")); 18.57 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "key 2"), "val 2")); 18.58 @@ -161,11 +161,11 @@ 18.59 cxMapPut(map, "key 2", (void *) "val 2"); 18.60 cxMapPut(map, "key 3", (void *) "val 3"); 18.61 18.62 - CX_TEST_ASSERT(map->size == 3); 18.63 + CX_TEST_ASSERT(map->base.size == 3); 18.64 18.65 cxMapClear(map); 18.66 18.67 - CX_TEST_ASSERT(map->size == 0); 18.68 + CX_TEST_ASSERT(map->base.size == 0); 18.69 CX_TEST_ASSERT(cxMapGet(map, "key 1") == NULL); 18.70 CX_TEST_ASSERT(cxMapGet(map, "key 2") == NULL); 18.71 CX_TEST_ASSERT(cxMapGet(map, "key 3") == NULL); 18.72 @@ -208,7 +208,7 @@ 18.73 18.74 // remove a string 18.75 cxMapRemove(map, "s2"); 18.76 - CX_TEST_ASSERT(map->size == 3); 18.77 + CX_TEST_ASSERT(map->base.size == 3); 18.78 18.79 // iterate 18.80 bool s3found = false, s4found = false, s5found = false; 18.81 @@ -244,8 +244,8 @@ 18.82 cx_foreach(CxMapEntry*, entry, iter) { 18.83 if (((char const *)entry->key->data)[4] % 2 == 1) cxIteratorFlagRemoval(iter); 18.84 } 18.85 - CX_TEST_ASSERT(map->size == 3); 18.86 - CX_TEST_ASSERT(iter.index == map->size); 18.87 + CX_TEST_ASSERT(map->base.size == 3); 18.88 + CX_TEST_ASSERT(iter.index == map->base.size); 18.89 18.90 CX_TEST_ASSERT(cxMapGet(map, "key 1") == NULL); 18.91 CX_TEST_ASSERT(cxMapGet(map, "key 2") != NULL); 18.92 @@ -348,7 +348,7 @@ 18.93 CxAllocator *allocator = &talloc.base; 18.94 CX_TEST_DO { 18.95 CxMap *map = cxHashMapCreate(allocator, CX_STORE_POINTERS, 0); 18.96 - map->simple_destructor = test_simple_destructor; 18.97 + map->base.simple_destructor = test_simple_destructor; 18.98 CX_TEST_CALL_SUBROUTINE(verify_any_destructor, map); 18.99 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 18.100 } 18.101 @@ -361,7 +361,7 @@ 18.102 CxAllocator *allocator = &talloc.base; 18.103 CX_TEST_DO { 18.104 CxMap *map = cxHashMapCreate(allocator, CX_STORE_POINTERS, 0); 18.105 - map->advanced_destructor = test_advanced_destructor; 18.106 + map->base.advanced_destructor = test_advanced_destructor; 18.107 CX_TEST_CALL_SUBROUTINE(verify_any_destructor, map); 18.108 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 18.109 } 18.110 @@ -370,7 +370,7 @@ 18.111 18.112 CX_TEST(test_empty_map_size) { 18.113 CX_TEST_DO { 18.114 - CX_TEST_ASSERT(cxEmptyMap->size == 0); 18.115 + CX_TEST_ASSERT(cxEmptyMap->base.size == 0); 18.116 } 18.117 } 18.118 18.119 @@ -430,7 +430,7 @@ 18.120 cxMapPut(map, cx_mutstr("foo"), "bar"); 18.121 cxMapPut(map, cx_str("hallo"), "welt"); 18.122 18.123 - CX_TEST_ASSERT(map->size == 3); 18.124 + CX_TEST_ASSERT(map->base.size == 3); 18.125 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "test"), "test")); 18.126 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "foo"), "bar")); 18.127 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "hallo"), "welt")); 18.128 @@ -441,16 +441,16 @@ 18.129 cxMapDetach(map, hallo); 18.130 cxMapPut(map, cx_hash_key_str("key"), "value"); 18.131 18.132 - CX_TEST_ASSERT(map->size == 2); 18.133 + CX_TEST_ASSERT(map->base.size == 2); 18.134 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "key"), "value")); 18.135 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "foo"), "bar")); 18.136 18.137 void *r; 18.138 r = cxMapRemoveAndGet(map, "key"); 18.139 r = cxMapRemoveAndGet(map, cx_str("foo")); 18.140 - if (r != NULL) map->size = 47; 18.141 + if (r != NULL) map->base.size = 47; 18.142 18.143 - CX_TEST_ASSERT(map->size == 0); 18.144 + CX_TEST_ASSERT(map->base.size == 0); 18.145 18.146 cxMapDestroy(map); 18.147 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 18.148 @@ -539,21 +539,21 @@ 18.149 18.150 static CX_TEST_SUBROUTINE(verify_map_contents, CxMap *map) { 18.151 // verify that the reference map has same size (i.e. no other keys are mapped) 18.152 - CX_TEST_ASSERT(map->size == test_map_reference_size()); 18.153 + CX_TEST_ASSERT(map->base.size == test_map_reference_size()); 18.154 18.155 // verify key iterator 18.156 { 18.157 // collect the keys from the map iterator 18.158 CxIterator keyiter = cxMapIteratorKeys(map); 18.159 CX_TEST_ASSERT(keyiter.elem_size == sizeof(CxHashKey)); 18.160 - CX_TEST_ASSERT(keyiter.elem_count == map->size); 18.161 - CxHashKey *keys = calloc(map->size, sizeof(CxHashKey)); 18.162 + CX_TEST_ASSERT(keyiter.elem_count == map->base.size); 18.163 + CxHashKey *keys = calloc(map->base.size, sizeof(CxHashKey)); 18.164 cx_foreach(CxHashKey*, elem, keyiter) { 18.165 keys[keyiter.index] = *elem; 18.166 } 18.167 - CX_TEST_ASSERT(keyiter.index == map->size); 18.168 + CX_TEST_ASSERT(keyiter.index == map->base.size); 18.169 // verify that all keys are mapped to values in reference map 18.170 - for (size_t i = 0 ; i < map->size ; i++) { 18.171 + for (size_t i = 0 ; i < map->base.size ; i++) { 18.172 cxmutstr ksz = cx_strdup(cx_strn(keys[i].data, keys[i].len)); 18.173 CX_TEST_ASSERT(test_map_reference_get(ksz.ptr) != NULL); 18.174 cx_strfree(&ksz); 18.175 @@ -566,15 +566,15 @@ 18.176 // by using that the values in our test data are unique strings 18.177 // we can re-use a similar approach as above 18.178 CxIterator valiter = cxMapIteratorValues(map); 18.179 - CX_TEST_ASSERT(valiter.elem_size == map->item_size); 18.180 - CX_TEST_ASSERT(valiter.elem_count == map->size); 18.181 - char const** values = calloc(map->size, sizeof(char const*)); 18.182 + CX_TEST_ASSERT(valiter.elem_size == map->base.item_size); 18.183 + CX_TEST_ASSERT(valiter.elem_count == map->base.size); 18.184 + char const** values = calloc(map->base.size, sizeof(char const*)); 18.185 cx_foreach(char const*, elem, valiter) { 18.186 values[valiter.index] = elem; 18.187 } 18.188 - CX_TEST_ASSERT(valiter.index == map->size); 18.189 + CX_TEST_ASSERT(valiter.index == map->base.size); 18.190 // verify that all values are present in the reference map 18.191 - for (size_t i = 0 ; i < map->size ; i++) { 18.192 + for (size_t i = 0 ; i < map->base.size ; i++) { 18.193 bool found = false; 18.194 for (size_t j = 0; j < test_map_reference_len ; j++) { 18.195 if (test_map_reference[j].value == values[i]) { 18.196 @@ -591,16 +591,16 @@ 18.197 { 18.198 CxIterator pairiter = cxMapIterator(map); 18.199 CX_TEST_ASSERT(pairiter.elem_size == sizeof(CxMapEntry)); 18.200 - CX_TEST_ASSERT(pairiter.elem_count == map->size); 18.201 - struct test_map_kv *pairs = calloc(map->size, sizeof(struct test_map_kv)); 18.202 + CX_TEST_ASSERT(pairiter.elem_count == map->base.size); 18.203 + struct test_map_kv *pairs = calloc(map->base.size, sizeof(struct test_map_kv)); 18.204 cx_foreach(CxMapEntry*, entry, pairiter) { 18.205 CxHashKey const *key = entry->key; 18.206 pairs[pairiter.index].key = cx_strdup(cx_strn(key->data, key->len)).ptr; 18.207 pairs[pairiter.index].value = entry->value; 18.208 } 18.209 - CX_TEST_ASSERT(pairiter.index == map->size); 18.210 + CX_TEST_ASSERT(pairiter.index == map->base.size); 18.211 // verify that all pairs are present in the reference map 18.212 - for (size_t i = 0 ; i < map->size ; i++) { 18.213 + for (size_t i = 0 ; i < map->base.size ; i++) { 18.214 CX_TEST_ASSERT(test_map_reference_get(pairs[i].key) == pairs[i].value); 18.215 // this was strdup'ed 18.216 free((void*)pairs[i].key);
19.1 --- a/tests/test_list.c Thu May 23 19:29:14 2024 +0200 19.2 +++ b/tests/test_list.c Thu May 23 20:29:28 2024 +0200 19.3 @@ -622,7 +622,7 @@ 19.4 19.5 CX_TEST(test_empty_list_size) { 19.6 CX_TEST_DO { 19.7 - CX_TEST_ASSERT(cxEmptyList->size == 0); 19.8 + CX_TEST_ASSERT(cxEmptyList->base.size == 0); 19.9 CX_TEST_ASSERT(cxListSize(cxEmptyList) == 0); 19.10 } 19.11 } 19.12 @@ -706,13 +706,13 @@ 19.13 CX_TEST_DO { 19.14 CxList *list = cxLinkedListCreate(alloc, cx_cmp_int, sizeof(int)); 19.15 CX_TEST_ASSERT(list != NULL); 19.16 - CX_TEST_ASSERT(list->item_size == sizeof(int)); 19.17 - CX_TEST_ASSERT(list->simple_destructor == NULL); 19.18 - CX_TEST_ASSERT(list->advanced_destructor == NULL); 19.19 - CX_TEST_ASSERT(list->destructor_data == NULL); 19.20 + CX_TEST_ASSERT(list->base.item_size == sizeof(int)); 19.21 + CX_TEST_ASSERT(list->base.simple_destructor == NULL); 19.22 + CX_TEST_ASSERT(list->base.advanced_destructor == NULL); 19.23 + CX_TEST_ASSERT(list->base.destructor_data == NULL); 19.24 CX_TEST_ASSERT(cxListSize(list) == 0); 19.25 - CX_TEST_ASSERT(list->allocator == alloc); 19.26 - CX_TEST_ASSERT(list->cmpfunc == cx_cmp_int); 19.27 + CX_TEST_ASSERT(list->base.allocator == alloc); 19.28 + CX_TEST_ASSERT(list->base.cmpfunc == cx_cmp_int); 19.29 CX_TEST_ASSERT(!cxListIsStoringPointers(list)); 19.30 cxListDestroy(list); 19.31 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 19.32 @@ -724,13 +724,13 @@ 19.33 CxList *list = cxLinkedListCreateSimple(sizeof(int)); 19.34 CX_TEST_DO { 19.35 CX_TEST_ASSERT(list != NULL); 19.36 - CX_TEST_ASSERT(list->item_size == sizeof(int)); 19.37 - CX_TEST_ASSERT(list->simple_destructor == NULL); 19.38 - CX_TEST_ASSERT(list->advanced_destructor == NULL); 19.39 - CX_TEST_ASSERT(list->destructor_data == NULL); 19.40 + CX_TEST_ASSERT(list->base.item_size == sizeof(int)); 19.41 + CX_TEST_ASSERT(list->base.simple_destructor == NULL); 19.42 + CX_TEST_ASSERT(list->base.advanced_destructor == NULL); 19.43 + CX_TEST_ASSERT(list->base.destructor_data == NULL); 19.44 CX_TEST_ASSERT(cxListSize(list) == 0); 19.45 - CX_TEST_ASSERT(list->allocator == cxDefaultAllocator); 19.46 - CX_TEST_ASSERT(list->cmpfunc == NULL); 19.47 + CX_TEST_ASSERT(list->base.allocator == cxDefaultAllocator); 19.48 + CX_TEST_ASSERT(list->base.cmpfunc == NULL); 19.49 CX_TEST_ASSERT(!cxListIsStoringPointers(list)); 19.50 } 19.51 cxListDestroy(list); 19.52 @@ -741,7 +741,7 @@ 19.53 CX_TEST_DO { 19.54 CX_TEST_ASSERT(!cxListIsStoringPointers(list)); 19.55 cxListStorePointers(list); 19.56 - CX_TEST_ASSERT(list->item_size == sizeof(void *)); 19.57 + CX_TEST_ASSERT(list->base.item_size == sizeof(void *)); 19.58 CX_TEST_ASSERT(list->cl != NULL); 19.59 CX_TEST_ASSERT(list->climpl != NULL); 19.60 CX_TEST_ASSERT(cxListIsStoringPointers(list)); 19.61 @@ -757,13 +757,13 @@ 19.62 CxList *list = cxLinkedListCreateSimple(CX_STORE_POINTERS); 19.63 CX_TEST_DO { 19.64 CX_TEST_ASSERT(list != NULL); 19.65 - CX_TEST_ASSERT(list->item_size == sizeof(void*)); 19.66 - CX_TEST_ASSERT(list->simple_destructor == NULL); 19.67 - CX_TEST_ASSERT(list->advanced_destructor == NULL); 19.68 - CX_TEST_ASSERT(list->destructor_data == NULL); 19.69 + CX_TEST_ASSERT(list->base.item_size == sizeof(void*)); 19.70 + CX_TEST_ASSERT(list->base.simple_destructor == NULL); 19.71 + CX_TEST_ASSERT(list->base.advanced_destructor == NULL); 19.72 + CX_TEST_ASSERT(list->base.destructor_data == NULL); 19.73 CX_TEST_ASSERT(cxListSize(list) == 0); 19.74 - CX_TEST_ASSERT(list->allocator == cxDefaultAllocator); 19.75 - CX_TEST_ASSERT(list->cmpfunc == cx_cmp_ptr); 19.76 + CX_TEST_ASSERT(list->base.allocator == cxDefaultAllocator); 19.77 + CX_TEST_ASSERT(list->base.cmpfunc == cx_cmp_ptr); 19.78 CX_TEST_ASSERT(cxListIsStoringPointers(list)); 19.79 } 19.80 cxListDestroy(list); 19.81 @@ -776,13 +776,13 @@ 19.82 CX_TEST_DO { 19.83 CxList *list = cxArrayListCreate(alloc, cx_cmp_int, sizeof(int), 8); 19.84 CX_TEST_ASSERT(list != NULL); 19.85 - CX_TEST_ASSERT(list->item_size == sizeof(int)); 19.86 - CX_TEST_ASSERT(list->simple_destructor == NULL); 19.87 - CX_TEST_ASSERT(list->advanced_destructor == NULL); 19.88 - CX_TEST_ASSERT(list->destructor_data == NULL); 19.89 + CX_TEST_ASSERT(list->base.item_size == sizeof(int)); 19.90 + CX_TEST_ASSERT(list->base.simple_destructor == NULL); 19.91 + CX_TEST_ASSERT(list->base.advanced_destructor == NULL); 19.92 + CX_TEST_ASSERT(list->base.destructor_data == NULL); 19.93 CX_TEST_ASSERT(cxListSize(list) == 0); 19.94 - CX_TEST_ASSERT(list->allocator == alloc); 19.95 - CX_TEST_ASSERT(list->cmpfunc == cx_cmp_int); 19.96 + CX_TEST_ASSERT(list->base.allocator == alloc); 19.97 + CX_TEST_ASSERT(list->base.cmpfunc == cx_cmp_int); 19.98 CX_TEST_ASSERT(!cxListIsStoringPointers(list)); 19.99 cxListDestroy(list); 19.100 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 19.101 @@ -794,13 +794,13 @@ 19.102 CxList *list = cxArrayListCreateSimple(sizeof(int), 8); 19.103 CX_TEST_DO { 19.104 CX_TEST_ASSERT(list != NULL); 19.105 - CX_TEST_ASSERT(list->item_size == sizeof(int)); 19.106 - CX_TEST_ASSERT(list->simple_destructor == NULL); 19.107 - CX_TEST_ASSERT(list->advanced_destructor == NULL); 19.108 - CX_TEST_ASSERT(list->destructor_data == NULL); 19.109 + CX_TEST_ASSERT(list->base.item_size == sizeof(int)); 19.110 + CX_TEST_ASSERT(list->base.simple_destructor == NULL); 19.111 + CX_TEST_ASSERT(list->base.advanced_destructor == NULL); 19.112 + CX_TEST_ASSERT(list->base.destructor_data == NULL); 19.113 CX_TEST_ASSERT(cxListSize(list) == 0); 19.114 - CX_TEST_ASSERT(list->allocator == cxDefaultAllocator); 19.115 - CX_TEST_ASSERT(list->cmpfunc == NULL); 19.116 + CX_TEST_ASSERT(list->base.allocator == cxDefaultAllocator); 19.117 + CX_TEST_ASSERT(list->base.cmpfunc == NULL); 19.118 CX_TEST_ASSERT(!cxListIsStoringPointers(list)); 19.119 } 19.120 cxListDestroy(list); 19.121 @@ -810,13 +810,13 @@ 19.122 CxList *list = cxArrayListCreateSimple(CX_STORE_POINTERS, 8); 19.123 CX_TEST_DO { 19.124 CX_TEST_ASSERT(list != NULL); 19.125 - CX_TEST_ASSERT(list->item_size == sizeof(void*)); 19.126 - CX_TEST_ASSERT(list->simple_destructor == NULL); 19.127 - CX_TEST_ASSERT(list->advanced_destructor == NULL); 19.128 - CX_TEST_ASSERT(list->destructor_data == NULL); 19.129 + CX_TEST_ASSERT(list->base.item_size == sizeof(void*)); 19.130 + CX_TEST_ASSERT(list->base.simple_destructor == NULL); 19.131 + CX_TEST_ASSERT(list->base.advanced_destructor == NULL); 19.132 + CX_TEST_ASSERT(list->base.destructor_data == NULL); 19.133 CX_TEST_ASSERT(cxListSize(list) == 0); 19.134 - CX_TEST_ASSERT(list->allocator == cxDefaultAllocator); 19.135 - CX_TEST_ASSERT(list->cmpfunc == cx_cmp_ptr); 19.136 + CX_TEST_ASSERT(list->base.allocator == cxDefaultAllocator); 19.137 + CX_TEST_ASSERT(list->base.cmpfunc == cx_cmp_ptr); 19.138 CX_TEST_ASSERT(cxListIsStoringPointers(list)); 19.139 } 19.140 cxListDestroy(list); 19.141 @@ -848,7 +848,7 @@ 19.142 CX_TEST_DO { 19.143 int item = 0; 19.144 CxList *list = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int, CX_STORE_POINTERS); 19.145 - list->simple_destructor = test_fake_simple_int_destr; 19.146 + list->base.simple_destructor = test_fake_simple_int_destr; 19.147 cxListAdd(list, &item); 19.148 cxListDestroy(list); 19.149 CX_TEST_ASSERT(item == 42); 19.150 @@ -862,8 +862,8 @@ 19.151 CX_TEST_DO { 19.152 void *item = cxMalloc(alloc, sizeof(int)); 19.153 CxList *list = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int, CX_STORE_POINTERS); 19.154 - list->destructor_data = alloc; 19.155 - list->advanced_destructor = (cx_destructor_func2) cxFree; 19.156 + list->base.destructor_data = alloc; 19.157 + list->base.advanced_destructor = (cx_destructor_func2) cxFree; 19.158 cxListAdd(list, item); 19.159 CX_TEST_ASSERT(!cx_testing_allocator_verify(&talloc)); 19.160 cxListDestroy(list); 19.161 @@ -894,7 +894,7 @@ 19.162 CX_TEST_DO { 19.163 int item = 0; 19.164 CxList *list = cxArrayListCreate(cxDefaultAllocator, cx_cmp_int, CX_STORE_POINTERS, 4); 19.165 - list->simple_destructor = test_fake_simple_int_destr; 19.166 + list->base.simple_destructor = test_fake_simple_int_destr; 19.167 cxListAdd(list, &item); 19.168 cxListDestroy(list); 19.169 CX_TEST_ASSERT(item == 42); 19.170 @@ -908,8 +908,8 @@ 19.171 CX_TEST_DO { 19.172 void *item = cxMalloc(alloc, sizeof(int)); 19.173 CxList *list = cxArrayListCreate(cxDefaultAllocator, cx_cmp_int, CX_STORE_POINTERS, 4); 19.174 - list->destructor_data = alloc; 19.175 - list->advanced_destructor = (cx_destructor_func2) cxFree; 19.176 + list->base.destructor_data = alloc; 19.177 + list->base.advanced_destructor = (cx_destructor_func2) cxFree; 19.178 cxListAdd(list, item); 19.179 CX_TEST_ASSERT(!cx_testing_allocator_verify(&talloc)); 19.180 cxListDestroy(list); 19.181 @@ -1207,8 +1207,8 @@ 19.182 int *testdata = int_test_data_added_to_list(list, isptrlist, len); 19.183 19.184 CxIterator iter = cxListIterator(list); 19.185 - CX_TEST_ASSERT(iter.elem_size == list->item_size); 19.186 - CX_TEST_ASSERT(iter.elem_count == list->size); 19.187 + CX_TEST_ASSERT(iter.elem_size == list->base.item_size); 19.188 + CX_TEST_ASSERT(iter.elem_count == list->base.size); 19.189 size_t i = 0; 19.190 cx_foreach(int*, x, iter) { 19.191 CX_TEST_ASSERT(i == iter.index); 19.192 @@ -1225,8 +1225,8 @@ 19.193 CX_TEST_ASSERT(i == 0); 19.194 i = len / 2; 19.195 CxIterator mut_iter = cxListMutIteratorAt(list, i); 19.196 - CX_TEST_ASSERT(mut_iter.elem_size == list->item_size); 19.197 - CX_TEST_ASSERT(mut_iter.elem_count == list->size); 19.198 + CX_TEST_ASSERT(mut_iter.elem_size == list->base.item_size); 19.199 + CX_TEST_ASSERT(mut_iter.elem_count == list->base.size); 19.200 size_t j = 0; 19.201 cx_foreach(int*, x, mut_iter) { 19.202 CX_TEST_ASSERT(mut_iter.index == len / 2 + j / 2); 19.203 @@ -1395,7 +1395,7 @@ 19.204 roll_out_test_combos(simple_destr, { 19.205 const size_t len = 60; 19.206 int *testdata = int_test_data_added_to_list(list, isptrlist, len); 19.207 - list->simple_destructor = simple_destr_test_fun; 19.208 + list->base.simple_destructor = simple_destr_test_fun; 19.209 CX_TEST_CALL_SUBROUTINE(test_list_verify_destructor, list, testdata, len); 19.210 free(testdata); 19.211 }) 19.212 @@ -1403,7 +1403,7 @@ 19.213 roll_out_test_combos(advanced_destr, { 19.214 const size_t len = 75; 19.215 int *testdata = int_test_data_added_to_list(list, isptrlist, len); 19.216 - list->advanced_destructor = advanced_destr_test_fun; 19.217 + list->base.advanced_destructor = advanced_destr_test_fun; 19.218 CX_TEST_CALL_SUBROUTINE(test_list_verify_destructor, list, testdata, len); 19.219 free(testdata); 19.220 })
20.1 --- a/tests/test_tree.c Thu May 23 19:29:14 2024 +0200 20.2 +++ b/tests/test_tree.c Thu May 23 20:29:28 2024 +0200 20.3 @@ -260,8 +260,8 @@ 20.4 CX_TEST_ASSERT(!iter.exiting); 20.5 CX_TEST_ASSERT(iter.counter == 1); 20.6 CX_TEST_ASSERT(iter.node == &root); 20.7 - CX_TEST_ASSERT(!iter.mutating); 20.8 - CX_TEST_ASSERT(!iter.remove); 20.9 + CX_TEST_ASSERT(!iter.base.mutating); 20.10 + CX_TEST_ASSERT(!iter.base.remove); 20.11 CX_TEST_ASSERT(iter.stack != NULL); 20.12 CX_TEST_ASSERT(iter.stack_capacity > 0); 20.13 CX_TEST_ASSERT(iter.stack_size == 1); 20.14 @@ -517,8 +517,8 @@ 20.15 CxTreeVisitor iter = cx_tree_visitor(&root, tree_child_list); 20.16 CX_TEST_ASSERT(iter.counter == 1); 20.17 CX_TEST_ASSERT(iter.node == &root); 20.18 - CX_TEST_ASSERT(!iter.mutating); 20.19 - CX_TEST_ASSERT(!iter.remove); 20.20 + CX_TEST_ASSERT(!iter.base.mutating); 20.21 + CX_TEST_ASSERT(!iter.base.remove); 20.22 CX_TEST_ASSERT(iter.queue_next != NULL); 20.23 CX_TEST_ASSERT(iter.queue_last != NULL); 20.24 CX_TEST_ASSERT(iter.depth == 1);