ucx/array_list.c

branch
ucx-3.1
changeset 816
839fefbdedc7
parent 776
96555c0ed875
equal deleted inserted replaced
815:1f40ca07ae1b 816:839fefbdedc7
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29 #include "cx/array_list.h" 29 #include "cx/array_list.h"
30 #include "cx/compare.h"
30 #include <assert.h> 31 #include <assert.h>
31 #include <string.h> 32 #include <string.h>
32 33
34 // Default array reallocator
35
36 static void *cx_array_default_realloc(
37 void *array,
38 size_t capacity,
39 size_t elem_size,
40 __attribute__((__unused__)) struct cx_array_reallocator_s *alloc
41 ) {
42 return realloc(array, capacity * elem_size);
43 }
44
45 struct cx_array_reallocator_s cx_array_default_reallocator_impl = {
46 cx_array_default_realloc, NULL, NULL, 0, 0
47 };
48
49 struct cx_array_reallocator_s *cx_array_default_reallocator = &cx_array_default_reallocator_impl;
50
33 // LOW LEVEL ARRAY LIST FUNCTIONS 51 // LOW LEVEL ARRAY LIST FUNCTIONS
34 52
35 enum cx_array_copy_result cx_array_copy( 53 enum cx_array_result cx_array_copy(
36 void **target, 54 void **target,
37 size_t *size, 55 size_t *size,
38 size_t *capacity, 56 size_t *capacity,
39 size_t index, 57 size_t index,
40 void const *src, 58 void const *src,
57 75
58 // reallocate if possible 76 // reallocate if possible
59 if (needrealloc) { 77 if (needrealloc) {
60 // a reallocator and a capacity variable must be available 78 // a reallocator and a capacity variable must be available
61 if (reallocator == NULL || capacity == NULL) { 79 if (reallocator == NULL || capacity == NULL) {
62 return CX_ARRAY_COPY_REALLOC_NOT_SUPPORTED; 80 return CX_ARRAY_REALLOC_NOT_SUPPORTED;
63 } 81 }
64 82
65 // check, if we need to repair the src pointer 83 // check, if we need to repair the src pointer
66 uintptr_t targetaddr = (uintptr_t) *target; 84 uintptr_t targetaddr = (uintptr_t) *target;
67 uintptr_t srcaddr = (uintptr_t) src; 85 uintptr_t srcaddr = (uintptr_t) src;
75 // perform reallocation 93 // perform reallocation
76 void *newmem = reallocator->realloc( 94 void *newmem = reallocator->realloc(
77 *target, cap, elem_size, reallocator 95 *target, cap, elem_size, reallocator
78 ); 96 );
79 if (newmem == NULL) { 97 if (newmem == NULL) {
80 return CX_ARRAY_COPY_REALLOC_FAILED; 98 return CX_ARRAY_REALLOC_FAILED;
81 } 99 }
82 100
83 // repair src pointer, if necessary 101 // repair src pointer, if necessary
84 if (repairsrc) { 102 if (repairsrc) {
85 src = ((char *) newmem) + (srcaddr - targetaddr); 103 src = ((char *) newmem) + (srcaddr - targetaddr);
97 // copy elements and set new size 115 // copy elements and set new size
98 memmove(start, src, elem_count * elem_size); 116 memmove(start, src, elem_count * elem_size);
99 *size = newsize; 117 *size = newsize;
100 118
101 // return successfully 119 // return successfully
102 return CX_ARRAY_COPY_SUCCESS; 120 return CX_ARRAY_SUCCESS;
103 } 121 }
104 122
105 #ifndef CX_ARRAY_SWAP_SBO_SIZE 123 #ifndef CX_ARRAY_SWAP_SBO_SIZE
106 #define CX_ARRAY_SWAP_SBO_SIZE 128 124 #define CX_ARRAY_SWAP_SBO_SIZE 128
107 #endif 125 #endif
126 unsigned cx_array_swap_sbo_size = CX_ARRAY_SWAP_SBO_SIZE;
108 127
109 void cx_array_swap( 128 void cx_array_swap(
110 void *arr, 129 void *arr,
111 size_t elem_size, 130 size_t elem_size,
112 size_t idx1, 131 size_t idx1,
170 static void cx_arl_destructor(struct cx_list_s *list) { 189 static void cx_arl_destructor(struct cx_list_s *list) {
171 cx_array_list *arl = (cx_array_list *) list; 190 cx_array_list *arl = (cx_array_list *) list;
172 191
173 char *ptr = arl->data; 192 char *ptr = arl->data;
174 193
175 if (list->simple_destructor) { 194 if (list->collection.simple_destructor) {
176 for (size_t i = 0; i < list->size; i++) { 195 for (size_t i = 0; i < list->collection.size; i++) {
177 cx_invoke_simple_destructor(list, ptr); 196 cx_invoke_simple_destructor(list, ptr);
178 ptr += list->item_size; 197 ptr += list->collection.elem_size;
179 } 198 }
180 } 199 }
181 if (list->advanced_destructor) { 200 if (list->collection.advanced_destructor) {
182 for (size_t i = 0; i < list->size; i++) { 201 for (size_t i = 0; i < list->collection.size; i++) {
183 cx_invoke_advanced_destructor(list, ptr); 202 cx_invoke_advanced_destructor(list, ptr);
184 ptr += list->item_size; 203 ptr += list->collection.elem_size;
185 } 204 }
186 } 205 }
187 206
188 cxFree(list->allocator, arl->data); 207 cxFree(list->collection.allocator, arl->data);
189 cxFree(list->allocator, list); 208 cxFree(list->collection.allocator, list);
190 } 209 }
191 210
192 static size_t cx_arl_insert_array( 211 static size_t cx_arl_insert_array(
193 struct cx_list_s *list, 212 struct cx_list_s *list,
194 size_t index, 213 size_t index,
195 void const *array, 214 void const *array,
196 size_t n 215 size_t n
197 ) { 216 ) {
198 // out of bounds and special case check 217 // out of bounds and special case check
199 if (index > list->size || n == 0) return 0; 218 if (index > list->collection.size || n == 0) return 0;
200 219
201 // get a correctly typed pointer to the list 220 // get a correctly typed pointer to the list
202 cx_array_list *arl = (cx_array_list *) list; 221 cx_array_list *arl = (cx_array_list *) list;
203 222
204 // do we need to move some elements? 223 // do we need to move some elements?
205 if (index < list->size) { 224 if (index < list->collection.size) {
206 char const *first_to_move = (char const *) arl->data; 225 char const *first_to_move = (char const *) arl->data;
207 first_to_move += index * list->item_size; 226 first_to_move += index * list->collection.elem_size;
208 size_t elems_to_move = list->size - index; 227 size_t elems_to_move = list->collection.size - index;
209 size_t start_of_moved = index + n; 228 size_t start_of_moved = index + n;
210 229
211 if (CX_ARRAY_COPY_SUCCESS != cx_array_copy( 230 if (CX_ARRAY_SUCCESS != cx_array_copy(
212 &arl->data, 231 &arl->data,
213 &list->size, 232 &list->collection.size,
214 &arl->capacity, 233 &arl->capacity,
215 start_of_moved, 234 start_of_moved,
216 first_to_move, 235 first_to_move,
217 list->item_size, 236 list->collection.elem_size,
218 elems_to_move, 237 elems_to_move,
219 &arl->reallocator 238 &arl->reallocator
220 )) { 239 )) {
221 // if moving existing elems is unsuccessful, abort 240 // if moving existing elems is unsuccessful, abort
222 return 0; 241 return 0;
226 // note that if we had to move the elements, the following operation 245 // note that if we had to move the elements, the following operation
227 // is guaranteed to succeed, because we have the memory already allocated 246 // is guaranteed to succeed, because we have the memory already allocated
228 // therefore, it is impossible to leave this function with an invalid array 247 // therefore, it is impossible to leave this function with an invalid array
229 248
230 // place the new elements 249 // place the new elements
231 if (CX_ARRAY_COPY_SUCCESS == cx_array_copy( 250 if (CX_ARRAY_SUCCESS == cx_array_copy(
232 &arl->data, 251 &arl->data,
233 &list->size, 252 &list->collection.size,
234 &arl->capacity, 253 &arl->capacity,
235 index, 254 index,
236 array, 255 array,
237 list->item_size, 256 list->collection.elem_size,
238 n, 257 n,
239 &arl->reallocator 258 &arl->reallocator
240 )) { 259 )) {
241 return n; 260 return n;
242 } else { 261 } else {
252 ) { 271 ) {
253 return 1 != cx_arl_insert_array(list, index, element, 1); 272 return 1 != cx_arl_insert_array(list, index, element, 1);
254 } 273 }
255 274
256 static int cx_arl_insert_iter( 275 static int cx_arl_insert_iter(
257 struct cx_mut_iterator_s *iter, 276 struct cx_iterator_s *iter,
258 void const *elem, 277 void const *elem,
259 int prepend 278 int prepend
260 ) { 279 ) {
261 struct cx_list_s *list = iter->src_handle; 280 struct cx_list_s *list = iter->src_handle.m;
262 if (iter->index < list->size) { 281 if (iter->index < list->collection.size) {
263 int result = cx_arl_insert_element( 282 int result = cx_arl_insert_element(
264 list, 283 list,
265 iter->index + 1 - prepend, 284 iter->index + 1 - prepend,
266 elem 285 elem
267 ); 286 );
268 if (result == 0 && prepend != 0) { 287 if (result == 0 && prepend != 0) {
269 iter->index++; 288 iter->index++;
270 iter->elem_handle = ((char *) iter->elem_handle) + list->item_size; 289 iter->elem_handle = ((char *) iter->elem_handle) + list->collection.elem_size;
271 } 290 }
272 return result; 291 return result;
273 } else { 292 } else {
274 int result = cx_arl_insert_element(list, list->size, elem); 293 int result = cx_arl_insert_element(list, list->collection.size, elem);
275 iter->index = list->size; 294 iter->index = list->collection.size;
276 return result; 295 return result;
277 } 296 }
278 } 297 }
279 298
280 static int cx_arl_remove( 299 static int cx_arl_remove(
282 size_t index 301 size_t index
283 ) { 302 ) {
284 cx_array_list *arl = (cx_array_list *) list; 303 cx_array_list *arl = (cx_array_list *) list;
285 304
286 // out-of-bounds check 305 // out-of-bounds check
287 if (index >= list->size) { 306 if (index >= list->collection.size) {
288 return 1; 307 return 1;
289 } 308 }
290 309
291 // content destruction 310 // content destruction
292 cx_invoke_destructor(list, ((char *) arl->data) + index * list->item_size); 311 cx_invoke_destructor(list, ((char *) arl->data) + index * list->collection.elem_size);
293 312
294 // short-circuit removal of last element 313 // short-circuit removal of last element
295 if (index == list->size - 1) { 314 if (index == list->collection.size - 1) {
296 list->size--; 315 list->collection.size--;
297 return 0; 316 return 0;
298 } 317 }
299 318
300 // just move the elements starting at index to the left 319 // just move the elements starting at index to the left
301 int result = cx_array_copy( 320 int result = cx_array_copy(
302 &arl->data, 321 &arl->data,
303 &list->size, 322 &list->collection.size,
304 &arl->capacity, 323 &arl->capacity,
305 index, 324 index,
306 ((char *) arl->data) + (index + 1) * list->item_size, 325 ((char *) arl->data) + (index + 1) * list->collection.elem_size,
307 list->item_size, 326 list->collection.elem_size,
308 list->size - index - 1, 327 list->collection.size - index - 1,
309 &arl->reallocator 328 &arl->reallocator
310 ); 329 );
311 if (result == 0) { 330
312 // decrease the size 331 // cx_array_copy cannot fail, array cannot grow
313 list->size--; 332 assert(result == 0);
314 } 333
315 return result; 334 // decrease the size
335 list->collection.size--;
336
337 return 0;
316 } 338 }
317 339
318 static void cx_arl_clear(struct cx_list_s *list) { 340 static void cx_arl_clear(struct cx_list_s *list) {
319 if (list->size == 0) return; 341 if (list->collection.size == 0) return;
320 342
321 cx_array_list *arl = (cx_array_list *) list; 343 cx_array_list *arl = (cx_array_list *) list;
322 char *ptr = arl->data; 344 char *ptr = arl->data;
323 345
324 if (list->simple_destructor) { 346 if (list->collection.simple_destructor) {
325 for (size_t i = 0; i < list->size; i++) { 347 for (size_t i = 0; i < list->collection.size; i++) {
326 cx_invoke_simple_destructor(list, ptr); 348 cx_invoke_simple_destructor(list, ptr);
327 ptr += list->item_size; 349 ptr += list->collection.elem_size;
328 } 350 }
329 } 351 }
330 if (list->advanced_destructor) { 352 if (list->collection.advanced_destructor) {
331 for (size_t i = 0; i < list->size; i++) { 353 for (size_t i = 0; i < list->collection.size; i++) {
332 cx_invoke_advanced_destructor(list, ptr); 354 cx_invoke_advanced_destructor(list, ptr);
333 ptr += list->item_size; 355 ptr += list->collection.elem_size;
334 } 356 }
335 } 357 }
336 358
337 memset(arl->data, 0, list->size * list->item_size); 359 memset(arl->data, 0, list->collection.size * list->collection.elem_size);
338 list->size = 0; 360 list->collection.size = 0;
339 } 361 }
340 362
341 static int cx_arl_swap( 363 static int cx_arl_swap(
342 struct cx_list_s *list, 364 struct cx_list_s *list,
343 size_t i, 365 size_t i,
344 size_t j 366 size_t j
345 ) { 367 ) {
346 if (i >= list->size || j >= list->size) return 1; 368 if (i >= list->collection.size || j >= list->collection.size) return 1;
347 cx_array_list *arl = (cx_array_list *) list; 369 cx_array_list *arl = (cx_array_list *) list;
348 cx_array_swap(arl->data, list->item_size, i, j); 370 cx_array_swap(arl->data, list->collection.elem_size, i, j);
349 return 0; 371 return 0;
350 } 372 }
351 373
352 static void *cx_arl_at( 374 static void *cx_arl_at(
353 struct cx_list_s const *list, 375 struct cx_list_s const *list,
354 size_t index 376 size_t index
355 ) { 377 ) {
356 if (index < list->size) { 378 if (index < list->collection.size) {
357 cx_array_list const *arl = (cx_array_list const *) list; 379 cx_array_list const *arl = (cx_array_list const *) list;
358 char *space = arl->data; 380 char *space = arl->data;
359 return space + index * list->item_size; 381 return space + index * list->collection.elem_size;
360 } else { 382 } else {
361 return NULL; 383 return NULL;
362 } 384 }
363 } 385 }
364 386
365 static ssize_t cx_arl_find( 387 static ssize_t cx_arl_find_remove(
366 struct cx_list_s const *list, 388 struct cx_list_s *list,
367 void const *elem 389 void const *elem,
368 ) { 390 bool remove
369 assert(list->cmpfunc != NULL); 391 ) {
370 assert(list->size < SIZE_MAX / 2); 392 assert(list->collection.cmpfunc != NULL);
393 assert(list->collection.size < SIZE_MAX / 2);
371 char *cur = ((cx_array_list const *) list)->data; 394 char *cur = ((cx_array_list const *) list)->data;
372 395
373 for (ssize_t i = 0; i < (ssize_t) list->size; i++) { 396 for (ssize_t i = 0; i < (ssize_t) list->collection.size; i++) {
374 if (0 == list->cmpfunc(elem, cur)) { 397 if (0 == list->collection.cmpfunc(elem, cur)) {
375 return i; 398 if (remove) {
376 } 399 if (0 == cx_arl_remove(list, i)) {
377 cur += list->item_size; 400 return i;
401 } else {
402 return -1;
403 }
404 } else {
405 return i;
406 }
407 }
408 cur += list->collection.elem_size;
378 } 409 }
379 410
380 return -1; 411 return -1;
381 } 412 }
382 413
383 static void cx_arl_sort(struct cx_list_s *list) { 414 static void cx_arl_sort(struct cx_list_s *list) {
384 assert(list->cmpfunc != NULL); 415 assert(list->collection.cmpfunc != NULL);
385 qsort(((cx_array_list *) list)->data, 416 qsort(((cx_array_list *) list)->data,
386 list->size, 417 list->collection.size,
387 list->item_size, 418 list->collection.elem_size,
388 list->cmpfunc 419 list->collection.cmpfunc
389 ); 420 );
390 } 421 }
391 422
392 static int cx_arl_compare( 423 static int cx_arl_compare(
393 struct cx_list_s const *list, 424 struct cx_list_s const *list,
394 struct cx_list_s const *other 425 struct cx_list_s const *other
395 ) { 426 ) {
396 assert(list->cmpfunc != NULL); 427 assert(list->collection.cmpfunc != NULL);
397 if (list->size == other->size) { 428 if (list->collection.size == other->collection.size) {
398 char const *left = ((cx_array_list const *) list)->data; 429 char const *left = ((cx_array_list const *) list)->data;
399 char const *right = ((cx_array_list const *) other)->data; 430 char const *right = ((cx_array_list const *) other)->data;
400 for (size_t i = 0; i < list->size; i++) { 431 for (size_t i = 0; i < list->collection.size; i++) {
401 int d = list->cmpfunc(left, right); 432 int d = list->collection.cmpfunc(left, right);
402 if (d != 0) { 433 if (d != 0) {
403 return d; 434 return d;
404 } 435 }
405 left += list->item_size; 436 left += list->collection.elem_size;
406 right += other->item_size; 437 right += other->collection.elem_size;
407 } 438 }
408 return 0; 439 return 0;
409 } else { 440 } else {
410 return list->size < other->size ? -1 : 1; 441 return list->collection.size < other->collection.size ? -1 : 1;
411 } 442 }
412 } 443 }
413 444
414 static void cx_arl_reverse(struct cx_list_s *list) { 445 static void cx_arl_reverse(struct cx_list_s *list) {
415 if (list->size < 2) return; 446 if (list->collection.size < 2) return;
416 void *data = ((cx_array_list const *) list)->data; 447 void *data = ((cx_array_list const *) list)->data;
417 size_t half = list->size / 2; 448 size_t half = list->collection.size / 2;
418 for (size_t i = 0; i < half; i++) { 449 for (size_t i = 0; i < half; i++) {
419 cx_array_swap(data, list->item_size, i, list->size - 1 - i); 450 cx_array_swap(data, list->collection.elem_size, i, list->collection.size - 1 - i);
420 } 451 }
421 } 452 }
422 453
423 static bool cx_arl_iter_valid(void const *it) { 454 static bool cx_arl_iter_valid(void const *it) {
424 struct cx_iterator_s const *iter = it; 455 struct cx_iterator_s const *iter = it;
425 struct cx_list_s const *list = iter->src_handle; 456 struct cx_list_s const *list = iter->src_handle.c;
426 return iter->index < list->size; 457 return iter->index < list->collection.size;
427 } 458 }
428 459
429 static void *cx_arl_iter_current(void const *it) { 460 static void *cx_arl_iter_current(void const *it) {
430 struct cx_iterator_s const *iter = it; 461 struct cx_iterator_s const *iter = it;
431 return iter->elem_handle; 462 return iter->elem_handle;
432 } 463 }
433 464
434 static void cx_arl_iter_next(void *it) { 465 static void cx_arl_iter_next(void *it) {
435 struct cx_iterator_base_s *itbase = it; 466 struct cx_iterator_s *iter = it;
436 if (itbase->remove) { 467 if (iter->base.remove) {
437 struct cx_mut_iterator_s *iter = it; 468 iter->base.remove = false;
438 itbase->remove = false; 469 cx_arl_remove(iter->src_handle.m, iter->index);
439 cx_arl_remove(iter->src_handle, iter->index); 470 } else {
440 } else {
441 struct cx_iterator_s *iter = it;
442 iter->index++; 471 iter->index++;
443 iter->elem_handle = 472 iter->elem_handle =
444 ((char *) iter->elem_handle) 473 ((char *) iter->elem_handle)
445 + ((struct cx_list_s const *) iter->src_handle)->item_size; 474 + ((struct cx_list_s const *) iter->src_handle.c)->collection.elem_size;
446 } 475 }
447 } 476 }
448 477
449 static void cx_arl_iter_prev(void *it) { 478 static void cx_arl_iter_prev(void *it) {
450 struct cx_iterator_base_s *itbase = it; 479 struct cx_iterator_s *iter = it;
451 struct cx_mut_iterator_s *iter = it; 480 cx_array_list const* list = iter->src_handle.c;
452 cx_array_list *const list = iter->src_handle; 481 if (iter->base.remove) {
453 if (itbase->remove) { 482 iter->base.remove = false;
454 itbase->remove = false; 483 cx_arl_remove(iter->src_handle.m, iter->index);
455 cx_arl_remove(iter->src_handle, iter->index);
456 } 484 }
457 iter->index--; 485 iter->index--;
458 if (iter->index < list->base.size) { 486 if (iter->index < list->base.collection.size) {
459 iter->elem_handle = ((char *) list->data) 487 iter->elem_handle = ((char *) list->data)
460 + iter->index * list->base.item_size; 488 + iter->index * list->base.collection.elem_size;
461 } 489 }
462 } 490 }
463 491
464 static bool cx_arl_iter_flag_rm(void *it) {
465 struct cx_iterator_base_s *iter = it;
466 if (iter->mutating) {
467 iter->remove = true;
468 return true;
469 } else {
470 return false;
471 }
472 }
473 492
474 static struct cx_iterator_s cx_arl_iterator( 493 static struct cx_iterator_s cx_arl_iterator(
475 struct cx_list_s const *list, 494 struct cx_list_s const *list,
476 size_t index, 495 size_t index,
477 bool backwards 496 bool backwards
478 ) { 497 ) {
479 struct cx_iterator_s iter; 498 struct cx_iterator_s iter;
480 499
481 iter.index = index; 500 iter.index = index;
482 iter.src_handle = list; 501 iter.src_handle.c = list;
483 iter.elem_handle = cx_arl_at(list, index); 502 iter.elem_handle = cx_arl_at(list, index);
503 iter.elem_size = list->collection.elem_size;
504 iter.elem_count = list->collection.size;
484 iter.base.valid = cx_arl_iter_valid; 505 iter.base.valid = cx_arl_iter_valid;
485 iter.base.current = cx_arl_iter_current; 506 iter.base.current = cx_arl_iter_current;
486 iter.base.next = backwards ? cx_arl_iter_prev : cx_arl_iter_next; 507 iter.base.next = backwards ? cx_arl_iter_prev : cx_arl_iter_next;
487 iter.base.flag_removal = cx_arl_iter_flag_rm;
488 iter.base.remove = false; 508 iter.base.remove = false;
489 iter.base.mutating = false; 509 iter.base.mutating = false;
490 510
491 return iter; 511 return iter;
492 } 512 }
498 cx_arl_insert_iter, 518 cx_arl_insert_iter,
499 cx_arl_remove, 519 cx_arl_remove,
500 cx_arl_clear, 520 cx_arl_clear,
501 cx_arl_swap, 521 cx_arl_swap,
502 cx_arl_at, 522 cx_arl_at,
503 cx_arl_find, 523 cx_arl_find_remove,
504 cx_arl_sort, 524 cx_arl_sort,
505 cx_arl_compare, 525 cx_arl_compare,
506 cx_arl_reverse, 526 cx_arl_reverse,
507 cx_arl_iterator, 527 cx_arl_iterator,
508 }; 528 };
509 529
510 CxList *cxArrayListCreate( 530 CxList *cxArrayListCreate(
511 CxAllocator const *allocator, 531 CxAllocator const *allocator,
512 cx_compare_func comparator, 532 cx_compare_func comparator,
513 size_t item_size, 533 size_t elem_size,
514 size_t initial_capacity 534 size_t initial_capacity
515 ) { 535 ) {
516 if (allocator == NULL) { 536 if (allocator == NULL) {
517 allocator = cxDefaultAllocator; 537 allocator = cxDefaultAllocator;
518 } 538 }
519 539
520 cx_array_list *list = cxCalloc(allocator, 1, sizeof(cx_array_list)); 540 cx_array_list *list = cxCalloc(allocator, 1, sizeof(cx_array_list));
521 if (list == NULL) return NULL; 541 if (list == NULL) return NULL;
522 542
523 list->base.cl = &cx_array_list_class; 543 list->base.cl = &cx_array_list_class;
524 list->base.allocator = allocator; 544 list->base.collection.allocator = allocator;
525 list->base.cmpfunc = comparator;
526 list->capacity = initial_capacity; 545 list->capacity = initial_capacity;
527 546
528 if (item_size > 0) { 547 if (elem_size > 0) {
529 list->base.item_size = item_size; 548 list->base.collection.elem_size = elem_size;
530 } else { 549 list->base.collection.cmpfunc = comparator;
531 item_size = sizeof(void *); 550 } else {
551 elem_size = sizeof(void *);
552 list->base.collection.cmpfunc = comparator == NULL ? cx_cmp_ptr : comparator;
532 cxListStorePointers((CxList *) list); 553 cxListStorePointers((CxList *) list);
533 } 554 }
534 555
535 // allocate the array after the real item_size is known 556 // allocate the array after the real elem_size is known
536 list->data = cxCalloc(allocator, initial_capacity, item_size); 557 list->data = cxCalloc(allocator, initial_capacity, elem_size);
537 if (list->data == NULL) { 558 if (list->data == NULL) {
538 cxFree(allocator, list); 559 cxFree(allocator, list);
539 return NULL; 560 return NULL;
540 } 561 }
541 562

mercurial