184 cx_array_list *arl = (cx_array_list *) list; |
185 cx_array_list *arl = (cx_array_list *) list; |
185 |
186 |
186 // do we need to move some elements? |
187 // do we need to move some elements? |
187 if (index < list->size) { |
188 if (index < list->size) { |
188 char const *first_to_move = (char const *) arl->data; |
189 char const *first_to_move = (char const *) arl->data; |
189 first_to_move += index * list->itemsize; |
190 first_to_move += index * list->item_size; |
190 size_t elems_to_move = list->size - index; |
191 size_t elems_to_move = list->size - index; |
191 size_t start_of_moved = index + n; |
192 size_t start_of_moved = index + n; |
192 |
193 |
193 if (CX_ARRAY_COPY_SUCCESS != cx_array_copy( |
194 if (CX_ARRAY_COPY_SUCCESS != cx_array_copy( |
194 &arl->data, |
195 &arl->data, |
195 &list->size, |
196 &list->size, |
196 &list->capacity, |
197 &arl->capacity, |
197 start_of_moved, |
198 start_of_moved, |
198 first_to_move, |
199 first_to_move, |
199 list->itemsize, |
200 list->item_size, |
200 elems_to_move, |
201 elems_to_move, |
201 &arl->reallocator |
202 &arl->reallocator |
202 )) { |
203 )) { |
203 // if moving existing elems is unsuccessful, abort |
204 // if moving existing elems is unsuccessful, abort |
204 return 0; |
205 return 0; |
247 iter->index + 1 - prepend, |
248 iter->index + 1 - prepend, |
248 elem |
249 elem |
249 ); |
250 ); |
250 if (result == 0 && prepend != 0) { |
251 if (result == 0 && prepend != 0) { |
251 iter->index++; |
252 iter->index++; |
252 iter->elem_handle = ((char *) iter->elem_handle) + list->itemsize; |
253 iter->elem_handle = ((char *) iter->elem_handle) + list->item_size; |
253 } |
254 } |
254 return result; |
255 return result; |
255 } else { |
256 } else { |
256 int result = cx_arl_insert_element(list, list->size, elem); |
257 int result = cx_arl_insert_element(list, list->size, elem); |
257 iter->index = list->size; |
258 iter->index = list->size; |
269 if (index >= list->size) { |
270 if (index >= list->size) { |
270 return 1; |
271 return 1; |
271 } |
272 } |
272 |
273 |
273 // content destruction |
274 // content destruction |
274 if (list->content_destructor_type != CX_DESTRUCTOR_NONE) { |
275 cx_invoke_destructor(list, ((char*)arl->data) + index * list->item_size); |
275 char *ptr = arl->data; |
|
276 ptr += index * list->itemsize; |
|
277 cx_list_invoke_destructor(list, ptr); |
|
278 } |
|
279 |
276 |
280 // short-circuit removal of last element |
277 // short-circuit removal of last element |
281 if (index == list->size - 1) { |
278 if (index == list->size - 1) { |
282 list->size--; |
279 list->size--; |
283 return 0; |
280 return 0; |
305 if (list->size == 0) return; |
302 if (list->size == 0) return; |
306 |
303 |
307 cx_array_list *arl = (cx_array_list *) list; |
304 cx_array_list *arl = (cx_array_list *) list; |
308 char *ptr = arl->data; |
305 char *ptr = arl->data; |
309 |
306 |
310 switch (list->content_destructor_type) { |
307 if (list->simple_destructor) { |
311 case CX_DESTRUCTOR_SIMPLE: { |
308 for (size_t i = 0; i < list->size; i++) { |
312 for (size_t i = 0; i < list->size; i++) { |
309 cx_invoke_simple_destructor(list, ptr); |
313 cx_list_invoke_simple_destructor(list, ptr); |
310 ptr += list->item_size; |
314 ptr += list->itemsize; |
311 } |
315 } |
312 } |
316 break; |
313 if (list->advanced_destructor) { |
317 } |
314 for (size_t i = 0; i < list->size; i++) { |
318 case CX_DESTRUCTOR_ADVANCED: { |
315 cx_invoke_advanced_destructor(list, ptr); |
319 for (size_t i = 0; i < list->size; i++) { |
316 ptr += list->item_size; |
320 cx_list_invoke_advanced_destructor(list, ptr); |
317 } |
321 ptr += list->itemsize; |
318 } |
322 } |
319 |
323 break; |
320 memset(arl->data, 0, list->size * list->item_size); |
324 } |
|
325 case CX_DESTRUCTOR_NONE: |
|
326 break; // nothing |
|
327 } |
|
328 |
|
329 memset(arl->data, 0, list->size * list->itemsize); |
|
330 list->size = 0; |
321 list->size = 0; |
331 } |
322 } |
332 |
323 |
333 static int cx_arl_swap( |
324 static int cx_arl_swap( |
334 struct cx_list_s *list, |
325 struct cx_list_s *list, |
335 size_t i, |
326 size_t i, |
336 size_t j |
327 size_t j |
337 ) { |
328 ) { |
338 if (i >= list->size || j >= list->size) return 1; |
329 if (i >= list->size || j >= list->size) return 1; |
339 cx_array_list *arl = (cx_array_list *) list; |
330 cx_array_list *arl = (cx_array_list *) list; |
340 cx_array_swap(arl->data, list->itemsize, i, j); |
331 cx_array_swap(arl->data, list->item_size, i, j); |
341 return 0; |
332 return 0; |
342 } |
333 } |
343 |
334 |
344 static void *cx_arl_at( |
335 static void *cx_arl_at( |
345 struct cx_list_s const *list, |
336 struct cx_list_s const *list, |
346 size_t index |
337 size_t index |
347 ) { |
338 ) { |
348 if (index < list->size) { |
339 if (index < list->size) { |
349 cx_array_list const *arl = (cx_array_list const *) list; |
340 cx_array_list const *arl = (cx_array_list const *) list; |
350 char *space = arl->data; |
341 char *space = arl->data; |
351 return space + index * list->itemsize; |
342 return space + index * list->item_size; |
352 } else { |
343 } else { |
353 return NULL; |
344 return NULL; |
354 } |
345 } |
355 } |
346 } |
356 |
347 |
363 |
354 |
364 for (size_t i = 0; i < list->size; i++) { |
355 for (size_t i = 0; i < list->size; i++) { |
365 if (0 == list->cmpfunc(elem, cur)) { |
356 if (0 == list->cmpfunc(elem, cur)) { |
366 return i; |
357 return i; |
367 } |
358 } |
368 cur += list->itemsize; |
359 cur += list->item_size; |
369 } |
360 } |
370 |
361 |
371 return list->size; |
362 return list->size; |
372 } |
363 } |
373 |
364 |
374 static void cx_arl_sort(struct cx_list_s *list) { |
365 static void cx_arl_sort(struct cx_list_s *list) { |
375 assert(list->cmpfunc != NULL); |
366 assert(list->cmpfunc != NULL); |
376 qsort(((cx_array_list *) list)->data, |
367 qsort(((cx_array_list *) list)->data, |
377 list->size, |
368 list->size, |
378 list->itemsize, |
369 list->item_size, |
379 list->cmpfunc |
370 list->cmpfunc |
380 ); |
371 ); |
381 } |
372 } |
382 |
373 |
383 static int cx_arl_compare( |
374 static int cx_arl_compare( |
405 static void cx_arl_reverse(struct cx_list_s *list) { |
396 static void cx_arl_reverse(struct cx_list_s *list) { |
406 if (list->size < 2) return; |
397 if (list->size < 2) return; |
407 void *data = ((cx_array_list const *) list)->data; |
398 void *data = ((cx_array_list const *) list)->data; |
408 size_t half = list->size / 2; |
399 size_t half = list->size / 2; |
409 for (size_t i = 0; i < half; i++) { |
400 for (size_t i = 0; i < half; i++) { |
410 cx_array_swap(data, list->itemsize, i, list->size - 1 - i); |
401 cx_array_swap(data, list->item_size, i, list->size - 1 - i); |
411 } |
402 } |
412 } |
403 } |
413 |
404 |
414 static bool cx_arl_iter_valid(void const *it) { |
405 static bool cx_arl_iter_valid(void const *it) { |
415 struct cx_iterator_s const *iter = it; |
406 struct cx_iterator_s const *iter = it; |
446 cx_arl_remove(iter->src_handle, iter->index); |
437 cx_arl_remove(iter->src_handle, iter->index); |
447 } |
438 } |
448 iter->index--; |
439 iter->index--; |
449 if (iter->index < list->base.size) { |
440 if (iter->index < list->base.size) { |
450 iter->elem_handle = ((char *) list->data) |
441 iter->elem_handle = ((char *) list->data) |
451 + iter->index * list->base.itemsize; |
442 + iter->index * list->base.item_size; |
452 } |
443 } |
453 } |
444 } |
454 |
445 |
455 static bool cx_arl_iter_flag_rm(void *it) { |
446 static bool cx_arl_iter_flag_rm(void *it) { |
456 struct cx_iterator_base_s *iter = it; |
447 struct cx_iterator_base_s *iter = it; |
498 cx_arl_iterator, |
489 cx_arl_iterator, |
499 }; |
490 }; |
500 |
491 |
501 CxList *cxArrayListCreate( |
492 CxList *cxArrayListCreate( |
502 CxAllocator const *allocator, |
493 CxAllocator const *allocator, |
503 CxListComparator comparator, |
494 cx_compare_func comparator, |
504 size_t item_size, |
495 size_t item_size, |
505 size_t initial_capacity |
496 size_t initial_capacity |
506 ) { |
497 ) { |
507 if (allocator == NULL) { |
498 if (allocator == NULL) { |
508 allocator = cxDefaultAllocator; |
499 allocator = cxDefaultAllocator; |
512 if (list == NULL) return NULL; |
503 if (list == NULL) return NULL; |
513 |
504 |
514 list->base.cl = &cx_array_list_class; |
505 list->base.cl = &cx_array_list_class; |
515 list->base.allocator = allocator; |
506 list->base.allocator = allocator; |
516 list->base.cmpfunc = comparator; |
507 list->base.cmpfunc = comparator; |
517 list->base.capacity = initial_capacity; |
508 list->capacity = initial_capacity; |
518 |
509 |
519 if (item_size > 0) { |
510 if (item_size > 0) { |
520 list->base.itemsize = item_size; |
511 list->base.item_size = item_size; |
521 } else { |
512 } else { |
522 item_size = sizeof(void*); |
513 item_size = sizeof(void*); |
523 cxListStorePointers((CxList *) list); |
514 cxListStorePointers((CxList *) list); |
524 } |
515 } |
525 |
516 |