src/list.c

changeset 890
54565fd74e74
parent 877
608b14deea18
equal deleted inserted replaced
889:f549fd9fbd8f 890:54565fd74e74
33 // <editor-fold desc="Store Pointers Functionality"> 33 // <editor-fold desc="Store Pointers Functionality">
34 34
35 static _Thread_local cx_compare_func cx_pl_cmpfunc_impl; 35 static _Thread_local cx_compare_func cx_pl_cmpfunc_impl;
36 36
37 static int cx_pl_cmpfunc( 37 static int cx_pl_cmpfunc(
38 void const *l, 38 const void *l,
39 void const *r 39 const void *r
40 ) { 40 ) {
41 void *const *lptr = l; 41 void *const *lptr = l;
42 void *const *rptr = r; 42 void *const *rptr = r;
43 void const *left = lptr == NULL ? NULL : *lptr; 43 const void *left = lptr == NULL ? NULL : *lptr;
44 void const *right = rptr == NULL ? NULL : *rptr; 44 const void *right = rptr == NULL ? NULL : *rptr;
45 return cx_pl_cmpfunc_impl(left, right); 45 return cx_pl_cmpfunc_impl(left, right);
46 } 46 }
47 47
48 static void cx_pl_hack_cmpfunc(struct cx_list_s const *list) { 48 static void cx_pl_hack_cmpfunc(const struct cx_list_s *list) {
49 // cast away const - this is the hacky thing 49 // cast away const - this is the hacky thing
50 struct cx_collection_s *l = (struct cx_collection_s*) &list->collection; 50 struct cx_collection_s *l = (struct cx_collection_s*) &list->collection;
51 cx_pl_cmpfunc_impl = l->cmpfunc; 51 cx_pl_cmpfunc_impl = l->cmpfunc;
52 l->cmpfunc = cx_pl_cmpfunc; 52 l->cmpfunc = cx_pl_cmpfunc;
53 } 53 }
54 54
55 static void cx_pl_unhack_cmpfunc(struct cx_list_s const *list) { 55 static void cx_pl_unhack_cmpfunc(const struct cx_list_s *list) {
56 // cast away const - this is the hacky thing 56 // cast away const - this is the hacky thing
57 struct cx_collection_s *l = (struct cx_collection_s*) &list->collection; 57 struct cx_collection_s *l = (struct cx_collection_s*) &list->collection;
58 l->cmpfunc = cx_pl_cmpfunc_impl; 58 l->cmpfunc = cx_pl_cmpfunc_impl;
59 } 59 }
60 60
63 } 63 }
64 64
65 static int cx_pl_insert_element( 65 static int cx_pl_insert_element(
66 struct cx_list_s *list, 66 struct cx_list_s *list,
67 size_t index, 67 size_t index,
68 void const *element 68 const void *element
69 ) { 69 ) {
70 return list->climpl->insert_element(list, index, &element); 70 return list->climpl->insert_element(list, index, &element);
71 } 71 }
72 72
73 static size_t cx_pl_insert_array( 73 static size_t cx_pl_insert_array(
74 struct cx_list_s *list, 74 struct cx_list_s *list,
75 size_t index, 75 size_t index,
76 void const *array, 76 const void *array,
77 size_t n 77 size_t n
78 ) { 78 ) {
79 return list->climpl->insert_array(list, index, array, n); 79 return list->climpl->insert_array(list, index, array, n);
80 } 80 }
81 81
82 static size_t cx_pl_insert_sorted( 82 static size_t cx_pl_insert_sorted(
83 struct cx_list_s *list, 83 struct cx_list_s *list,
84 void const *array, 84 const void *array,
85 size_t n 85 size_t n
86 ) { 86 ) {
87 cx_pl_hack_cmpfunc(list); 87 cx_pl_hack_cmpfunc(list);
88 size_t result = list->climpl->insert_sorted(list, array, n); 88 size_t result = list->climpl->insert_sorted(list, array, n);
89 cx_pl_unhack_cmpfunc(list); 89 cx_pl_unhack_cmpfunc(list);
90 return result; 90 return result;
91 } 91 }
92 92
93 static int cx_pl_insert_iter( 93 static int cx_pl_insert_iter(
94 struct cx_iterator_s *iter, 94 struct cx_iterator_s *iter,
95 void const *elem, 95 const void *elem,
96 int prepend 96 int prepend
97 ) { 97 ) {
98 struct cx_list_s *list = iter->src_handle.m; 98 struct cx_list_s *list = iter->src_handle.m;
99 return list->climpl->insert_iter(iter, &elem, prepend); 99 return list->climpl->insert_iter(iter, &elem, prepend);
100 } 100 }
117 ) { 117 ) {
118 return list->climpl->swap(list, i, j); 118 return list->climpl->swap(list, i, j);
119 } 119 }
120 120
121 static void *cx_pl_at( 121 static void *cx_pl_at(
122 struct cx_list_s const *list, 122 const struct cx_list_s *list,
123 size_t index 123 size_t index
124 ) { 124 ) {
125 void **ptr = list->climpl->at(list, index); 125 void **ptr = list->climpl->at(list, index);
126 return ptr == NULL ? NULL : *ptr; 126 return ptr == NULL ? NULL : *ptr;
127 } 127 }
128 128
129 static ssize_t cx_pl_find_remove( 129 static ssize_t cx_pl_find_remove(
130 struct cx_list_s *list, 130 struct cx_list_s *list,
131 void const *elem, 131 const void *elem,
132 bool remove 132 bool remove
133 ) { 133 ) {
134 cx_pl_hack_cmpfunc(list); 134 cx_pl_hack_cmpfunc(list);
135 ssize_t ret = list->climpl->find_remove(list, &elem, remove); 135 ssize_t ret = list->climpl->find_remove(list, &elem, remove);
136 cx_pl_unhack_cmpfunc(list); 136 cx_pl_unhack_cmpfunc(list);
142 list->climpl->sort(list); 142 list->climpl->sort(list);
143 cx_pl_unhack_cmpfunc(list); 143 cx_pl_unhack_cmpfunc(list);
144 } 144 }
145 145
146 static int cx_pl_compare( 146 static int cx_pl_compare(
147 struct cx_list_s const *list, 147 const struct cx_list_s *list,
148 struct cx_list_s const *other 148 const struct cx_list_s *other
149 ) { 149 ) {
150 cx_pl_hack_cmpfunc(list); 150 cx_pl_hack_cmpfunc(list);
151 int ret = list->climpl->compare(list, other); 151 int ret = list->climpl->compare(list, other);
152 cx_pl_unhack_cmpfunc(list); 152 cx_pl_unhack_cmpfunc(list);
153 return ret; 153 return ret;
155 155
156 static void cx_pl_reverse(struct cx_list_s *list) { 156 static void cx_pl_reverse(struct cx_list_s *list) {
157 list->climpl->reverse(list); 157 list->climpl->reverse(list);
158 } 158 }
159 159
160 static void *cx_pl_iter_current(void const *it) { 160 static void *cx_pl_iter_current(const void *it) {
161 struct cx_iterator_s const *iter = it; 161 const struct cx_iterator_s *iter = it;
162 void **ptr = iter->base.current_impl(it); 162 void **ptr = iter->base.current_impl(it);
163 return ptr == NULL ? NULL : *ptr; 163 return ptr == NULL ? NULL : *ptr;
164 } 164 }
165 165
166 static struct cx_iterator_s cx_pl_iterator( 166 static struct cx_iterator_s cx_pl_iterator(
167 struct cx_list_s const *list, 167 const struct cx_list_s *list,
168 size_t index, 168 size_t index,
169 bool backwards 169 bool backwards
170 ) { 170 ) {
171 struct cx_iterator_s iter = list->climpl->iterator(list, index, backwards); 171 struct cx_iterator_s iter = list->climpl->iterator(list, index, backwards);
172 iter.base.current_impl = iter.base.current; 172 iter.base.current_impl = iter.base.current;
213 static void cx_emptyl_noop(__attribute__((__unused__)) CxList *list) { 213 static void cx_emptyl_noop(__attribute__((__unused__)) CxList *list) {
214 // this is a noop, but MUST be implemented 214 // this is a noop, but MUST be implemented
215 } 215 }
216 216
217 static void *cx_emptyl_at( 217 static void *cx_emptyl_at(
218 __attribute__((__unused__)) struct cx_list_s const *list, 218 __attribute__((__unused__)) const struct cx_list_s *list,
219 __attribute__((__unused__)) size_t index 219 __attribute__((__unused__)) size_t index
220 ) { 220 ) {
221 return NULL; 221 return NULL;
222 } 222 }
223 223
224 static ssize_t cx_emptyl_find_remove( 224 static ssize_t cx_emptyl_find_remove(
225 __attribute__((__unused__)) struct cx_list_s *list, 225 __attribute__((__unused__)) struct cx_list_s *list,
226 __attribute__((__unused__)) void const *elem, 226 __attribute__((__unused__)) const void *elem,
227 __attribute__((__unused__)) bool remove 227 __attribute__((__unused__)) bool remove
228 ) { 228 ) {
229 return -1; 229 return -1;
230 } 230 }
231 231
232 static bool cx_emptyl_iter_valid(__attribute__((__unused__)) void const *iter) { 232 static bool cx_emptyl_iter_valid(__attribute__((__unused__)) const void *iter) {
233 return false; 233 return false;
234 } 234 }
235 235
236 static CxIterator cx_emptyl_iterator( 236 static CxIterator cx_emptyl_iterator(
237 struct cx_list_s const *list, 237 const struct cx_list_s *list,
238 size_t index, 238 size_t index,
239 __attribute__((__unused__)) bool backwards 239 __attribute__((__unused__)) bool backwards
240 ) { 240 ) {
241 CxIterator iter = {0}; 241 CxIterator iter = {0};
242 iter.src_handle.c = list; 242 iter.src_handle.c = list;
286 (list, __VA_ARGS__) 286 (list, __VA_ARGS__)
287 287
288 size_t cx_list_default_insert_array( 288 size_t cx_list_default_insert_array(
289 struct cx_list_s *list, 289 struct cx_list_s *list,
290 size_t index, 290 size_t index,
291 void const *data, 291 const void *data,
292 size_t n 292 size_t n
293 ) { 293 ) {
294 size_t elem_size = list->collection.elem_size; 294 size_t elem_size = list->collection.elem_size;
295 char const *src = data; 295 const char *src = data;
296 size_t i = 0; 296 size_t i = 0;
297 for (; i < n; i++) { 297 for (; i < n; i++) {
298 if (0 != invoke_list_func(insert_element, 298 if (0 != invoke_list_func(insert_element,
299 list, index + i, src + (i * elem_size))) { 299 list, index + i, src + (i * elem_size))) {
300 return i; 300 return i;
303 return i; 303 return i;
304 } 304 }
305 305
306 size_t cx_list_default_insert_sorted( 306 size_t cx_list_default_insert_sorted(
307 struct cx_list_s *list, 307 struct cx_list_s *list,
308 void const *sorted_data, 308 const void *sorted_data,
309 size_t n 309 size_t n
310 ) { 310 ) {
311 // corner case 311 // corner case
312 if (n == 0) return 0; 312 if (n == 0) return 0;
313 313
314 size_t elem_size = list->collection.elem_size; 314 size_t elem_size = list->collection.elem_size;
315 cx_compare_func cmp = list->collection.cmpfunc; 315 cx_compare_func cmp = list->collection.cmpfunc;
316 char const *src = sorted_data; 316 const char *src = sorted_data;
317 317
318 // track indices and number of inserted items 318 // track indices and number of inserted items
319 size_t di = 0, si = 0, inserted = 0; 319 size_t di = 0, si = 0, inserted = 0;
320 320
321 // search the list for insertion points 321 // search the list for insertion points
322 for (; di < list->collection.size; di++) { 322 for (; di < list->collection.size; di++) {
323 void const *list_elm = invoke_list_func(at, list, di); 323 const void *list_elm = invoke_list_func(at, list, di);
324 324
325 // compare current list element with first source element 325 // compare current list element with first source element
326 // if less or equal, skip 326 // if less or equal, skip
327 if (cmp(list_elm, src) <= 0) { 327 if (cmp(list_elm, src) <= 0) {
328 continue; 328 continue;
329 } 329 }
330 330
331 // determine number of consecutive elements that can be inserted 331 // determine number of consecutive elements that can be inserted
332 size_t ins = 1; 332 size_t ins = 1;
333 char const *next = src; 333 const char *next = src;
334 while (++si < n) { 334 while (++si < n) {
335 next += elem_size; 335 next += elem_size;
336 // once we become larger than the list elem, break 336 // once we become larger than the list elem, break
337 if (cmp(list_elm, next) <= 0) { 337 if (cmp(list_elm, next) <= 0) {
338 break; 338 break;
420 void cxListDestroy(CxList *list) { 420 void cxListDestroy(CxList *list) {
421 list->cl->destructor(list); 421 list->cl->destructor(list);
422 } 422 }
423 423
424 int cxListCompare( 424 int cxListCompare(
425 CxList const *list, 425 const CxList *list,
426 CxList const *other 426 const CxList *other
427 ) { 427 ) {
428 bool cannot_optimize = false; 428 bool cannot_optimize = false;
429 429
430 // if one is storing pointers but the other is not 430 // if one is storing pointers but the other is not
431 cannot_optimize |= list->collection.store_pointer ^ other->collection.store_pointer; 431 cannot_optimize |= list->collection.store_pointer ^ other->collection.store_pointer;

mercurial