src/array_list.c

changeset 919
75da57d4634e
parent 890
54565fd74e74
equal deleted inserted replaced
918:ec1f2015ec79 919:75da57d4634e
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;

mercurial