99 CxArrayReallocator *reallocator |
99 CxArrayReallocator *reallocator |
100 ) { |
100 ) { |
101 // assert pointers |
101 // assert pointers |
102 assert(target != NULL); |
102 assert(target != NULL); |
103 assert(size != NULL); |
103 assert(size != NULL); |
|
104 assert(capacity != NULL); |
104 assert(src != NULL); |
105 assert(src != NULL); |
|
106 assert(reallocator != NULL); |
105 |
107 |
106 // determine capacity |
108 // determine capacity |
107 size_t cap = capacity == NULL ? *size : *capacity; |
109 size_t cap = *capacity; |
108 assert(*target != NULL || cap == 0); |
110 assert(*target != NULL || cap == 0); |
109 |
111 |
110 // check if resize is required |
112 // check if resize is required |
111 size_t minsize = index + elem_count; |
113 size_t minsize = index + elem_count; |
112 size_t newsize = *size < minsize ? minsize : *size; |
114 size_t newsize = *size < minsize ? minsize : *size; |
113 bool needrealloc = newsize > cap; |
|
114 |
115 |
115 // reallocate if possible |
116 // reallocate if possible |
116 if (needrealloc) { |
117 if (newsize > cap) { |
117 // a reallocator and a capacity variable must be available |
|
118 if (reallocator == NULL || capacity == NULL) { |
|
119 return CX_ARRAY_REALLOC_NOT_SUPPORTED; |
|
120 } |
|
121 |
|
122 // check, if we need to repair the src pointer |
118 // check, if we need to repair the src pointer |
123 uintptr_t targetaddr = (uintptr_t) *target; |
119 uintptr_t targetaddr = (uintptr_t) *target; |
124 uintptr_t srcaddr = (uintptr_t) src; |
120 uintptr_t srcaddr = (uintptr_t) src; |
125 bool repairsrc = targetaddr <= srcaddr |
121 bool repairsrc = targetaddr <= srcaddr |
126 && srcaddr < targetaddr + cap * elem_size; |
122 && srcaddr < targetaddr + cap * elem_size; |
132 // perform reallocation |
128 // perform reallocation |
133 void *newmem = reallocator->realloc( |
129 void *newmem = reallocator->realloc( |
134 *target, cap, elem_size, reallocator |
130 *target, cap, elem_size, reallocator |
135 ); |
131 ); |
136 if (newmem == NULL) { |
132 if (newmem == NULL) { |
137 return CX_ARRAY_REALLOC_FAILED; |
133 return 1; |
138 } |
134 } |
139 |
135 |
140 // repair src pointer, if necessary |
136 // repair src pointer, if necessary |
141 if (repairsrc) { |
137 if (repairsrc) { |
142 src = ((char *) newmem) + (srcaddr - targetaddr); |
138 src = ((char *) newmem) + (srcaddr - targetaddr); |
154 // copy elements and set new size |
150 // copy elements and set new size |
155 memmove(start, src, elem_count * elem_size); |
151 memmove(start, src, elem_count * elem_size); |
156 *size = newsize; |
152 *size = newsize; |
157 |
153 |
158 // return successfully |
154 // return successfully |
159 return CX_ARRAY_SUCCESS; |
155 return 0; |
160 } |
156 } |
161 |
157 |
162 enum cx_array_result cx_array_insert_sorted( |
158 int cx_array_insert_sorted( |
163 void **target, |
159 void **target, |
164 size_t *size, |
160 size_t *size, |
165 size_t *capacity, |
161 size_t *capacity, |
166 cx_compare_func cmp_func, |
162 cx_compare_func cmp_func, |
167 const void *sorted_data, |
163 const void *sorted_data, |
191 *target, new_capacity, elem_size, reallocator |
187 *target, new_capacity, elem_size, reallocator |
192 ); |
188 ); |
193 if (new_mem == NULL) { |
189 if (new_mem == NULL) { |
194 // give it up right away, there is no contract |
190 // give it up right away, there is no contract |
195 // that requires us to insert as much as we can |
191 // that requires us to insert as much as we can |
196 return CX_ARRAY_REALLOC_FAILED; |
192 return 1; |
197 } |
193 } |
198 *target = new_mem; |
194 *target = new_mem; |
199 *capacity = new_capacity; |
195 *capacity = new_capacity; |
200 } |
196 } |
201 |
197 |
456 const char *first_to_move = (const char *) arl->data; |
452 const char *first_to_move = (const char *) arl->data; |
457 first_to_move += index * list->collection.elem_size; |
453 first_to_move += index * list->collection.elem_size; |
458 size_t elems_to_move = list->collection.size - index; |
454 size_t elems_to_move = list->collection.size - index; |
459 size_t start_of_moved = index + n; |
455 size_t start_of_moved = index + n; |
460 |
456 |
461 if (CX_ARRAY_SUCCESS != cx_array_copy( |
457 if (cx_array_copy( |
462 &arl->data, |
458 &arl->data, |
463 &list->collection.size, |
459 &list->collection.size, |
464 &arl->capacity, |
460 &arl->capacity, |
465 start_of_moved, |
461 start_of_moved, |
466 first_to_move, |
462 first_to_move, |
476 // note that if we had to move the elements, the following operation |
472 // note that if we had to move the elements, the following operation |
477 // is guaranteed to succeed, because we have the memory already allocated |
473 // is guaranteed to succeed, because we have the memory already allocated |
478 // therefore, it is impossible to leave this function with an invalid array |
474 // therefore, it is impossible to leave this function with an invalid array |
479 |
475 |
480 // place the new elements |
476 // place the new elements |
481 if (CX_ARRAY_SUCCESS == cx_array_copy( |
477 if (cx_array_copy( |
482 &arl->data, |
478 &arl->data, |
483 &list->collection.size, |
479 &list->collection.size, |
484 &arl->capacity, |
480 &arl->capacity, |
485 index, |
481 index, |
486 array, |
482 array, |
487 list->collection.elem_size, |
483 list->collection.elem_size, |
488 n, |
484 n, |
489 &arl->reallocator |
485 &arl->reallocator |
490 )) { |
486 )) { |
491 return n; |
|
492 } else { |
|
493 // array list implementation is "all or nothing" |
487 // array list implementation is "all or nothing" |
494 return 0; |
488 return 0; |
|
489 } else { |
|
490 return n; |
495 } |
491 } |
496 } |
492 } |
497 |
493 |
498 static size_t cx_arl_insert_sorted( |
494 static size_t cx_arl_insert_sorted( |
499 struct cx_list_s *list, |
495 struct cx_list_s *list, |
501 size_t n |
497 size_t n |
502 ) { |
498 ) { |
503 // get a correctly typed pointer to the list |
499 // get a correctly typed pointer to the list |
504 cx_array_list *arl = (cx_array_list *) list; |
500 cx_array_list *arl = (cx_array_list *) list; |
505 |
501 |
506 if (CX_ARRAY_SUCCESS == cx_array_insert_sorted( |
502 if (cx_array_insert_sorted( |
507 &arl->data, |
503 &arl->data, |
508 &list->collection.size, |
504 &list->collection.size, |
509 &arl->capacity, |
505 &arl->capacity, |
510 list->collection.cmpfunc, |
506 list->collection.cmpfunc, |
511 sorted_data, |
507 sorted_data, |
512 list->collection.elem_size, |
508 list->collection.elem_size, |
513 n, |
509 n, |
514 &arl->reallocator |
510 &arl->reallocator |
515 )) { |
511 )) { |
516 return n; |
|
517 } else { |
|
518 // array list implementation is "all or nothing" |
512 // array list implementation is "all or nothing" |
519 return 0; |
513 return 0; |
|
514 } else { |
|
515 return n; |
520 } |
516 } |
521 } |
517 } |
522 |
518 |
523 static int cx_arl_insert_element( |
519 static int cx_arl_insert_element( |
524 struct cx_list_s *list, |
520 struct cx_list_s *list, |