274 |
266 |
275 CxList *const cxEmptyList = &cx_empty_list; |
267 CxList *const cxEmptyList = &cx_empty_list; |
276 |
268 |
277 // </editor-fold> |
269 // </editor-fold> |
278 |
270 |
|
271 #define invoke_list_func(name, list, ...) \ |
|
272 ((list)->climpl == NULL ? (list)->cl->name : (list)->climpl->name) \ |
|
273 (list, __VA_ARGS__) |
|
274 |
|
275 size_t cx_list_default_insert_array( |
|
276 struct cx_list_s *list, |
|
277 size_t index, |
|
278 void const *data, |
|
279 size_t n |
|
280 ) { |
|
281 size_t elem_size = list->collection.elem_size; |
|
282 char const *src = data; |
|
283 size_t i = 0; |
|
284 for (; i < n; i++) { |
|
285 if (0 != invoke_list_func(insert_element, |
|
286 list, index + i, src + (i * elem_size))) { |
|
287 return i; |
|
288 } |
|
289 } |
|
290 return i; |
|
291 } |
|
292 |
|
293 void cx_list_default_sort(struct cx_list_s *list) { |
|
294 size_t elem_size = list->collection.elem_size; |
|
295 size_t list_size = list->collection.size; |
|
296 void *tmp = malloc(elem_size * list_size); |
|
297 if (tmp == NULL) abort(); |
|
298 |
|
299 // copy elements from source array |
|
300 char *loc = tmp; |
|
301 for (size_t i = 0; i < list_size; i++) { |
|
302 void *src = invoke_list_func(at, list, i); |
|
303 memcpy(loc, src, elem_size); |
|
304 loc += elem_size; |
|
305 } |
|
306 |
|
307 // qsort |
|
308 qsort(tmp, list_size, elem_size, |
|
309 list->collection.cmpfunc); |
|
310 |
|
311 // copy elements back |
|
312 loc = tmp; |
|
313 for (size_t i = 0; i < list_size; i++) { |
|
314 void *dest = invoke_list_func(at, list, i); |
|
315 memcpy(dest, loc, elem_size); |
|
316 loc += elem_size; |
|
317 } |
|
318 |
|
319 free(tmp); |
|
320 } |
|
321 |
|
322 int cx_list_default_swap(struct cx_list_s *list, size_t i, size_t j) { |
|
323 if (i == j) return 0; |
|
324 if (i >= list->collection.size) return 1; |
|
325 if (j >= list->collection.size) return 1; |
|
326 |
|
327 size_t elem_size = list->collection.elem_size; |
|
328 |
|
329 void *tmp = malloc(elem_size); |
|
330 if (tmp == NULL) return 1; |
|
331 |
|
332 void *ip = invoke_list_func(at, list, i); |
|
333 void *jp = invoke_list_func(at, list, j); |
|
334 |
|
335 memcpy(tmp, ip, elem_size); |
|
336 memcpy(ip, jp, elem_size); |
|
337 memcpy(jp, tmp, elem_size); |
|
338 |
|
339 free(tmp); |
|
340 |
|
341 return 0; |
|
342 } |
|
343 |
279 void cxListDestroy(CxList *list) { |
344 void cxListDestroy(CxList *list) { |
280 list->cl->destructor(list); |
345 list->cl->destructor(list); |
281 } |
346 } |
282 |
347 |
283 int cxListCompare( |
348 int cxListCompare( |
284 CxList const *list, |
349 CxList const *list, |
285 CxList const *other |
350 CxList const *other |
286 ) { |
351 ) { |
287 if ( |
352 bool cannot_optimize = false; |
288 // if one is storing pointers but the other is not |
353 |
289 (list->collection.store_pointer ^ other->collection.store_pointer) || |
354 // if one is storing pointers but the other is not |
290 |
355 cannot_optimize |= list->collection.store_pointer ^ other->collection.store_pointer; |
291 // if one class is wrapped but the other is not |
356 |
292 ((list->climpl == NULL) ^ (other->climpl == NULL)) || |
357 // if one class is wrapped but the other is not |
293 |
358 cannot_optimize |= (list->climpl == NULL) ^ (other->climpl == NULL); |
294 // if the resolved compare functions are not the same |
359 |
295 ((list->climpl != NULL ? list->climpl->compare : list->cl->compare) != |
360 // if the compare functions do not match or both are NULL |
296 (other->climpl != NULL ? other->climpl->compare : other->cl->compare)) |
361 if (!cannot_optimize) { |
297 ) { |
362 cx_compare_func list_cmp = (cx_compare_func) (list->climpl != NULL ? |
|
363 list->climpl->compare : list->cl->compare); |
|
364 cx_compare_func other_cmp = (cx_compare_func) (other->climpl != NULL ? |
|
365 other->climpl->compare : other->cl->compare); |
|
366 cannot_optimize |= list_cmp != other_cmp; |
|
367 cannot_optimize |= list_cmp == NULL; |
|
368 } |
|
369 |
|
370 if (cannot_optimize) { |
298 // lists are definitely different - cannot use internal compare function |
371 // lists are definitely different - cannot use internal compare function |
299 if (list->collection.size == other->collection.size) { |
372 if (list->collection.size == other->collection.size) { |
300 CxIterator left = list->cl->iterator(list, 0, false); |
373 CxIterator left = list->cl->iterator(list, 0, false); |
301 CxIterator right = other->cl->iterator(other, 0, false); |
374 CxIterator right = other->cl->iterator(other, 0, false); |
302 for (size_t i = 0; i < list->collection.size; i++) { |
375 for (size_t i = 0; i < list->collection.size; i++) { |