ucx/array_list.c

branch
newapi
changeset 324
ce13a778654a
parent 253
087cc9216f28
equal deleted inserted replaced
323:38cb8e3992e8 324:ce13a778654a
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
116 memmove(start, src, elem_count * elem_size); 116 memmove(start, src, elem_count * elem_size);
117 *size = newsize; 117 *size = newsize;
118 118
119 // return successfully 119 // return successfully
120 return CX_ARRAY_SUCCESS; 120 return CX_ARRAY_SUCCESS;
121 }
122
123 enum cx_array_result cx_array_insert_sorted(
124 void **target,
125 size_t *size,
126 size_t *capacity,
127 cx_compare_func cmp_func,
128 const void *sorted_data,
129 size_t elem_size,
130 size_t elem_count,
131 struct cx_array_reallocator_s *reallocator
132 ) {
133 // assert pointers
134 assert(target != NULL);
135 assert(size != NULL);
136 assert(capacity != NULL);
137 assert(cmp_func != NULL);
138 assert(sorted_data != NULL);
139 assert(reallocator != NULL);
140
141 // corner case
142 if (elem_count == 0) return 0;
143
144 // store some counts
145 size_t old_size = *size;
146 size_t needed_capacity = old_size + elem_count;
147
148 // if we need more than we have, try a reallocation
149 if (needed_capacity > *capacity) {
150 size_t new_capacity = needed_capacity - (needed_capacity % 16) + 16;
151 void *new_mem = reallocator->realloc(
152 *target, new_capacity, elem_size, reallocator
153 );
154 if (new_mem == NULL) {
155 // give it up right away, there is no contract
156 // that requires us to insert as much as we can
157 return CX_ARRAY_REALLOC_FAILED;
158 }
159 *target = new_mem;
160 *capacity = new_capacity;
161 }
162
163 // now we have guaranteed that we can insert everything
164 size_t new_size = old_size + elem_count;
165 *size = new_size;
166
167 // declare the source and destination indices/pointers
168 size_t si = 0, di = 0;
169 const char *src = sorted_data;
170 char *dest = *target;
171
172 // find the first insertion point
173 di = cx_array_binary_search_sup(dest, old_size, elem_size, src, cmp_func);
174 dest += di * elem_size;
175
176 // move the remaining elements in the array completely to the right
177 // we will call it the "buffer" for parked elements
178 size_t buf_size = old_size - di;
179 size_t bi = new_size - buf_size;
180 char *bptr = ((char *) *target) + bi * elem_size;
181 memmove(bptr, dest, buf_size * elem_size);
182
183 // while there are both source and buffered elements left,
184 // copy them interleaving
185 while (si < elem_count && bi < new_size) {
186 // determine how many source elements can be inserted
187 size_t copy_len, bytes_copied;
188 copy_len = cx_array_binary_search_sup(
189 src,
190 elem_count - si,
191 elem_size,
192 bptr,
193 cmp_func
194 );
195
196 // copy the source elements
197 bytes_copied = copy_len * elem_size;
198 memcpy(dest, src, bytes_copied);
199 dest += bytes_copied;
200 src += bytes_copied;
201 si += copy_len;
202
203 // when all source elements are in place, we are done
204 if (si >= elem_count) break;
205
206 // determine how many buffered elements need to be restored
207 copy_len = cx_array_binary_search_sup(
208 bptr,
209 new_size - bi,
210 elem_size,
211 src,
212 cmp_func
213 );
214
215 // restore the buffered elements
216 bytes_copied = copy_len * elem_size;
217 memmove(dest, bptr, bytes_copied);
218 dest += bytes_copied;
219 bptr += bytes_copied;
220 bi += copy_len;
221 }
222
223 // still source elements left? simply append them
224 if (si < elem_count) {
225 memcpy(dest, src, elem_size * (elem_count - si));
226 }
227
228 // still buffer elements left?
229 // don't worry, we already moved them to the correct place
230
231 return CX_ARRAY_SUCCESS;
232 }
233
234 size_t cx_array_binary_search_inf(
235 const void *arr,
236 size_t size,
237 size_t elem_size,
238 const void *elem,
239 cx_compare_func cmp_func
240 ) {
241 // special case: empty array
242 if (size == 0) return 0;
243
244 // declare a variable that will contain the compare results
245 int result;
246
247 // cast the array pointer to something we can use offsets with
248 const char *array = arr;
249
250 // check the first array element
251 result = cmp_func(elem, array);
252 if (result < 0) {
253 return size;
254 } else if (result == 0) {
255 return 0;
256 }
257
258 // check the last array element
259 result = cmp_func(elem, array + elem_size * (size - 1));
260 if (result >= 0) {
261 return size - 1;
262 }
263
264 // the element is now guaranteed to be somewhere in the list
265 // so start the binary search
266 size_t left_index = 1;
267 size_t right_index = size - 1;
268 size_t pivot_index;
269
270 while (left_index <= right_index) {
271 pivot_index = left_index + (right_index - left_index) / 2;
272 const char *arr_elem = array + pivot_index * elem_size;
273 result = cmp_func(elem, arr_elem);
274 if (result == 0) {
275 // found it!
276 return pivot_index;
277 } else if (result < 0) {
278 // element is smaller than pivot, continue search left
279 right_index = pivot_index - 1;
280 } else {
281 // element is larger than pivot, continue search right
282 left_index = pivot_index + 1;
283 }
284 }
285
286 // report the largest upper bound
287 return result < 0 ? (pivot_index - 1) : pivot_index;
121 } 288 }
122 289
123 #ifndef CX_ARRAY_SWAP_SBO_SIZE 290 #ifndef CX_ARRAY_SWAP_SBO_SIZE
124 #define CX_ARRAY_SWAP_SBO_SIZE 128 291 #define CX_ARRAY_SWAP_SBO_SIZE 128
125 #endif 292 #endif
178 size_t capacity, 345 size_t capacity,
179 size_t elem_size, 346 size_t elem_size,
180 struct cx_array_reallocator_s *alloc 347 struct cx_array_reallocator_s *alloc
181 ) { 348 ) {
182 // retrieve the pointer to the list allocator 349 // retrieve the pointer to the list allocator
183 CxAllocator const *al = alloc->ptr1; 350 const CxAllocator *al = alloc->ptr1;
184 351
185 // use the list allocator to reallocate the memory 352 // use the list allocator to reallocate the memory
186 return cxRealloc(al, array, capacity * elem_size); 353 return cxRealloc(al, array, capacity * elem_size);
187 } 354 }
188 355
189 static void cx_arl_destructor(struct cx_list_s *list) { 356 static void cx_arl_destructor(struct cx_list_s *list) {
190 cx_array_list *arl = (cx_array_list *) list; 357 cx_array_list *arl = (cx_array_list *) list;
191 358
192 char *ptr = arl->data; 359 char *ptr = arl->data;
193 360
194 if (list->simple_destructor) { 361 if (list->collection.simple_destructor) {
195 for (size_t i = 0; i < list->size; i++) { 362 for (size_t i = 0; i < list->collection.size; i++) {
196 cx_invoke_simple_destructor(list, ptr); 363 cx_invoke_simple_destructor(list, ptr);
197 ptr += list->item_size; 364 ptr += list->collection.elem_size;
198 } 365 }
199 } 366 }
200 if (list->advanced_destructor) { 367 if (list->collection.advanced_destructor) {
201 for (size_t i = 0; i < list->size; i++) { 368 for (size_t i = 0; i < list->collection.size; i++) {
202 cx_invoke_advanced_destructor(list, ptr); 369 cx_invoke_advanced_destructor(list, ptr);
203 ptr += list->item_size; 370 ptr += list->collection.elem_size;
204 } 371 }
205 } 372 }
206 373
207 cxFree(list->allocator, arl->data); 374 cxFree(list->collection.allocator, arl->data);
208 cxFree(list->allocator, list); 375 cxFree(list->collection.allocator, list);
209 } 376 }
210 377
211 static size_t cx_arl_insert_array( 378 static size_t cx_arl_insert_array(
212 struct cx_list_s *list, 379 struct cx_list_s *list,
213 size_t index, 380 size_t index,
214 void const *array, 381 const void *array,
215 size_t n 382 size_t n
216 ) { 383 ) {
217 // out of bounds and special case check 384 // out of bounds and special case check
218 if (index > list->size || n == 0) return 0; 385 if (index > list->collection.size || n == 0) return 0;
219 386
220 // get a correctly typed pointer to the list 387 // get a correctly typed pointer to the list
221 cx_array_list *arl = (cx_array_list *) list; 388 cx_array_list *arl = (cx_array_list *) list;
222 389
223 // do we need to move some elements? 390 // do we need to move some elements?
224 if (index < list->size) { 391 if (index < list->collection.size) {
225 char const *first_to_move = (char const *) arl->data; 392 const char *first_to_move = (const char *) arl->data;
226 first_to_move += index * list->item_size; 393 first_to_move += index * list->collection.elem_size;
227 size_t elems_to_move = list->size - index; 394 size_t elems_to_move = list->collection.size - index;
228 size_t start_of_moved = index + n; 395 size_t start_of_moved = index + n;
229 396
230 if (CX_ARRAY_SUCCESS != cx_array_copy( 397 if (CX_ARRAY_SUCCESS != cx_array_copy(
231 &arl->data, 398 &arl->data,
232 &list->size, 399 &list->collection.size,
233 &arl->capacity, 400 &arl->capacity,
234 start_of_moved, 401 start_of_moved,
235 first_to_move, 402 first_to_move,
236 list->item_size, 403 list->collection.elem_size,
237 elems_to_move, 404 elems_to_move,
238 &arl->reallocator 405 &arl->reallocator
239 )) { 406 )) {
240 // if moving existing elems is unsuccessful, abort 407 // if moving existing elems is unsuccessful, abort
241 return 0; 408 return 0;
247 // therefore, it is impossible to leave this function with an invalid array 414 // therefore, it is impossible to leave this function with an invalid array
248 415
249 // place the new elements 416 // place the new elements
250 if (CX_ARRAY_SUCCESS == cx_array_copy( 417 if (CX_ARRAY_SUCCESS == cx_array_copy(
251 &arl->data, 418 &arl->data,
252 &list->size, 419 &list->collection.size,
253 &arl->capacity, 420 &arl->capacity,
254 index, 421 index,
255 array, 422 array,
256 list->item_size, 423 list->collection.elem_size,
257 n, 424 n,
258 &arl->reallocator 425 &arl->reallocator
259 )) { 426 )) {
260 return n; 427 return n;
261 } else { 428 } else {
262 // array list implementation is "all or nothing" 429 // array list implementation is "all or nothing"
263 return 0; 430 return 0;
264 } 431 }
265 } 432 }
266 433
434 static size_t cx_arl_insert_sorted(
435 struct cx_list_s *list,
436 const void *sorted_data,
437 size_t n
438 ) {
439 // get a correctly typed pointer to the list
440 cx_array_list *arl = (cx_array_list *) list;
441
442 if (CX_ARRAY_SUCCESS == cx_array_insert_sorted(
443 &arl->data,
444 &list->collection.size,
445 &arl->capacity,
446 list->collection.cmpfunc,
447 sorted_data,
448 list->collection.elem_size,
449 n,
450 &arl->reallocator
451 )) {
452 return n;
453 } else {
454 // array list implementation is "all or nothing"
455 return 0;
456 }
457 }
458
267 static int cx_arl_insert_element( 459 static int cx_arl_insert_element(
268 struct cx_list_s *list, 460 struct cx_list_s *list,
269 size_t index, 461 size_t index,
270 void const *element 462 const void *element
271 ) { 463 ) {
272 return 1 != cx_arl_insert_array(list, index, element, 1); 464 return 1 != cx_arl_insert_array(list, index, element, 1);
273 } 465 }
274 466
275 static int cx_arl_insert_iter( 467 static int cx_arl_insert_iter(
276 struct cx_mut_iterator_s *iter, 468 struct cx_iterator_s *iter,
277 void const *elem, 469 const void *elem,
278 int prepend 470 int prepend
279 ) { 471 ) {
280 struct cx_list_s *list = iter->src_handle; 472 struct cx_list_s *list = iter->src_handle.m;
281 if (iter->index < list->size) { 473 if (iter->index < list->collection.size) {
282 int result = cx_arl_insert_element( 474 int result = cx_arl_insert_element(
283 list, 475 list,
284 iter->index + 1 - prepend, 476 iter->index + 1 - prepend,
285 elem 477 elem
286 ); 478 );
287 if (result == 0 && prepend != 0) { 479 if (result == 0) {
288 iter->index++; 480 iter->elem_count++;
289 iter->elem_handle = ((char *) iter->elem_handle) + list->item_size; 481 if (prepend != 0) {
482 iter->index++;
483 iter->elem_handle = ((char *) iter->elem_handle) + list->collection.elem_size;
484 }
290 } 485 }
291 return result; 486 return result;
292 } else { 487 } else {
293 int result = cx_arl_insert_element(list, list->size, elem); 488 int result = cx_arl_insert_element(list, list->collection.size, elem);
294 iter->index = list->size; 489 if (result == 0) {
490 iter->elem_count++;
491 iter->index = list->collection.size;
492 }
295 return result; 493 return result;
296 } 494 }
297 } 495 }
298 496
299 static int cx_arl_remove( 497 static int cx_arl_remove(
301 size_t index 499 size_t index
302 ) { 500 ) {
303 cx_array_list *arl = (cx_array_list *) list; 501 cx_array_list *arl = (cx_array_list *) list;
304 502
305 // out-of-bounds check 503 // out-of-bounds check
306 if (index >= list->size) { 504 if (index >= list->collection.size) {
307 return 1; 505 return 1;
308 } 506 }
309 507
310 // content destruction 508 // content destruction
311 cx_invoke_destructor(list, ((char *) arl->data) + index * list->item_size); 509 cx_invoke_destructor(list, ((char *) arl->data) + index * list->collection.elem_size);
312 510
313 // short-circuit removal of last element 511 // short-circuit removal of last element
314 if (index == list->size - 1) { 512 if (index == list->collection.size - 1) {
315 list->size--; 513 list->collection.size--;
316 return 0; 514 return 0;
317 } 515 }
318 516
319 // just move the elements starting at index to the left 517 // just move the elements starting at index to the left
320 int result = cx_array_copy( 518 int result = cx_array_copy(
321 &arl->data, 519 &arl->data,
322 &list->size, 520 &list->collection.size,
323 &arl->capacity, 521 &arl->capacity,
324 index, 522 index,
325 ((char *) arl->data) + (index + 1) * list->item_size, 523 ((char *) arl->data) + (index + 1) * list->collection.elem_size,
326 list->item_size, 524 list->collection.elem_size,
327 list->size - index - 1, 525 list->collection.size - index - 1,
328 &arl->reallocator 526 &arl->reallocator
329 ); 527 );
330 528
331 // cx_array_copy cannot fail, array cannot grow 529 // cx_array_copy cannot fail, array cannot grow
332 assert(result == 0); 530 assert(result == 0);
333 531
334 // decrease the size 532 // decrease the size
335 list->size--; 533 list->collection.size--;
336 534
337 return 0; 535 return 0;
338 } 536 }
339 537
340 static void cx_arl_clear(struct cx_list_s *list) { 538 static void cx_arl_clear(struct cx_list_s *list) {
341 if (list->size == 0) return; 539 if (list->collection.size == 0) return;
342 540
343 cx_array_list *arl = (cx_array_list *) list; 541 cx_array_list *arl = (cx_array_list *) list;
344 char *ptr = arl->data; 542 char *ptr = arl->data;
345 543
346 if (list->simple_destructor) { 544 if (list->collection.simple_destructor) {
347 for (size_t i = 0; i < list->size; i++) { 545 for (size_t i = 0; i < list->collection.size; i++) {
348 cx_invoke_simple_destructor(list, ptr); 546 cx_invoke_simple_destructor(list, ptr);
349 ptr += list->item_size; 547 ptr += list->collection.elem_size;
350 } 548 }
351 } 549 }
352 if (list->advanced_destructor) { 550 if (list->collection.advanced_destructor) {
353 for (size_t i = 0; i < list->size; i++) { 551 for (size_t i = 0; i < list->collection.size; i++) {
354 cx_invoke_advanced_destructor(list, ptr); 552 cx_invoke_advanced_destructor(list, ptr);
355 ptr += list->item_size; 553 ptr += list->collection.elem_size;
356 } 554 }
357 } 555 }
358 556
359 memset(arl->data, 0, list->size * list->item_size); 557 memset(arl->data, 0, list->collection.size * list->collection.elem_size);
360 list->size = 0; 558 list->collection.size = 0;
361 } 559 }
362 560
363 static int cx_arl_swap( 561 static int cx_arl_swap(
364 struct cx_list_s *list, 562 struct cx_list_s *list,
365 size_t i, 563 size_t i,
366 size_t j 564 size_t j
367 ) { 565 ) {
368 if (i >= list->size || j >= list->size) return 1; 566 if (i >= list->collection.size || j >= list->collection.size) return 1;
369 cx_array_list *arl = (cx_array_list *) list; 567 cx_array_list *arl = (cx_array_list *) list;
370 cx_array_swap(arl->data, list->item_size, i, j); 568 cx_array_swap(arl->data, list->collection.elem_size, i, j);
371 return 0; 569 return 0;
372 } 570 }
373 571
374 static void *cx_arl_at( 572 static void *cx_arl_at(
375 struct cx_list_s const *list, 573 const struct cx_list_s *list,
376 size_t index 574 size_t index
377 ) { 575 ) {
378 if (index < list->size) { 576 if (index < list->collection.size) {
379 cx_array_list const *arl = (cx_array_list const *) list; 577 const cx_array_list *arl = (const cx_array_list *) list;
380 char *space = arl->data; 578 char *space = arl->data;
381 return space + index * list->item_size; 579 return space + index * list->collection.elem_size;
382 } else { 580 } else {
383 return NULL; 581 return NULL;
384 } 582 }
385 } 583 }
386 584
387 static ssize_t cx_arl_find_remove( 585 static ssize_t cx_arl_find_remove(
388 struct cx_list_s *list, 586 struct cx_list_s *list,
389 void const *elem, 587 const void *elem,
390 bool remove 588 bool remove
391 ) { 589 ) {
392 assert(list->cmpfunc != NULL); 590 assert(list->collection.cmpfunc != NULL);
393 assert(list->size < SIZE_MAX / 2); 591 assert(list->collection.size < SIZE_MAX / 2);
394 char *cur = ((cx_array_list const *) list)->data; 592 char *cur = ((const cx_array_list *) list)->data;
395 593
396 for (ssize_t i = 0; i < (ssize_t) list->size; i++) { 594 for (ssize_t i = 0; i < (ssize_t) list->collection.size; i++) {
397 if (0 == list->cmpfunc(elem, cur)) { 595 if (0 == list->collection.cmpfunc(elem, cur)) {
398 if (remove) { 596 if (remove) {
399 if (0 == cx_arl_remove(list, i)) { 597 if (0 == cx_arl_remove(list, i)) {
400 return i; 598 return i;
401 } else { 599 } else {
402 return -1; 600 return -1;
403 } 601 }
404 } else { 602 } else {
405 return i; 603 return i;
406 } 604 }
407 } 605 }
408 cur += list->item_size; 606 cur += list->collection.elem_size;
409 } 607 }
410 608
411 return -1; 609 return -1;
412 } 610 }
413 611
414 static void cx_arl_sort(struct cx_list_s *list) { 612 static void cx_arl_sort(struct cx_list_s *list) {
415 assert(list->cmpfunc != NULL); 613 assert(list->collection.cmpfunc != NULL);
416 qsort(((cx_array_list *) list)->data, 614 qsort(((cx_array_list *) list)->data,
417 list->size, 615 list->collection.size,
418 list->item_size, 616 list->collection.elem_size,
419 list->cmpfunc 617 list->collection.cmpfunc
420 ); 618 );
421 } 619 }
422 620
423 static int cx_arl_compare( 621 static int cx_arl_compare(
424 struct cx_list_s const *list, 622 const struct cx_list_s *list,
425 struct cx_list_s const *other 623 const struct cx_list_s *other
426 ) { 624 ) {
427 assert(list->cmpfunc != NULL); 625 assert(list->collection.cmpfunc != NULL);
428 if (list->size == other->size) { 626 if (list->collection.size == other->collection.size) {
429 char const *left = ((cx_array_list const *) list)->data; 627 const char *left = ((const cx_array_list *) list)->data;
430 char const *right = ((cx_array_list const *) other)->data; 628 const char *right = ((const cx_array_list *) other)->data;
431 for (size_t i = 0; i < list->size; i++) { 629 for (size_t i = 0; i < list->collection.size; i++) {
432 int d = list->cmpfunc(left, right); 630 int d = list->collection.cmpfunc(left, right);
433 if (d != 0) { 631 if (d != 0) {
434 return d; 632 return d;
435 } 633 }
436 left += list->item_size; 634 left += list->collection.elem_size;
437 right += other->item_size; 635 right += other->collection.elem_size;
438 } 636 }
439 return 0; 637 return 0;
440 } else { 638 } else {
441 return list->size < other->size ? -1 : 1; 639 return list->collection.size < other->collection.size ? -1 : 1;
442 } 640 }
443 } 641 }
444 642
445 static void cx_arl_reverse(struct cx_list_s *list) { 643 static void cx_arl_reverse(struct cx_list_s *list) {
446 if (list->size < 2) return; 644 if (list->collection.size < 2) return;
447 void *data = ((cx_array_list const *) list)->data; 645 void *data = ((const cx_array_list *) list)->data;
448 size_t half = list->size / 2; 646 size_t half = list->collection.size / 2;
449 for (size_t i = 0; i < half; i++) { 647 for (size_t i = 0; i < half; i++) {
450 cx_array_swap(data, list->item_size, i, list->size - 1 - i); 648 cx_array_swap(data, list->collection.elem_size, i, list->collection.size - 1 - i);
451 } 649 }
452 } 650 }
453 651
454 static bool cx_arl_iter_valid(void const *it) { 652 static bool cx_arl_iter_valid(const void *it) {
455 struct cx_iterator_s const *iter = it; 653 const struct cx_iterator_s *iter = it;
456 struct cx_list_s const *list = iter->src_handle; 654 const struct cx_list_s *list = iter->src_handle.c;
457 return iter->index < list->size; 655 return iter->index < list->collection.size;
458 } 656 }
459 657
460 static void *cx_arl_iter_current(void const *it) { 658 static void *cx_arl_iter_current(const void *it) {
461 struct cx_iterator_s const *iter = it; 659 const struct cx_iterator_s *iter = it;
462 return iter->elem_handle; 660 return iter->elem_handle;
463 } 661 }
464 662
465 static void cx_arl_iter_next(void *it) { 663 static void cx_arl_iter_next(void *it) {
466 struct cx_iterator_base_s *itbase = it; 664 struct cx_iterator_s *iter = it;
467 if (itbase->remove) { 665 if (iter->base.remove) {
468 struct cx_mut_iterator_s *iter = it; 666 iter->base.remove = false;
469 itbase->remove = false; 667 cx_arl_remove(iter->src_handle.m, iter->index);
470 cx_arl_remove(iter->src_handle, iter->index);
471 } else { 668 } else {
472 struct cx_iterator_s *iter = it;
473 iter->index++; 669 iter->index++;
474 iter->elem_handle = 670 iter->elem_handle =
475 ((char *) iter->elem_handle) 671 ((char *) iter->elem_handle)
476 + ((struct cx_list_s const *) iter->src_handle)->item_size; 672 + ((const struct cx_list_s *) iter->src_handle.c)->collection.elem_size;
477 } 673 }
478 } 674 }
479 675
480 static void cx_arl_iter_prev(void *it) { 676 static void cx_arl_iter_prev(void *it) {
481 struct cx_iterator_base_s *itbase = it; 677 struct cx_iterator_s *iter = it;
482 struct cx_mut_iterator_s *iter = it; 678 const cx_array_list *list = iter->src_handle.c;
483 cx_array_list *const list = iter->src_handle; 679 if (iter->base.remove) {
484 if (itbase->remove) { 680 iter->base.remove = false;
485 itbase->remove = false; 681 cx_arl_remove(iter->src_handle.m, iter->index);
486 cx_arl_remove(iter->src_handle, iter->index);
487 } 682 }
488 iter->index--; 683 iter->index--;
489 if (iter->index < list->base.size) { 684 if (iter->index < list->base.collection.size) {
490 iter->elem_handle = ((char *) list->data) 685 iter->elem_handle = ((char *) list->data)
491 + iter->index * list->base.item_size; 686 + iter->index * list->base.collection.elem_size;
492 } 687 }
493 } 688 }
494 689
495 static bool cx_arl_iter_flag_rm(void *it) {
496 struct cx_iterator_base_s *iter = it;
497 if (iter->mutating) {
498 iter->remove = true;
499 return true;
500 } else {
501 return false;
502 }
503 }
504 690
505 static struct cx_iterator_s cx_arl_iterator( 691 static struct cx_iterator_s cx_arl_iterator(
506 struct cx_list_s const *list, 692 const struct cx_list_s *list,
507 size_t index, 693 size_t index,
508 bool backwards 694 bool backwards
509 ) { 695 ) {
510 struct cx_iterator_s iter; 696 struct cx_iterator_s iter;
511 697
512 iter.index = index; 698 iter.index = index;
513 iter.src_handle = list; 699 iter.src_handle.c = list;
514 iter.elem_handle = cx_arl_at(list, index); 700 iter.elem_handle = cx_arl_at(list, index);
701 iter.elem_size = list->collection.elem_size;
702 iter.elem_count = list->collection.size;
515 iter.base.valid = cx_arl_iter_valid; 703 iter.base.valid = cx_arl_iter_valid;
516 iter.base.current = cx_arl_iter_current; 704 iter.base.current = cx_arl_iter_current;
517 iter.base.next = backwards ? cx_arl_iter_prev : cx_arl_iter_next; 705 iter.base.next = backwards ? cx_arl_iter_prev : cx_arl_iter_next;
518 iter.base.flag_removal = cx_arl_iter_flag_rm;
519 iter.base.remove = false; 706 iter.base.remove = false;
520 iter.base.mutating = false; 707 iter.base.mutating = false;
521 708
522 return iter; 709 return iter;
523 } 710 }
524 711
525 static cx_list_class cx_array_list_class = { 712 static cx_list_class cx_array_list_class = {
526 cx_arl_destructor, 713 cx_arl_destructor,
527 cx_arl_insert_element, 714 cx_arl_insert_element,
528 cx_arl_insert_array, 715 cx_arl_insert_array,
716 cx_arl_insert_sorted,
529 cx_arl_insert_iter, 717 cx_arl_insert_iter,
530 cx_arl_remove, 718 cx_arl_remove,
531 cx_arl_clear, 719 cx_arl_clear,
532 cx_arl_swap, 720 cx_arl_swap,
533 cx_arl_at, 721 cx_arl_at,
537 cx_arl_reverse, 725 cx_arl_reverse,
538 cx_arl_iterator, 726 cx_arl_iterator,
539 }; 727 };
540 728
541 CxList *cxArrayListCreate( 729 CxList *cxArrayListCreate(
542 CxAllocator const *allocator, 730 const CxAllocator *allocator,
543 cx_compare_func comparator, 731 cx_compare_func comparator,
544 size_t item_size, 732 size_t elem_size,
545 size_t initial_capacity 733 size_t initial_capacity
546 ) { 734 ) {
547 if (allocator == NULL) { 735 if (allocator == NULL) {
548 allocator = cxDefaultAllocator; 736 allocator = cxDefaultAllocator;
549 } 737 }
550 738
551 cx_array_list *list = cxCalloc(allocator, 1, sizeof(cx_array_list)); 739 cx_array_list *list = cxCalloc(allocator, 1, sizeof(cx_array_list));
552 if (list == NULL) return NULL; 740 if (list == NULL) return NULL;
553 741
554 list->base.cl = &cx_array_list_class; 742 list->base.cl = &cx_array_list_class;
555 list->base.allocator = allocator; 743 list->base.collection.allocator = allocator;
556 list->capacity = initial_capacity; 744 list->capacity = initial_capacity;
557 745
558 if (item_size > 0) { 746 if (elem_size > 0) {
559 list->base.item_size = item_size; 747 list->base.collection.elem_size = elem_size;
560 list->base.cmpfunc = comparator; 748 list->base.collection.cmpfunc = comparator;
561 } else { 749 } else {
562 item_size = sizeof(void *); 750 elem_size = sizeof(void *);
563 list->base.cmpfunc = comparator == NULL ? cx_cmp_ptr : comparator; 751 list->base.collection.cmpfunc = comparator == NULL ? cx_cmp_ptr : comparator;
564 cxListStorePointers((CxList *) list); 752 cxListStorePointers((CxList *) list);
565 } 753 }
566 754
567 // allocate the array after the real item_size is known 755 // allocate the array after the real elem_size is known
568 list->data = cxCalloc(allocator, initial_capacity, item_size); 756 list->data = cxCalloc(allocator, initial_capacity, elem_size);
569 if (list->data == NULL) { 757 if (list->data == NULL) {
570 cxFree(allocator, list); 758 cxFree(allocator, list);
571 return NULL; 759 return NULL;
572 } 760 }
573 761

mercurial