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 |