src/array_list.c

changeset 1322
7be10b57f658
parent 1319
aa1f580f8f59
equal deleted inserted replaced
1321:1003c014bf92 1322:7be10b57f658
34 34
35 // Default array reallocator 35 // Default array reallocator
36 36
37 static void *cx_array_default_realloc( 37 static void *cx_array_default_realloc(
38 void *array, 38 void *array,
39 size_t capacity, 39 cx_attr_unused size_t old_capacity,
40 size_t new_capacity,
40 size_t elem_size, 41 size_t elem_size,
41 cx_attr_unused CxArrayReallocator *alloc 42 cx_attr_unused CxArrayReallocator *alloc
42 ) { 43 ) {
43 size_t n; 44 size_t n;
44 if (cx_szmul(capacity, elem_size, &n)) { 45 if (cx_szmul(new_capacity, elem_size, &n)) {
45 errno = EOVERFLOW; 46 errno = EOVERFLOW;
46 return NULL; 47 return NULL;
47 } 48 }
48 return cxReallocDefault(array, n); 49 return cxReallocDefault(array, n);
49 } 50 }
56 57
57 // Stack-aware array reallocator 58 // Stack-aware array reallocator
58 59
59 static void *cx_array_advanced_realloc( 60 static void *cx_array_advanced_realloc(
60 void *array, 61 void *array,
61 size_t capacity, 62 size_t old_capacity,
63 size_t new_capacity,
62 size_t elem_size, 64 size_t elem_size,
63 cx_attr_unused CxArrayReallocator *alloc 65 cx_attr_unused CxArrayReallocator *alloc
64 ) { 66 ) {
65 // check for overflow 67 // check for overflow
66 size_t n; 68 size_t n;
67 if (cx_szmul(capacity, elem_size, &n)) { 69 if (cx_szmul(new_capacity, elem_size, &n)) {
68 errno = EOVERFLOW; 70 errno = EOVERFLOW;
69 return NULL; 71 return NULL;
70 } 72 }
71 73
72 // retrieve the pointer to the actual allocator 74 // retrieve the pointer to the actual allocator
75 // check if the array is still located on the stack 77 // check if the array is still located on the stack
76 void *newmem; 78 void *newmem;
77 if (array == alloc->ptr2) { 79 if (array == alloc->ptr2) {
78 newmem = cxMalloc(al, n); 80 newmem = cxMalloc(al, n);
79 if (newmem != NULL && array != NULL) { 81 if (newmem != NULL && array != NULL) {
80 memcpy(newmem, array, n); 82 memcpy(newmem, array, old_capacity*elem_size);
81 } 83 }
82 } else { 84 } else {
83 newmem = cxRealloc(al, array, n); 85 newmem = cxRealloc(al, array, n);
84 } 86 }
85 return newmem; 87 return newmem;
178 // calculate new capacity (next number divisible by 16) 180 // calculate new capacity (next number divisible by 16)
179 newcap = cx_array_align_capacity(newcap, 16, max_size); 181 newcap = cx_array_align_capacity(newcap, 16, max_size);
180 182
181 // perform reallocation 183 // perform reallocation
182 void *newmem = reallocator->realloc( 184 void *newmem = reallocator->realloc(
183 *array, newcap, elem_size, reallocator 185 *array, oldcap, newcap, elem_size, reallocator
184 ); 186 );
185 if (newmem == NULL) { 187 if (newmem == NULL) {
186 return 1; // LCOV_EXCL_LINE 188 return 1; // LCOV_EXCL_LINE
187 } 189 }
188 190
284 newcap = cx_array_align_capacity(newsize, 16, max_size); 286 newcap = cx_array_align_capacity(newsize, 16, max_size);
285 assert(newcap > newsize); 287 assert(newcap > newsize);
286 288
287 // perform reallocation 289 // perform reallocation
288 void *newmem = reallocator->realloc( 290 void *newmem = reallocator->realloc(
289 *target, newcap, elem_size, reallocator 291 *target, oldcap, newcap, elem_size, reallocator
290 ); 292 );
291 if (newmem == NULL) { 293 if (newmem == NULL) {
292 return 1; 294 return 1;
293 } 295 }
294 296
364 return 1; 366 return 1;
365 } 367 }
366 368
367 // store some counts 369 // store some counts
368 size_t old_size = *size; 370 size_t old_size = *size;
371 size_t old_capacity = *capacity;
369 size_t needed_capacity = old_size + elem_count; 372 size_t needed_capacity = old_size + elem_count;
370 373
371 // if we need more than we have, try a reallocation 374 // if we need more than we have, try a reallocation
372 if (needed_capacity > *capacity) { 375 if (needed_capacity > old_capacity) {
373 size_t new_capacity = cx_array_align_capacity(needed_capacity, 16, SIZE_MAX); 376 size_t new_capacity = cx_array_align_capacity(needed_capacity, 16, SIZE_MAX);
374 void *new_mem = reallocator->realloc( 377 void *new_mem = reallocator->realloc(
375 *target, new_capacity, elem_size, reallocator 378 *target, old_capacity, new_capacity, elem_size, reallocator
376 ); 379 );
377 if (new_mem == NULL) { 380 if (new_mem == NULL) {
378 // give it up right away, there is no contract 381 // give it up right away, there is no contract
379 // that requires us to insert as much as we can 382 // that requires us to insert as much as we can
380 return 1; // LCOV_EXCL_LINE 383 return 1; // LCOV_EXCL_LINE

mercurial