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->base; |
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->base; |
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); |
146 list->climpl->reverse(list); |
146 list->climpl->reverse(list); |
147 } |
147 } |
148 |
148 |
149 static void *cx_pl_iter_current(void const *it) { |
149 static void *cx_pl_iter_current(void const *it) { |
150 struct cx_iterator_s const *iter = it; |
150 struct cx_iterator_s const *iter = it; |
151 void **ptr = iter->current_impl(it); |
151 void **ptr = iter->base.current_impl(it); |
152 return ptr == NULL ? NULL : *ptr; |
152 return ptr == NULL ? NULL : *ptr; |
153 } |
153 } |
154 |
154 |
155 static struct cx_iterator_s cx_pl_iterator( |
155 static struct cx_iterator_s cx_pl_iterator( |
156 struct cx_list_s const *list, |
156 struct cx_list_s const *list, |
157 size_t index, |
157 size_t index, |
158 bool backwards |
158 bool backwards |
159 ) { |
159 ) { |
160 struct cx_iterator_s iter = list->climpl->iterator(list, index, backwards); |
160 struct cx_iterator_s iter = list->climpl->iterator(list, index, backwards); |
161 iter.current_impl = iter.current; |
161 iter.base.current_impl = iter.base.current; |
162 iter.current = cx_pl_iter_current; |
162 iter.base.current = cx_pl_iter_current; |
163 return iter; |
163 return iter; |
164 } |
164 } |
165 |
165 |
166 static cx_list_class cx_pointer_list_class = { |
166 static cx_list_class cx_pointer_list_class = { |
167 cx_pl_destructor, |
167 cx_pl_destructor, |
178 cx_pl_reverse, |
178 cx_pl_reverse, |
179 cx_pl_iterator, |
179 cx_pl_iterator, |
180 }; |
180 }; |
181 |
181 |
182 void cxListStoreObjects(CxList *list) { |
182 void cxListStoreObjects(CxList *list) { |
183 list->store_pointer = false; |
183 list->base.store_pointer = false; |
184 if (list->climpl != NULL) { |
184 if (list->climpl != NULL) { |
185 list->cl = list->climpl; |
185 list->cl = list->climpl; |
186 list->climpl = NULL; |
186 list->climpl = NULL; |
187 } |
187 } |
188 } |
188 } |
189 |
189 |
190 void cxListStorePointers(CxList *list) { |
190 void cxListStorePointers(CxList *list) { |
191 list->item_size = sizeof(void *); |
191 list->base.item_size = sizeof(void *); |
192 list->store_pointer = true; |
192 list->base.store_pointer = true; |
193 list->climpl = list->cl; |
193 list->climpl = list->cl; |
194 list->cl = &cx_pointer_list_class; |
194 list->cl = &cx_pointer_list_class; |
195 } |
195 } |
196 |
196 |
197 // </editor-fold> |
197 // </editor-fold> |
219 |
219 |
220 static int cx_emptyl_compare( |
220 static int cx_emptyl_compare( |
221 __attribute__((__unused__)) struct cx_list_s const *list, |
221 __attribute__((__unused__)) struct cx_list_s const *list, |
222 struct cx_list_s const *other |
222 struct cx_list_s const *other |
223 ) { |
223 ) { |
224 if (other->size == 0) return 0; |
224 if (other->base.size == 0) return 0; |
225 return -1; |
225 return -1; |
226 } |
226 } |
227 |
227 |
228 static bool cx_emptyl_iter_valid(__attribute__((__unused__)) void const *iter) { |
228 static bool cx_emptyl_iter_valid(__attribute__((__unused__)) void const *iter) { |
229 return false; |
229 return false; |
235 __attribute__((__unused__)) bool backwards |
235 __attribute__((__unused__)) bool backwards |
236 ) { |
236 ) { |
237 CxIterator iter = {0}; |
237 CxIterator iter = {0}; |
238 iter.src_handle.c = list; |
238 iter.src_handle.c = list; |
239 iter.index = index; |
239 iter.index = index; |
240 iter.valid = cx_emptyl_iter_valid; |
240 iter.base.valid = cx_emptyl_iter_valid; |
241 return iter; |
241 return iter; |
242 } |
242 } |
243 |
243 |
244 static cx_list_class cx_empty_list_class = { |
244 static cx_list_class cx_empty_list_class = { |
245 cx_emptyl_noop, |
245 cx_emptyl_noop, |
282 CxList const *list, |
284 CxList const *list, |
283 CxList const *other |
285 CxList const *other |
284 ) { |
286 ) { |
285 if ( |
287 if ( |
286 // if one is storing pointers but the other is not |
288 // if one is storing pointers but the other is not |
287 (list->store_pointer ^ other->store_pointer) || |
289 (list->base.store_pointer ^ other->base.store_pointer) || |
288 |
290 |
289 // if one class is wrapped but the other is not |
291 // if one class is wrapped but the other is not |
290 ((list->climpl == NULL) ^ (other->climpl == NULL)) || |
292 ((list->climpl == NULL) ^ (other->climpl == NULL)) || |
291 |
293 |
292 // if the resolved compare functions are not the same |
294 // if the resolved compare functions are not the same |
293 ((list->climpl != NULL ? list->climpl->compare : list->cl->compare) != |
295 ((list->climpl != NULL ? list->climpl->compare : list->cl->compare) != |
294 (other->climpl != NULL ? other->climpl->compare : other->cl->compare)) |
296 (other->climpl != NULL ? other->climpl->compare : other->cl->compare)) |
295 ) { |
297 ) { |
296 // lists are definitely different - cannot use internal compare function |
298 // lists are definitely different - cannot use internal compare function |
297 if (list->size == other->size) { |
299 if (list->base.size == other->base.size) { |
298 CxIterator left = list->cl->iterator(list, 0, false); |
300 CxIterator left = list->cl->iterator(list, 0, false); |
299 CxIterator right = other->cl->iterator(other, 0, false); |
301 CxIterator right = other->cl->iterator(other, 0, false); |
300 for (size_t i = 0; i < list->size; i++) { |
302 for (size_t i = 0; i < list->base.size; i++) { |
301 void *leftValue = cxIteratorCurrent(left); |
303 void *leftValue = cxIteratorCurrent(left); |
302 void *rightValue = cxIteratorCurrent(right); |
304 void *rightValue = cxIteratorCurrent(right); |
303 int d = list->cmpfunc(leftValue, rightValue); |
305 int d = list->base.cmpfunc(leftValue, rightValue); |
304 if (d != 0) { |
306 if (d != 0) { |
305 return d; |
307 return d; |
306 } |
308 } |
307 cxIteratorNext(left); |
309 cxIteratorNext(left); |
308 cxIteratorNext(right); |
310 cxIteratorNext(right); |
309 } |
311 } |
310 return 0; |
312 return 0; |
311 } else { |
313 } else { |
312 return list->size < other->size ? -1 : 1; |
314 return list->base.size < other->base.size ? -1 : 1; |
313 } |
315 } |
314 } else { |
316 } else { |
315 // lists are compatible |
317 // lists are compatible |
316 return list->cl->compare(list, other); |
318 return list->cl->compare(list, other); |
317 } |
319 } |
320 CxIterator cxListMutIteratorAt( |
322 CxIterator cxListMutIteratorAt( |
321 CxList *list, |
323 CxList *list, |
322 size_t index |
324 size_t index |
323 ) { |
325 ) { |
324 CxIterator it = list->cl->iterator(list, index, false); |
326 CxIterator it = list->cl->iterator(list, index, false); |
325 it.mutating = true; |
327 it.base.mutating = true; |
326 return it; |
328 return it; |
327 } |
329 } |
328 |
330 |
329 CxIterator cxListMutBackwardsIteratorAt( |
331 CxIterator cxListMutBackwardsIteratorAt( |
330 CxList *list, |
332 CxList *list, |
331 size_t index |
333 size_t index |
332 ) { |
334 ) { |
333 CxIterator it = list->cl->iterator(list, index, true); |
335 CxIterator it = list->cl->iterator(list, index, true); |
334 it.mutating = true; |
336 it.base.mutating = true; |
335 return it; |
337 return it; |
336 } |
338 } |