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--; |
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) { |