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; |