492 } |
492 } |
493 return result; |
493 return result; |
494 } |
494 } |
495 } |
495 } |
496 |
496 |
497 static int cx_arl_remove( |
497 static size_t cx_arl_remove( |
498 struct cx_list_s *list, |
498 struct cx_list_s *list, |
499 size_t index |
499 size_t index, |
|
500 size_t num, |
|
501 void *targetbuf |
500 ) { |
502 ) { |
501 cx_array_list *arl = (cx_array_list *) list; |
503 cx_array_list *arl = (cx_array_list *) list; |
502 |
504 |
503 // out-of-bounds check |
505 // out-of-bounds check |
|
506 size_t remove; |
504 if (index >= list->collection.size) { |
507 if (index >= list->collection.size) { |
505 return 1; |
508 remove = 0; |
506 } |
509 } else if (index + num > list->collection.size) { |
507 |
510 remove = list->collection.size - index; |
508 // content destruction |
511 } else { |
509 cx_invoke_destructor(list, ((char *) arl->data) + index * list->collection.elem_size); |
512 remove = num; |
510 |
513 } |
511 // short-circuit removal of last element |
514 |
512 if (index == list->collection.size - 1) { |
515 // easy exit |
513 list->collection.size--; |
516 if (remove == 0) return 0; |
514 return 0; |
517 |
515 } |
518 // destroy or copy contents |
516 |
519 if (targetbuf == NULL) { |
517 // just move the elements starting at index to the left |
520 for (size_t idx = index; idx < index + remove; idx++) { |
|
521 cx_invoke_destructor( |
|
522 list, |
|
523 ((char *) arl->data) + idx * list->collection.elem_size |
|
524 ); |
|
525 } |
|
526 } else { |
|
527 memcpy( |
|
528 targetbuf, |
|
529 ((char *) arl->data) + index * list->collection.elem_size, |
|
530 remove * list->collection.elem_size |
|
531 ); |
|
532 } |
|
533 |
|
534 // short-circuit removal of last elements |
|
535 if (index + remove == list->collection.size) { |
|
536 list->collection.size -= remove; |
|
537 return remove; |
|
538 } |
|
539 |
|
540 // just move the elements to the left |
518 int result = cx_array_copy( |
541 int result = cx_array_copy( |
519 &arl->data, |
542 &arl->data, |
520 &list->collection.size, |
543 &list->collection.size, |
521 &arl->capacity, |
544 &arl->capacity, |
522 index, |
545 index, |
523 ((char *) arl->data) + (index + 1) * list->collection.elem_size, |
546 ((char *) arl->data) + (index + remove) * list->collection.elem_size, |
524 list->collection.elem_size, |
547 list->collection.elem_size, |
525 list->collection.size - index - 1, |
548 list->collection.size - index - remove, |
526 &arl->reallocator |
549 &arl->reallocator |
527 ); |
550 ); |
528 |
551 |
529 // cx_array_copy cannot fail, array cannot grow |
552 // cx_array_copy cannot fail, array cannot grow |
530 assert(result == 0); |
553 assert(result == 0); |
531 |
554 |
532 // decrease the size |
555 // decrease the size |
533 list->collection.size--; |
556 list->collection.size -= remove; |
534 |
557 |
535 return 0; |
558 return remove; |
536 } |
559 } |
537 |
560 |
538 static void cx_arl_clear(struct cx_list_s *list) { |
561 static void cx_arl_clear(struct cx_list_s *list) { |
539 if (list->collection.size == 0) return; |
562 if (list->collection.size == 0) return; |
540 |
563 |
592 char *cur = ((const cx_array_list *) list)->data; |
615 char *cur = ((const cx_array_list *) list)->data; |
593 |
616 |
594 for (ssize_t i = 0; i < (ssize_t) list->collection.size; i++) { |
617 for (ssize_t i = 0; i < (ssize_t) list->collection.size; i++) { |
595 if (0 == list->collection.cmpfunc(elem, cur)) { |
618 if (0 == list->collection.cmpfunc(elem, cur)) { |
596 if (remove) { |
619 if (remove) { |
597 if (0 == cx_arl_remove(list, i)) { |
620 if (1 == cx_arl_remove(list, i, 1, NULL)) { |
598 return i; |
621 return i; |
599 } else { |
622 } else { |
600 return -1; |
623 return -1; |
601 } |
624 } |
602 } else { |
625 } else { |
662 |
685 |
663 static void cx_arl_iter_next(void *it) { |
686 static void cx_arl_iter_next(void *it) { |
664 struct cx_iterator_s *iter = it; |
687 struct cx_iterator_s *iter = it; |
665 if (iter->base.remove) { |
688 if (iter->base.remove) { |
666 iter->base.remove = false; |
689 iter->base.remove = false; |
667 cx_arl_remove(iter->src_handle.m, iter->index); |
690 cx_arl_remove(iter->src_handle.m, iter->index, 1, NULL); |
668 } else { |
691 } else { |
669 iter->index++; |
692 iter->index++; |
670 iter->elem_handle = |
693 iter->elem_handle = |
671 ((char *) iter->elem_handle) |
694 ((char *) iter->elem_handle) |
672 + ((const struct cx_list_s *) iter->src_handle.c)->collection.elem_size; |
695 + ((const struct cx_list_s *) iter->src_handle.c)->collection.elem_size; |
676 static void cx_arl_iter_prev(void *it) { |
699 static void cx_arl_iter_prev(void *it) { |
677 struct cx_iterator_s *iter = it; |
700 struct cx_iterator_s *iter = it; |
678 const cx_array_list *list = iter->src_handle.c; |
701 const cx_array_list *list = iter->src_handle.c; |
679 if (iter->base.remove) { |
702 if (iter->base.remove) { |
680 iter->base.remove = false; |
703 iter->base.remove = false; |
681 cx_arl_remove(iter->src_handle.m, iter->index); |
704 cx_arl_remove(iter->src_handle.m, iter->index, 1, NULL); |
682 } |
705 } |
683 iter->index--; |
706 iter->index--; |
684 if (iter->index < list->base.collection.size) { |
707 if (iter->index < list->base.collection.size) { |
685 iter->elem_handle = ((char *) list->data) |
708 iter->elem_handle = ((char *) list->data) |
686 + iter->index * list->base.collection.elem_size; |
709 + iter->index * list->base.collection.elem_size; |