src/array_list.c

changeset 677
b09aae58bba4
parent 676
d0680a23d850
child 678
78f943d76f50
equal deleted inserted replaced
676:d0680a23d850 677:b09aae58bba4
148 // HIGH LEVEL ARRAY LIST FUNCTIONS 148 // HIGH LEVEL ARRAY LIST FUNCTIONS
149 149
150 typedef struct { 150 typedef struct {
151 struct cx_list_s base; 151 struct cx_list_s base;
152 void *data; 152 void *data;
153 size_t capacity;
153 struct cx_array_reallocator_s reallocator; 154 struct cx_array_reallocator_s reallocator;
154 } cx_array_list; 155 } cx_array_list;
155 156
156 static void *cx_arl_realloc( 157 static void *cx_arl_realloc(
157 void *array, 158 void *array,
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;
211 212
212 // place the new elements 213 // place the new elements
213 if (CX_ARRAY_COPY_SUCCESS == cx_array_copy( 214 if (CX_ARRAY_COPY_SUCCESS == cx_array_copy(
214 &arl->data, 215 &arl->data,
215 &list->size, 216 &list->size,
216 &list->capacity, 217 &arl->capacity,
217 index, 218 index,
218 array, 219 array,
219 list->itemsize, 220 list->item_size,
220 n, 221 n,
221 &arl->reallocator 222 &arl->reallocator
222 )) { 223 )) {
223 return n; 224 return n;
224 } else { 225 } else {
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;
285 282
286 // just move the elements starting at index to the left 283 // just move the elements starting at index to the left
287 int result = cx_array_copy( 284 int result = cx_array_copy(
288 &arl->data, 285 &arl->data,
289 &list->size, 286 &list->size,
290 &list->capacity, 287 &arl->capacity,
291 index, 288 index,
292 ((char *) arl->data) + (index + 1) * list->itemsize, 289 ((char *) arl->data) + (index + 1) * list->item_size,
293 list->itemsize, 290 list->item_size,
294 list->size - index - 1, 291 list->size - index - 1,
295 &arl->reallocator 292 &arl->reallocator
296 ); 293 );
297 if (result == 0) { 294 if (result == 0) {
298 // decrease the size 295 // decrease the size
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(
391 for (size_t i = 0; i < list->size; i++) { 382 for (size_t i = 0; i < list->size; i++) {
392 int d = list->cmpfunc(left, right); 383 int d = list->cmpfunc(left, right);
393 if (d != 0) { 384 if (d != 0) {
394 return d; 385 return d;
395 } 386 }
396 left += list->itemsize; 387 left += list->item_size;
397 right += other->itemsize; 388 right += other->item_size;
398 } 389 }
399 return 0; 390 return 0;
400 } else { 391 } else {
401 return list->size < other->size ? -1 : 1; 392 return list->size < other->size ? -1 : 1;
402 } 393 }
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;
431 } else { 422 } else {
432 struct cx_iterator_s *iter = it; 423 struct cx_iterator_s *iter = it;
433 iter->index++; 424 iter->index++;
434 iter->elem_handle = 425 iter->elem_handle =
435 ((char *) iter->elem_handle) 426 ((char *) iter->elem_handle)
436 + ((struct cx_list_s const *) iter->src_handle)->itemsize; 427 + ((struct cx_list_s const *) iter->src_handle)->item_size;
437 } 428 }
438 } 429 }
439 430
440 static void cx_arl_iter_prev(void *it) { 431 static void cx_arl_iter_prev(void *it) {
441 struct cx_iterator_base_s *itbase = it; 432 struct cx_iterator_base_s *itbase = 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

mercurial