35 |
35 |
36 static void *cx_array_default_realloc( |
36 static void *cx_array_default_realloc( |
37 void *array, |
37 void *array, |
38 size_t capacity, |
38 size_t capacity, |
39 size_t elem_size, |
39 size_t elem_size, |
40 __attribute__((__unused__)) struct cx_array_reallocator_s *alloc |
40 __attribute__((__unused__)) CxArrayReallocator *alloc |
41 ) { |
41 ) { |
42 return realloc(array, capacity * elem_size); |
42 return realloc(array, capacity * elem_size); |
43 } |
43 } |
44 |
44 |
45 struct cx_array_reallocator_s cx_array_default_reallocator_impl = { |
45 CxArrayReallocator cx_array_default_reallocator_impl = { |
46 cx_array_default_realloc, NULL, NULL, 0, 0 |
46 cx_array_default_realloc, NULL, NULL, 0, 0 |
47 }; |
47 }; |
48 |
48 |
49 struct cx_array_reallocator_s *cx_array_default_reallocator = &cx_array_default_reallocator_impl; |
49 CxArrayReallocator *cx_array_default_reallocator = &cx_array_default_reallocator_impl; |
|
50 |
|
51 // Stack-aware array reallocator |
|
52 |
|
53 static void *cx_array_advanced_realloc( |
|
54 void *array, |
|
55 size_t capacity, |
|
56 size_t elem_size, |
|
57 __attribute__((__unused__)) CxArrayReallocator *alloc |
|
58 ) { |
|
59 // retrieve the pointer to the actual allocator |
|
60 const CxAllocator *al = alloc->ptr1; |
|
61 |
|
62 // check if the array is still located on the stack |
|
63 void *newmem; |
|
64 if (array == alloc->ptr2) { |
|
65 newmem = cxMalloc(al, capacity * elem_size); |
|
66 if (newmem != NULL) { |
|
67 memcpy(newmem, array, capacity * elem_size); |
|
68 } |
|
69 } else { |
|
70 newmem = cxRealloc(al, array, capacity * elem_size); |
|
71 } |
|
72 return newmem; |
|
73 } |
|
74 |
|
75 struct cx_array_reallocator_s cx_array_reallocator( |
|
76 const struct cx_allocator_s *allocator, |
|
77 const void *stackmem |
|
78 ) { |
|
79 if (allocator == NULL) { |
|
80 allocator = cxDefaultAllocator; |
|
81 } |
|
82 return (struct cx_array_reallocator_s) { |
|
83 cx_array_advanced_realloc, |
|
84 (void*) allocator, (void*) stackmem, |
|
85 0, 0 |
|
86 }; |
|
87 } |
50 |
88 |
51 // LOW LEVEL ARRAY LIST FUNCTIONS |
89 // LOW LEVEL ARRAY LIST FUNCTIONS |
52 |
90 |
53 enum cx_array_result cx_array_copy( |
91 enum cx_array_result cx_array_copy( |
54 void **target, |
92 void **target, |
126 size_t *capacity, |
164 size_t *capacity, |
127 cx_compare_func cmp_func, |
165 cx_compare_func cmp_func, |
128 const void *sorted_data, |
166 const void *sorted_data, |
129 size_t elem_size, |
167 size_t elem_size, |
130 size_t elem_count, |
168 size_t elem_count, |
131 struct cx_array_reallocator_s *reallocator |
169 CxArrayReallocator *reallocator |
132 ) { |
170 ) { |
133 // assert pointers |
171 // assert pointers |
134 assert(target != NULL); |
172 assert(target != NULL); |
135 assert(size != NULL); |
173 assert(size != NULL); |
136 assert(capacity != NULL); |
174 assert(capacity != NULL); |
335 |
373 |
336 typedef struct { |
374 typedef struct { |
337 struct cx_list_s base; |
375 struct cx_list_s base; |
338 void *data; |
376 void *data; |
339 size_t capacity; |
377 size_t capacity; |
340 struct cx_array_reallocator_s reallocator; |
378 CxArrayReallocator reallocator; |
341 } cx_array_list; |
379 } cx_array_list; |
342 |
|
343 static void *cx_arl_realloc( |
|
344 void *array, |
|
345 size_t capacity, |
|
346 size_t elem_size, |
|
347 struct cx_array_reallocator_s *alloc |
|
348 ) { |
|
349 // retrieve the pointer to the list allocator |
|
350 const CxAllocator *al = alloc->ptr1; |
|
351 |
|
352 // use the list allocator to reallocate the memory |
|
353 return cxRealloc(al, array, capacity * elem_size); |
|
354 } |
|
355 |
380 |
356 static void cx_arl_destructor(struct cx_list_s *list) { |
381 static void cx_arl_destructor(struct cx_list_s *list) { |
357 cx_array_list *arl = (cx_array_list *) list; |
382 cx_array_list *arl = (cx_array_list *) list; |
358 |
383 |
359 char *ptr = arl->data; |
384 char *ptr = arl->data; |
781 cxFree(allocator, list); |
806 cxFree(allocator, list); |
782 return NULL; |
807 return NULL; |
783 } |
808 } |
784 |
809 |
785 // configure the reallocator |
810 // configure the reallocator |
786 list->reallocator.realloc = cx_arl_realloc; |
811 list->reallocator = cx_array_reallocator(allocator, NULL); |
787 list->reallocator.ptr1 = (void *) allocator; |
|
788 |
812 |
789 return (CxList *) list; |
813 return (CxList *) list; |
790 } |
814 } |