src/array_list.c

changeset 890
54565fd74e74
parent 889
f549fd9fbd8f
child 919
75da57d4634e
equal deleted inserted replaced
889:f549fd9fbd8f 890:54565fd74e74
53 enum cx_array_result cx_array_copy( 53 enum cx_array_result cx_array_copy(
54 void **target, 54 void **target,
55 size_t *size, 55 size_t *size,
56 size_t *capacity, 56 size_t *capacity,
57 size_t index, 57 size_t index,
58 void const *src, 58 const void *src,
59 size_t elem_size, 59 size_t elem_size,
60 size_t elem_count, 60 size_t elem_count,
61 struct cx_array_reallocator_s *reallocator 61 struct cx_array_reallocator_s *reallocator
62 ) { 62 ) {
63 // assert pointers 63 // assert pointers
123 enum cx_array_result cx_array_insert_sorted( 123 enum cx_array_result cx_array_insert_sorted(
124 void **target, 124 void **target,
125 size_t *size, 125 size_t *size,
126 size_t *capacity, 126 size_t *capacity,
127 cx_compare_func cmp_func, 127 cx_compare_func cmp_func,
128 void const *sorted_data, 128 const void *sorted_data,
129 size_t elem_size, 129 size_t elem_size,
130 size_t elem_count, 130 size_t elem_count,
131 struct cx_array_reallocator_s *reallocator 131 struct cx_array_reallocator_s *reallocator
132 ) { 132 ) {
133 // assert pointers 133 // assert pointers
164 size_t new_size = old_size + elem_count; 164 size_t new_size = old_size + elem_count;
165 *size = new_size; 165 *size = new_size;
166 166
167 // declare the source and destination indices/pointers 167 // declare the source and destination indices/pointers
168 size_t si = 0, di = 0; 168 size_t si = 0, di = 0;
169 char const *src = sorted_data; 169 const char *src = sorted_data;
170 char *dest = *target; 170 char *dest = *target;
171 171
172 // find the first insertion point 172 // find the first insertion point
173 di = cx_array_binary_search_sup(dest, old_size, elem_size, src, cmp_func); 173 di = cx_array_binary_search_sup(dest, old_size, elem_size, src, cmp_func);
174 dest += di * elem_size; 174 dest += di * elem_size;
230 230
231 return CX_ARRAY_SUCCESS; 231 return CX_ARRAY_SUCCESS;
232 } 232 }
233 233
234 size_t cx_array_binary_search_inf( 234 size_t cx_array_binary_search_inf(
235 void const *arr, 235 const void *arr,
236 size_t size, 236 size_t size,
237 size_t elem_size, 237 size_t elem_size,
238 void const *elem, 238 const void *elem,
239 cx_compare_func cmp_func 239 cx_compare_func cmp_func
240 ) { 240 ) {
241 // special case: empty array 241 // special case: empty array
242 if (size == 0) return 0; 242 if (size == 0) return 0;
243 243
244 // declare a variable that will contain the compare results 244 // declare a variable that will contain the compare results
245 int result; 245 int result;
246 246
247 // cast the array pointer to something we can use offsets with 247 // cast the array pointer to something we can use offsets with
248 char const *array = arr; 248 const char *array = arr;
249 249
250 // check the first array element 250 // check the first array element
251 result = cmp_func(elem, array); 251 result = cmp_func(elem, array);
252 if (result < 0) { 252 if (result < 0) {
253 return size; 253 return size;
267 size_t right_index = size - 1; 267 size_t right_index = size - 1;
268 size_t pivot_index; 268 size_t pivot_index;
269 269
270 while (left_index <= right_index) { 270 while (left_index <= right_index) {
271 pivot_index = left_index + (right_index - left_index) / 2; 271 pivot_index = left_index + (right_index - left_index) / 2;
272 char const *arr_elem = array + pivot_index * elem_size; 272 const char *arr_elem = array + pivot_index * elem_size;
273 result = cmp_func(elem, arr_elem); 273 result = cmp_func(elem, arr_elem);
274 if (result == 0) { 274 if (result == 0) {
275 // found it! 275 // found it!
276 return pivot_index; 276 return pivot_index;
277 } else if (result < 0) { 277 } else if (result < 0) {
345 size_t capacity, 345 size_t capacity,
346 size_t elem_size, 346 size_t elem_size,
347 struct cx_array_reallocator_s *alloc 347 struct cx_array_reallocator_s *alloc
348 ) { 348 ) {
349 // retrieve the pointer to the list allocator 349 // retrieve the pointer to the list allocator
350 CxAllocator const *al = alloc->ptr1; 350 const CxAllocator *al = alloc->ptr1;
351 351
352 // use the list allocator to reallocate the memory 352 // use the list allocator to reallocate the memory
353 return cxRealloc(al, array, capacity * elem_size); 353 return cxRealloc(al, array, capacity * elem_size);
354 } 354 }
355 355
376 } 376 }
377 377
378 static size_t cx_arl_insert_array( 378 static size_t cx_arl_insert_array(
379 struct cx_list_s *list, 379 struct cx_list_s *list,
380 size_t index, 380 size_t index,
381 void const *array, 381 const void *array,
382 size_t n 382 size_t n
383 ) { 383 ) {
384 // out of bounds and special case check 384 // out of bounds and special case check
385 if (index > list->collection.size || n == 0) return 0; 385 if (index > list->collection.size || n == 0) return 0;
386 386
387 // get a correctly typed pointer to the list 387 // get a correctly typed pointer to the list
388 cx_array_list *arl = (cx_array_list *) list; 388 cx_array_list *arl = (cx_array_list *) list;
389 389
390 // do we need to move some elements? 390 // do we need to move some elements?
391 if (index < list->collection.size) { 391 if (index < list->collection.size) {
392 char const *first_to_move = (char const *) arl->data; 392 const char *first_to_move = (const char *) arl->data;
393 first_to_move += index * list->collection.elem_size; 393 first_to_move += index * list->collection.elem_size;
394 size_t elems_to_move = list->collection.size - index; 394 size_t elems_to_move = list->collection.size - index;
395 size_t start_of_moved = index + n; 395 size_t start_of_moved = index + n;
396 396
397 if (CX_ARRAY_SUCCESS != cx_array_copy( 397 if (CX_ARRAY_SUCCESS != cx_array_copy(
431 } 431 }
432 } 432 }
433 433
434 static size_t cx_arl_insert_sorted( 434 static size_t cx_arl_insert_sorted(
435 struct cx_list_s *list, 435 struct cx_list_s *list,
436 void const *sorted_data, 436 const void *sorted_data,
437 size_t n 437 size_t n
438 ) { 438 ) {
439 // get a correctly typed pointer to the list 439 // get a correctly typed pointer to the list
440 cx_array_list *arl = (cx_array_list *) list; 440 cx_array_list *arl = (cx_array_list *) list;
441 441
457 } 457 }
458 458
459 static int cx_arl_insert_element( 459 static int cx_arl_insert_element(
460 struct cx_list_s *list, 460 struct cx_list_s *list,
461 size_t index, 461 size_t index,
462 void const *element 462 const void *element
463 ) { 463 ) {
464 return 1 != cx_arl_insert_array(list, index, element, 1); 464 return 1 != cx_arl_insert_array(list, index, element, 1);
465 } 465 }
466 466
467 static int cx_arl_insert_iter( 467 static int cx_arl_insert_iter(
468 struct cx_iterator_s *iter, 468 struct cx_iterator_s *iter,
469 void const *elem, 469 const void *elem,
470 int prepend 470 int prepend
471 ) { 471 ) {
472 struct cx_list_s *list = iter->src_handle.m; 472 struct cx_list_s *list = iter->src_handle.m;
473 if (iter->index < list->collection.size) { 473 if (iter->index < list->collection.size) {
474 int result = cx_arl_insert_element( 474 int result = cx_arl_insert_element(
568 cx_array_swap(arl->data, list->collection.elem_size, i, j); 568 cx_array_swap(arl->data, list->collection.elem_size, i, j);
569 return 0; 569 return 0;
570 } 570 }
571 571
572 static void *cx_arl_at( 572 static void *cx_arl_at(
573 struct cx_list_s const *list, 573 const struct cx_list_s *list,
574 size_t index 574 size_t index
575 ) { 575 ) {
576 if (index < list->collection.size) { 576 if (index < list->collection.size) {
577 cx_array_list const *arl = (cx_array_list const *) list; 577 const cx_array_list *arl = (const cx_array_list *) list;
578 char *space = arl->data; 578 char *space = arl->data;
579 return space + index * list->collection.elem_size; 579 return space + index * list->collection.elem_size;
580 } else { 580 } else {
581 return NULL; 581 return NULL;
582 } 582 }
583 } 583 }
584 584
585 static ssize_t cx_arl_find_remove( 585 static ssize_t cx_arl_find_remove(
586 struct cx_list_s *list, 586 struct cx_list_s *list,
587 void const *elem, 587 const void *elem,
588 bool remove 588 bool remove
589 ) { 589 ) {
590 assert(list->collection.cmpfunc != NULL); 590 assert(list->collection.cmpfunc != NULL);
591 assert(list->collection.size < SIZE_MAX / 2); 591 assert(list->collection.size < SIZE_MAX / 2);
592 char *cur = ((cx_array_list const *) list)->data; 592 char *cur = ((const cx_array_list *) list)->data;
593 593
594 for (ssize_t i = 0; i < (ssize_t) list->collection.size; i++) { 594 for (ssize_t i = 0; i < (ssize_t) list->collection.size; i++) {
595 if (0 == list->collection.cmpfunc(elem, cur)) { 595 if (0 == list->collection.cmpfunc(elem, cur)) {
596 if (remove) { 596 if (remove) {
597 if (0 == cx_arl_remove(list, i)) { 597 if (0 == cx_arl_remove(list, i)) {
617 list->collection.cmpfunc 617 list->collection.cmpfunc
618 ); 618 );
619 } 619 }
620 620
621 static int cx_arl_compare( 621 static int cx_arl_compare(
622 struct cx_list_s const *list, 622 const struct cx_list_s *list,
623 struct cx_list_s const *other 623 const struct cx_list_s *other
624 ) { 624 ) {
625 assert(list->collection.cmpfunc != NULL); 625 assert(list->collection.cmpfunc != NULL);
626 if (list->collection.size == other->collection.size) { 626 if (list->collection.size == other->collection.size) {
627 char const *left = ((cx_array_list const *) list)->data; 627 const char *left = ((const cx_array_list *) list)->data;
628 char const *right = ((cx_array_list const *) other)->data; 628 const char *right = ((const cx_array_list *) other)->data;
629 for (size_t i = 0; i < list->collection.size; i++) { 629 for (size_t i = 0; i < list->collection.size; i++) {
630 int d = list->collection.cmpfunc(left, right); 630 int d = list->collection.cmpfunc(left, right);
631 if (d != 0) { 631 if (d != 0) {
632 return d; 632 return d;
633 } 633 }
640 } 640 }
641 } 641 }
642 642
643 static void cx_arl_reverse(struct cx_list_s *list) { 643 static void cx_arl_reverse(struct cx_list_s *list) {
644 if (list->collection.size < 2) return; 644 if (list->collection.size < 2) return;
645 void *data = ((cx_array_list const *) list)->data; 645 void *data = ((const cx_array_list *) list)->data;
646 size_t half = list->collection.size / 2; 646 size_t half = list->collection.size / 2;
647 for (size_t i = 0; i < half; i++) { 647 for (size_t i = 0; i < half; i++) {
648 cx_array_swap(data, list->collection.elem_size, i, list->collection.size - 1 - i); 648 cx_array_swap(data, list->collection.elem_size, i, list->collection.size - 1 - i);
649 } 649 }
650 } 650 }
651 651
652 static bool cx_arl_iter_valid(void const *it) { 652 static bool cx_arl_iter_valid(const void *it) {
653 struct cx_iterator_s const *iter = it; 653 const struct cx_iterator_s *iter = it;
654 struct cx_list_s const *list = iter->src_handle.c; 654 const struct cx_list_s *list = iter->src_handle.c;
655 return iter->index < list->collection.size; 655 return iter->index < list->collection.size;
656 } 656 }
657 657
658 static void *cx_arl_iter_current(void const *it) { 658 static void *cx_arl_iter_current(const void *it) {
659 struct cx_iterator_s const *iter = it; 659 const struct cx_iterator_s *iter = it;
660 return iter->elem_handle; 660 return iter->elem_handle;
661 } 661 }
662 662
663 static void cx_arl_iter_next(void *it) { 663 static void cx_arl_iter_next(void *it) {
664 struct cx_iterator_s *iter = it; 664 struct cx_iterator_s *iter = it;
667 cx_arl_remove(iter->src_handle.m, iter->index); 667 cx_arl_remove(iter->src_handle.m, iter->index);
668 } else { 668 } else {
669 iter->index++; 669 iter->index++;
670 iter->elem_handle = 670 iter->elem_handle =
671 ((char *) iter->elem_handle) 671 ((char *) iter->elem_handle)
672 + ((struct cx_list_s const *) iter->src_handle.c)->collection.elem_size; 672 + ((const struct cx_list_s *) iter->src_handle.c)->collection.elem_size;
673 } 673 }
674 } 674 }
675 675
676 static void cx_arl_iter_prev(void *it) { 676 static void cx_arl_iter_prev(void *it) {
677 struct cx_iterator_s *iter = it; 677 struct cx_iterator_s *iter = it;
678 cx_array_list const* list = iter->src_handle.c; 678 const cx_array_list *list = iter->src_handle.c;
679 if (iter->base.remove) { 679 if (iter->base.remove) {
680 iter->base.remove = false; 680 iter->base.remove = false;
681 cx_arl_remove(iter->src_handle.m, iter->index); 681 cx_arl_remove(iter->src_handle.m, iter->index);
682 } 682 }
683 iter->index--; 683 iter->index--;
687 } 687 }
688 } 688 }
689 689
690 690
691 static struct cx_iterator_s cx_arl_iterator( 691 static struct cx_iterator_s cx_arl_iterator(
692 struct cx_list_s const *list, 692 const struct cx_list_s *list,
693 size_t index, 693 size_t index,
694 bool backwards 694 bool backwards
695 ) { 695 ) {
696 struct cx_iterator_s iter; 696 struct cx_iterator_s iter;
697 697
725 cx_arl_reverse, 725 cx_arl_reverse,
726 cx_arl_iterator, 726 cx_arl_iterator,
727 }; 727 };
728 728
729 CxList *cxArrayListCreate( 729 CxList *cxArrayListCreate(
730 CxAllocator const *allocator, 730 const CxAllocator *allocator,
731 cx_compare_func comparator, 731 cx_compare_func comparator,
732 size_t elem_size, 732 size_t elem_size,
733 size_t initial_capacity 733 size_t initial_capacity
734 ) { 734 ) {
735 if (allocator == NULL) { 735 if (allocator == NULL) {

mercurial