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(struct cx_list_s const *list) { |
49 // cast away const - this is the hacky thing |
49 // cast away const - this is the hacky thing |
50 struct cx_list_s *l = (struct cx_list_s *) list; |
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(struct cx_list_s const *list) { |
56 // cast away const - this is the hacky thing |
56 // cast away const - this is the hacky thing |
57 struct cx_list_s *l = (struct cx_list_s *) list; |
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 |
61 static void cx_pl_destructor(struct cx_list_s *list) { |
61 static void cx_pl_destructor(struct cx_list_s *list) { |
62 list->climpl->destructor(list); |
62 list->climpl->destructor(list); |
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 int cx_pl_insert_iter( |
82 static int cx_pl_insert_iter( |
83 struct cx_mut_iterator_s *iter, |
83 struct cx_iterator_s *iter, |
84 void const *elem, |
84 void const *elem, |
85 int prepend |
85 int prepend |
86 ) { |
86 ) { |
87 struct cx_list_s *list = iter->src_handle; |
87 struct cx_list_s *list = iter->src_handle.m; |
88 return list->climpl->insert_iter(iter, &elem, prepend); |
88 return list->climpl->insert_iter(iter, &elem, prepend); |
89 } |
89 } |
90 |
90 |
91 static int cx_pl_remove( |
91 static int cx_pl_remove( |
92 struct cx_list_s *list, |
92 struct cx_list_s *list, |
113 ) { |
113 ) { |
114 void **ptr = list->climpl->at(list, index); |
114 void **ptr = list->climpl->at(list, index); |
115 return ptr == NULL ? NULL : *ptr; |
115 return ptr == NULL ? NULL : *ptr; |
116 } |
116 } |
117 |
117 |
118 static ssize_t cx_pl_find( |
118 static ssize_t cx_pl_find_remove( |
119 struct cx_list_s const *list, |
119 struct cx_list_s *list, |
120 void const *elem |
120 void const *elem, |
|
121 bool remove |
121 ) { |
122 ) { |
122 cx_pl_hack_cmpfunc(list); |
123 cx_pl_hack_cmpfunc(list); |
123 ssize_t ret = list->climpl->find(list, &elem); |
124 ssize_t ret = list->climpl->find_remove(list, &elem, remove); |
124 cx_pl_unhack_cmpfunc(list); |
125 cx_pl_unhack_cmpfunc(list); |
125 return ret; |
126 return ret; |
126 } |
127 } |
127 |
128 |
128 static void cx_pl_sort(struct cx_list_s *list) { |
129 static void cx_pl_sort(struct cx_list_s *list) { |
169 cx_pl_insert_iter, |
170 cx_pl_insert_iter, |
170 cx_pl_remove, |
171 cx_pl_remove, |
171 cx_pl_clear, |
172 cx_pl_clear, |
172 cx_pl_swap, |
173 cx_pl_swap, |
173 cx_pl_at, |
174 cx_pl_at, |
174 cx_pl_find, |
175 cx_pl_find_remove, |
175 cx_pl_sort, |
176 cx_pl_sort, |
176 cx_pl_compare, |
177 cx_pl_compare, |
177 cx_pl_reverse, |
178 cx_pl_reverse, |
178 cx_pl_iterator, |
179 cx_pl_iterator, |
179 }; |
180 }; |
180 |
181 |
181 void cxListStoreObjects(CxList *list) { |
182 void cxListStoreObjects(CxList *list) { |
182 list->store_pointer = false; |
183 list->collection.store_pointer = false; |
183 if (list->climpl != NULL) { |
184 if (list->climpl != NULL) { |
184 list->cl = list->climpl; |
185 list->cl = list->climpl; |
185 list->climpl = NULL; |
186 list->climpl = NULL; |
186 } |
187 } |
187 } |
188 } |
188 |
189 |
189 void cxListStorePointers(CxList *list) { |
190 void cxListStorePointers(CxList *list) { |
190 list->item_size = sizeof(void *); |
191 list->collection.elem_size = sizeof(void *); |
191 list->store_pointer = true; |
192 list->collection.store_pointer = true; |
192 list->climpl = list->cl; |
193 list->climpl = list->cl; |
193 list->cl = &cx_pointer_list_class; |
194 list->cl = &cx_pointer_list_class; |
194 } |
195 } |
195 |
196 |
196 // </editor-fold> |
197 // </editor-fold> |
206 __attribute__((__unused__)) size_t index |
207 __attribute__((__unused__)) size_t index |
207 ) { |
208 ) { |
208 return NULL; |
209 return NULL; |
209 } |
210 } |
210 |
211 |
211 static ssize_t cx_emptyl_find( |
212 static ssize_t cx_emptyl_find_remove( |
212 __attribute__((__unused__)) struct cx_list_s const *list, |
213 __attribute__((__unused__)) struct cx_list_s *list, |
213 __attribute__((__unused__)) void const *elem |
214 __attribute__((__unused__)) void const *elem, |
|
215 __attribute__((__unused__)) bool remove |
214 ) { |
216 ) { |
215 return -1; |
217 return -1; |
216 } |
218 } |
217 |
219 |
218 static int cx_emptyl_compare( |
220 static int cx_emptyl_compare( |
219 __attribute__((__unused__)) struct cx_list_s const *list, |
221 __attribute__((__unused__)) struct cx_list_s const *list, |
220 struct cx_list_s const *other |
222 struct cx_list_s const *other |
221 ) { |
223 ) { |
222 if (other->size == 0) return 0; |
224 if (other->collection.size == 0) return 0; |
223 return -1; |
225 return -1; |
224 } |
226 } |
225 |
227 |
226 static bool cx_emptyl_iter_valid(__attribute__((__unused__)) void const *iter) { |
228 static bool cx_emptyl_iter_valid(__attribute__((__unused__)) void const *iter) { |
227 return false; |
229 return false; |
280 CxList const *list, |
284 CxList const *list, |
281 CxList const *other |
285 CxList const *other |
282 ) { |
286 ) { |
283 if ( |
287 if ( |
284 // if one is storing pointers but the other is not |
288 // if one is storing pointers but the other is not |
285 (list->store_pointer ^ other->store_pointer) || |
289 (list->collection.store_pointer ^ other->collection.store_pointer) || |
286 |
290 |
287 // if one class is wrapped but the other is not |
291 // if one class is wrapped but the other is not |
288 ((list->climpl == NULL) ^ (other->climpl == NULL)) || |
292 ((list->climpl == NULL) ^ (other->climpl == NULL)) || |
289 |
293 |
290 // if the resolved compare functions are not the same |
294 // if the resolved compare functions are not the same |
291 ((list->climpl != NULL ? list->climpl->compare : list->cl->compare) != |
295 ((list->climpl != NULL ? list->climpl->compare : list->cl->compare) != |
292 (other->climpl != NULL ? other->climpl->compare : other->cl->compare)) |
296 (other->climpl != NULL ? other->climpl->compare : other->cl->compare)) |
293 ) { |
297 ) { |
294 // lists are definitely different - cannot use internal compare function |
298 // lists are definitely different - cannot use internal compare function |
295 if (list->size == other->size) { |
299 if (list->collection.size == other->collection.size) { |
296 CxIterator left = cxListIterator(list); |
300 CxIterator left = list->cl->iterator(list, 0, false); |
297 CxIterator right = cxListIterator(other); |
301 CxIterator right = other->cl->iterator(other, 0, false); |
298 for (size_t i = 0; i < list->size; i++) { |
302 for (size_t i = 0; i < list->collection.size; i++) { |
299 void *leftValue = cxIteratorCurrent(left); |
303 void *leftValue = cxIteratorCurrent(left); |
300 void *rightValue = cxIteratorCurrent(right); |
304 void *rightValue = cxIteratorCurrent(right); |
301 int d = list->cmpfunc(leftValue, rightValue); |
305 int d = list->collection.cmpfunc(leftValue, rightValue); |
302 if (d != 0) { |
306 if (d != 0) { |
303 return d; |
307 return d; |
304 } |
308 } |
305 cxIteratorNext(left); |
309 cxIteratorNext(left); |
306 cxIteratorNext(right); |
310 cxIteratorNext(right); |
307 } |
311 } |
308 return 0; |
312 return 0; |
309 } else { |
313 } else { |
310 return list->size < other->size ? -1 : 1; |
314 return list->collection.size < other->collection.size ? -1 : 1; |
311 } |
315 } |
312 } else { |
316 } else { |
313 // lists are compatible |
317 // lists are compatible |
314 return list->cl->compare(list, other); |
318 return list->cl->compare(list, other); |
315 } |
319 } |
316 } |
320 } |
317 |
321 |
318 CxMutIterator cxListMutIteratorAt( |
322 CxIterator cxListMutIteratorAt( |
319 CxList *list, |
323 CxList *list, |
320 size_t index |
324 size_t index |
321 ) { |
325 ) { |
322 CxIterator it = list->cl->iterator(list, index, false); |
326 CxIterator it = list->cl->iterator(list, index, false); |
323 it.base.mutating = true; |
327 it.base.mutating = true; |
324 |
328 return it; |
325 // we know the iterators share the same memory layout |
329 } |
326 CxMutIterator iter; |
330 |
327 memcpy(&iter, &it, sizeof(CxMutIterator)); |
331 CxIterator cxListMutBackwardsIteratorAt( |
328 return iter; |
|
329 } |
|
330 |
|
331 CxMutIterator cxListMutBackwardsIteratorAt( |
|
332 CxList *list, |
332 CxList *list, |
333 size_t index |
333 size_t index |
334 ) { |
334 ) { |
335 CxIterator it = list->cl->iterator(list, index, true); |
335 CxIterator it = list->cl->iterator(list, index, true); |
336 it.base.mutating = true; |
336 it.base.mutating = true; |
337 |
337 return it; |
338 // we know the iterators share the same memory layout |
338 } |
339 CxMutIterator iter; |
|
340 memcpy(&iter, &it, sizeof(CxMutIterator)); |
|
341 return iter; |
|
342 } |
|