170 static void cx_arl_destructor(struct cx_list_s *list) { |
189 static void cx_arl_destructor(struct cx_list_s *list) { |
171 cx_array_list *arl = (cx_array_list *) list; |
190 cx_array_list *arl = (cx_array_list *) list; |
172 |
191 |
173 char *ptr = arl->data; |
192 char *ptr = arl->data; |
174 |
193 |
175 if (list->simple_destructor) { |
194 if (list->collection.simple_destructor) { |
176 for (size_t i = 0; i < list->size; i++) { |
195 for (size_t i = 0; i < list->collection.size; i++) { |
177 cx_invoke_simple_destructor(list, ptr); |
196 cx_invoke_simple_destructor(list, ptr); |
178 ptr += list->item_size; |
197 ptr += list->collection.elem_size; |
179 } |
198 } |
180 } |
199 } |
181 if (list->advanced_destructor) { |
200 if (list->collection.advanced_destructor) { |
182 for (size_t i = 0; i < list->size; i++) { |
201 for (size_t i = 0; i < list->collection.size; i++) { |
183 cx_invoke_advanced_destructor(list, ptr); |
202 cx_invoke_advanced_destructor(list, ptr); |
184 ptr += list->item_size; |
203 ptr += list->collection.elem_size; |
185 } |
204 } |
186 } |
205 } |
187 |
206 |
188 cxFree(list->allocator, arl->data); |
207 cxFree(list->collection.allocator, arl->data); |
189 cxFree(list->allocator, list); |
208 cxFree(list->collection.allocator, list); |
190 } |
209 } |
191 |
210 |
192 static size_t cx_arl_insert_array( |
211 static size_t cx_arl_insert_array( |
193 struct cx_list_s *list, |
212 struct cx_list_s *list, |
194 size_t index, |
213 size_t index, |
195 void const *array, |
214 void const *array, |
196 size_t n |
215 size_t n |
197 ) { |
216 ) { |
198 // out of bounds and special case check |
217 // out of bounds and special case check |
199 if (index > list->size || n == 0) return 0; |
218 if (index > list->collection.size || n == 0) return 0; |
200 |
219 |
201 // get a correctly typed pointer to the list |
220 // get a correctly typed pointer to the list |
202 cx_array_list *arl = (cx_array_list *) list; |
221 cx_array_list *arl = (cx_array_list *) list; |
203 |
222 |
204 // do we need to move some elements? |
223 // do we need to move some elements? |
205 if (index < list->size) { |
224 if (index < list->collection.size) { |
206 char const *first_to_move = (char const *) arl->data; |
225 char const *first_to_move = (char const *) arl->data; |
207 first_to_move += index * list->item_size; |
226 first_to_move += index * list->collection.elem_size; |
208 size_t elems_to_move = list->size - index; |
227 size_t elems_to_move = list->collection.size - index; |
209 size_t start_of_moved = index + n; |
228 size_t start_of_moved = index + n; |
210 |
229 |
211 if (CX_ARRAY_COPY_SUCCESS != cx_array_copy( |
230 if (CX_ARRAY_SUCCESS != cx_array_copy( |
212 &arl->data, |
231 &arl->data, |
213 &list->size, |
232 &list->collection.size, |
214 &arl->capacity, |
233 &arl->capacity, |
215 start_of_moved, |
234 start_of_moved, |
216 first_to_move, |
235 first_to_move, |
217 list->item_size, |
236 list->collection.elem_size, |
218 elems_to_move, |
237 elems_to_move, |
219 &arl->reallocator |
238 &arl->reallocator |
220 )) { |
239 )) { |
221 // if moving existing elems is unsuccessful, abort |
240 // if moving existing elems is unsuccessful, abort |
222 return 0; |
241 return 0; |
282 size_t index |
301 size_t index |
283 ) { |
302 ) { |
284 cx_array_list *arl = (cx_array_list *) list; |
303 cx_array_list *arl = (cx_array_list *) list; |
285 |
304 |
286 // out-of-bounds check |
305 // out-of-bounds check |
287 if (index >= list->size) { |
306 if (index >= list->collection.size) { |
288 return 1; |
307 return 1; |
289 } |
308 } |
290 |
309 |
291 // content destruction |
310 // content destruction |
292 cx_invoke_destructor(list, ((char *) arl->data) + index * list->item_size); |
311 cx_invoke_destructor(list, ((char *) arl->data) + index * list->collection.elem_size); |
293 |
312 |
294 // short-circuit removal of last element |
313 // short-circuit removal of last element |
295 if (index == list->size - 1) { |
314 if (index == list->collection.size - 1) { |
296 list->size--; |
315 list->collection.size--; |
297 return 0; |
316 return 0; |
298 } |
317 } |
299 |
318 |
300 // just move the elements starting at index to the left |
319 // just move the elements starting at index to the left |
301 int result = cx_array_copy( |
320 int result = cx_array_copy( |
302 &arl->data, |
321 &arl->data, |
303 &list->size, |
322 &list->collection.size, |
304 &arl->capacity, |
323 &arl->capacity, |
305 index, |
324 index, |
306 ((char *) arl->data) + (index + 1) * list->item_size, |
325 ((char *) arl->data) + (index + 1) * list->collection.elem_size, |
307 list->item_size, |
326 list->collection.elem_size, |
308 list->size - index - 1, |
327 list->collection.size - index - 1, |
309 &arl->reallocator |
328 &arl->reallocator |
310 ); |
329 ); |
311 if (result == 0) { |
330 |
312 // decrease the size |
331 // cx_array_copy cannot fail, array cannot grow |
313 list->size--; |
332 assert(result == 0); |
314 } |
333 |
315 return result; |
334 // decrease the size |
|
335 list->collection.size--; |
|
336 |
|
337 return 0; |
316 } |
338 } |
317 |
339 |
318 static void cx_arl_clear(struct cx_list_s *list) { |
340 static void cx_arl_clear(struct cx_list_s *list) { |
319 if (list->size == 0) return; |
341 if (list->collection.size == 0) return; |
320 |
342 |
321 cx_array_list *arl = (cx_array_list *) list; |
343 cx_array_list *arl = (cx_array_list *) list; |
322 char *ptr = arl->data; |
344 char *ptr = arl->data; |
323 |
345 |
324 if (list->simple_destructor) { |
346 if (list->collection.simple_destructor) { |
325 for (size_t i = 0; i < list->size; i++) { |
347 for (size_t i = 0; i < list->collection.size; i++) { |
326 cx_invoke_simple_destructor(list, ptr); |
348 cx_invoke_simple_destructor(list, ptr); |
327 ptr += list->item_size; |
349 ptr += list->collection.elem_size; |
328 } |
350 } |
329 } |
351 } |
330 if (list->advanced_destructor) { |
352 if (list->collection.advanced_destructor) { |
331 for (size_t i = 0; i < list->size; i++) { |
353 for (size_t i = 0; i < list->collection.size; i++) { |
332 cx_invoke_advanced_destructor(list, ptr); |
354 cx_invoke_advanced_destructor(list, ptr); |
333 ptr += list->item_size; |
355 ptr += list->collection.elem_size; |
334 } |
356 } |
335 } |
357 } |
336 |
358 |
337 memset(arl->data, 0, list->size * list->item_size); |
359 memset(arl->data, 0, list->collection.size * list->collection.elem_size); |
338 list->size = 0; |
360 list->collection.size = 0; |
339 } |
361 } |
340 |
362 |
341 static int cx_arl_swap( |
363 static int cx_arl_swap( |
342 struct cx_list_s *list, |
364 struct cx_list_s *list, |
343 size_t i, |
365 size_t i, |
344 size_t j |
366 size_t j |
345 ) { |
367 ) { |
346 if (i >= list->size || j >= list->size) return 1; |
368 if (i >= list->collection.size || j >= list->collection.size) return 1; |
347 cx_array_list *arl = (cx_array_list *) list; |
369 cx_array_list *arl = (cx_array_list *) list; |
348 cx_array_swap(arl->data, list->item_size, i, j); |
370 cx_array_swap(arl->data, list->collection.elem_size, i, j); |
349 return 0; |
371 return 0; |
350 } |
372 } |
351 |
373 |
352 static void *cx_arl_at( |
374 static void *cx_arl_at( |
353 struct cx_list_s const *list, |
375 struct cx_list_s const *list, |
354 size_t index |
376 size_t index |
355 ) { |
377 ) { |
356 if (index < list->size) { |
378 if (index < list->collection.size) { |
357 cx_array_list const *arl = (cx_array_list const *) list; |
379 cx_array_list const *arl = (cx_array_list const *) list; |
358 char *space = arl->data; |
380 char *space = arl->data; |
359 return space + index * list->item_size; |
381 return space + index * list->collection.elem_size; |
360 } else { |
382 } else { |
361 return NULL; |
383 return NULL; |
362 } |
384 } |
363 } |
385 } |
364 |
386 |
365 static ssize_t cx_arl_find( |
387 static ssize_t cx_arl_find_remove( |
366 struct cx_list_s const *list, |
388 struct cx_list_s *list, |
367 void const *elem |
389 void const *elem, |
368 ) { |
390 bool remove |
369 assert(list->cmpfunc != NULL); |
391 ) { |
370 assert(list->size < SIZE_MAX / 2); |
392 assert(list->collection.cmpfunc != NULL); |
|
393 assert(list->collection.size < SIZE_MAX / 2); |
371 char *cur = ((cx_array_list const *) list)->data; |
394 char *cur = ((cx_array_list const *) list)->data; |
372 |
395 |
373 for (ssize_t i = 0; i < (ssize_t) list->size; i++) { |
396 for (ssize_t i = 0; i < (ssize_t) list->collection.size; i++) { |
374 if (0 == list->cmpfunc(elem, cur)) { |
397 if (0 == list->collection.cmpfunc(elem, cur)) { |
375 return i; |
398 if (remove) { |
376 } |
399 if (0 == cx_arl_remove(list, i)) { |
377 cur += list->item_size; |
400 return i; |
|
401 } else { |
|
402 return -1; |
|
403 } |
|
404 } else { |
|
405 return i; |
|
406 } |
|
407 } |
|
408 cur += list->collection.elem_size; |
378 } |
409 } |
379 |
410 |
380 return -1; |
411 return -1; |
381 } |
412 } |
382 |
413 |
383 static void cx_arl_sort(struct cx_list_s *list) { |
414 static void cx_arl_sort(struct cx_list_s *list) { |
384 assert(list->cmpfunc != NULL); |
415 assert(list->collection.cmpfunc != NULL); |
385 qsort(((cx_array_list *) list)->data, |
416 qsort(((cx_array_list *) list)->data, |
386 list->size, |
417 list->collection.size, |
387 list->item_size, |
418 list->collection.elem_size, |
388 list->cmpfunc |
419 list->collection.cmpfunc |
389 ); |
420 ); |
390 } |
421 } |
391 |
422 |
392 static int cx_arl_compare( |
423 static int cx_arl_compare( |
393 struct cx_list_s const *list, |
424 struct cx_list_s const *list, |
394 struct cx_list_s const *other |
425 struct cx_list_s const *other |
395 ) { |
426 ) { |
396 assert(list->cmpfunc != NULL); |
427 assert(list->collection.cmpfunc != NULL); |
397 if (list->size == other->size) { |
428 if (list->collection.size == other->collection.size) { |
398 char const *left = ((cx_array_list const *) list)->data; |
429 char const *left = ((cx_array_list const *) list)->data; |
399 char const *right = ((cx_array_list const *) other)->data; |
430 char const *right = ((cx_array_list const *) other)->data; |
400 for (size_t i = 0; i < list->size; i++) { |
431 for (size_t i = 0; i < list->collection.size; i++) { |
401 int d = list->cmpfunc(left, right); |
432 int d = list->collection.cmpfunc(left, right); |
402 if (d != 0) { |
433 if (d != 0) { |
403 return d; |
434 return d; |
404 } |
435 } |
405 left += list->item_size; |
436 left += list->collection.elem_size; |
406 right += other->item_size; |
437 right += other->collection.elem_size; |
407 } |
438 } |
408 return 0; |
439 return 0; |
409 } else { |
440 } else { |
410 return list->size < other->size ? -1 : 1; |
441 return list->collection.size < other->collection.size ? -1 : 1; |
411 } |
442 } |
412 } |
443 } |
413 |
444 |
414 static void cx_arl_reverse(struct cx_list_s *list) { |
445 static void cx_arl_reverse(struct cx_list_s *list) { |
415 if (list->size < 2) return; |
446 if (list->collection.size < 2) return; |
416 void *data = ((cx_array_list const *) list)->data; |
447 void *data = ((cx_array_list const *) list)->data; |
417 size_t half = list->size / 2; |
448 size_t half = list->collection.size / 2; |
418 for (size_t i = 0; i < half; i++) { |
449 for (size_t i = 0; i < half; i++) { |
419 cx_array_swap(data, list->item_size, i, list->size - 1 - i); |
450 cx_array_swap(data, list->collection.elem_size, i, list->collection.size - 1 - i); |
420 } |
451 } |
421 } |
452 } |
422 |
453 |
423 static bool cx_arl_iter_valid(void const *it) { |
454 static bool cx_arl_iter_valid(void const *it) { |
424 struct cx_iterator_s const *iter = it; |
455 struct cx_iterator_s const *iter = it; |
425 struct cx_list_s const *list = iter->src_handle; |
456 struct cx_list_s const *list = iter->src_handle.c; |
426 return iter->index < list->size; |
457 return iter->index < list->collection.size; |
427 } |
458 } |
428 |
459 |
429 static void *cx_arl_iter_current(void const *it) { |
460 static void *cx_arl_iter_current(void const *it) { |
430 struct cx_iterator_s const *iter = it; |
461 struct cx_iterator_s const *iter = it; |
431 return iter->elem_handle; |
462 return iter->elem_handle; |
432 } |
463 } |
433 |
464 |
434 static void cx_arl_iter_next(void *it) { |
465 static void cx_arl_iter_next(void *it) { |
435 struct cx_iterator_base_s *itbase = it; |
466 struct cx_iterator_s *iter = it; |
436 if (itbase->remove) { |
467 if (iter->base.remove) { |
437 struct cx_mut_iterator_s *iter = it; |
468 iter->base.remove = false; |
438 itbase->remove = false; |
469 cx_arl_remove(iter->src_handle.m, iter->index); |
439 cx_arl_remove(iter->src_handle, iter->index); |
470 } else { |
440 } else { |
|
441 struct cx_iterator_s *iter = it; |
|
442 iter->index++; |
471 iter->index++; |
443 iter->elem_handle = |
472 iter->elem_handle = |
444 ((char *) iter->elem_handle) |
473 ((char *) iter->elem_handle) |
445 + ((struct cx_list_s const *) iter->src_handle)->item_size; |
474 + ((struct cx_list_s const *) iter->src_handle.c)->collection.elem_size; |
446 } |
475 } |
447 } |
476 } |
448 |
477 |
449 static void cx_arl_iter_prev(void *it) { |
478 static void cx_arl_iter_prev(void *it) { |
450 struct cx_iterator_base_s *itbase = it; |
479 struct cx_iterator_s *iter = it; |
451 struct cx_mut_iterator_s *iter = it; |
480 cx_array_list const* list = iter->src_handle.c; |
452 cx_array_list *const list = iter->src_handle; |
481 if (iter->base.remove) { |
453 if (itbase->remove) { |
482 iter->base.remove = false; |
454 itbase->remove = false; |
483 cx_arl_remove(iter->src_handle.m, iter->index); |
455 cx_arl_remove(iter->src_handle, iter->index); |
|
456 } |
484 } |
457 iter->index--; |
485 iter->index--; |
458 if (iter->index < list->base.size) { |
486 if (iter->index < list->base.collection.size) { |
459 iter->elem_handle = ((char *) list->data) |
487 iter->elem_handle = ((char *) list->data) |
460 + iter->index * list->base.item_size; |
488 + iter->index * list->base.collection.elem_size; |
461 } |
489 } |
462 } |
490 } |
463 |
491 |
464 static bool cx_arl_iter_flag_rm(void *it) { |
|
465 struct cx_iterator_base_s *iter = it; |
|
466 if (iter->mutating) { |
|
467 iter->remove = true; |
|
468 return true; |
|
469 } else { |
|
470 return false; |
|
471 } |
|
472 } |
|
473 |
492 |
474 static struct cx_iterator_s cx_arl_iterator( |
493 static struct cx_iterator_s cx_arl_iterator( |
475 struct cx_list_s const *list, |
494 struct cx_list_s const *list, |
476 size_t index, |
495 size_t index, |
477 bool backwards |
496 bool backwards |
478 ) { |
497 ) { |
479 struct cx_iterator_s iter; |
498 struct cx_iterator_s iter; |
480 |
499 |
481 iter.index = index; |
500 iter.index = index; |
482 iter.src_handle = list; |
501 iter.src_handle.c = list; |
483 iter.elem_handle = cx_arl_at(list, index); |
502 iter.elem_handle = cx_arl_at(list, index); |
|
503 iter.elem_size = list->collection.elem_size; |
|
504 iter.elem_count = list->collection.size; |
484 iter.base.valid = cx_arl_iter_valid; |
505 iter.base.valid = cx_arl_iter_valid; |
485 iter.base.current = cx_arl_iter_current; |
506 iter.base.current = cx_arl_iter_current; |
486 iter.base.next = backwards ? cx_arl_iter_prev : cx_arl_iter_next; |
507 iter.base.next = backwards ? cx_arl_iter_prev : cx_arl_iter_next; |
487 iter.base.flag_removal = cx_arl_iter_flag_rm; |
|
488 iter.base.remove = false; |
508 iter.base.remove = false; |
489 iter.base.mutating = false; |
509 iter.base.mutating = false; |
490 |
510 |
491 return iter; |
511 return iter; |
492 } |
512 } |