25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
26 * POSSIBILITY OF SUCH DAMAGE. |
26 * POSSIBILITY OF SUCH DAMAGE. |
27 */ |
27 */ |
28 |
28 |
29 #include "cx/array_list.h" |
29 #include "cx/array_list.h" |
|
30 #include <assert.h> |
|
31 #include <string.h> |
30 |
32 |
31 /* LOW LEVEL ARRAY LIST FUNCTIONS */ |
33 /* LOW LEVEL ARRAY LIST FUNCTIONS */ |
32 |
34 |
33 |
35 enum cx_array_coppy_result cx_array_copy( |
|
36 void **target, |
|
37 size_t *size, |
|
38 size_t *capacity, |
|
39 size_t index, |
|
40 void const *src, |
|
41 size_t elem_size, |
|
42 size_t elem_count, |
|
43 struct cx_array_reallocator_s *reallocator |
|
44 ) { |
|
45 /* assert pointers */ |
|
46 assert(target != NULL); |
|
47 assert(size != NULL); |
|
48 assert(src != NULL); |
|
49 |
|
50 /* determine capacity */ |
|
51 size_t cap = capacity == NULL ? *size : *capacity; |
|
52 |
|
53 /* check if resize is required */ |
|
54 size_t newsize = index + elem_count; |
|
55 bool needrealloc = newsize > cap; |
|
56 |
|
57 /* reallocate if possible */ |
|
58 if (needrealloc) { |
|
59 /* a reallocator and a capacity variable must be available */ |
|
60 if (reallocator == NULL || capacity == NULL) { |
|
61 return CX_ARRAY_COPY_REALLOC_NOT_SUPPORTED; |
|
62 } |
|
63 |
|
64 /* increase capacity linearly */ |
|
65 cap += 16; |
|
66 |
|
67 /* perform reallocation */ |
|
68 void *newmem = reallocator->realloc( |
|
69 *target, cap, elem_size, reallocator |
|
70 ); |
|
71 if (newmem == NULL) { |
|
72 return CX_ARRAY_COPY_REALLOC_FAILED; |
|
73 } |
|
74 |
|
75 /* store new pointer and capacity */ |
|
76 *target = newmem; |
|
77 *capacity = cap; |
|
78 } |
|
79 |
|
80 /* determine target pointer */ |
|
81 char *start = *target; |
|
82 start += index * elem_size; |
|
83 |
|
84 /* copy elements and set new size */ |
|
85 memcpy(start, src, elem_count * elem_size); |
|
86 *size = newsize; |
|
87 |
|
88 /* return successfully */ |
|
89 return CX_ARRAY_COPY_SUCCESS; |
|
90 } |
34 |
91 |
35 /* HIGH LEVEL ARRAY LIST FUNCTIONS */ |
92 /* HIGH LEVEL ARRAY LIST FUNCTIONS */ |
36 |
93 |
37 typedef struct { |
94 typedef struct { |
38 struct cx_list_s base; |
95 struct cx_list_s base; |
39 void *data; |
96 void *data; |
|
97 struct cx_array_reallocator_s reallocator; |
40 } cx_array_list; |
98 } cx_array_list; |
41 |
99 |
|
100 static void *cx_arl_realloc( |
|
101 void *array, |
|
102 size_t capacity, |
|
103 size_t elem_size, |
|
104 struct cx_array_reallocator_s *alloc |
|
105 ) { |
|
106 /* retrieve the pointer to the list allocator */ |
|
107 CxAllocator const *al = alloc->ptr1; |
|
108 |
|
109 /* use the list allocator to reallocate the memory */ |
|
110 return cxRealloc(al, array, capacity * elem_size); |
|
111 } |
|
112 |
42 static void cx_arl_destructor(struct cx_list_s *list) { |
113 static void cx_arl_destructor(struct cx_list_s *list) { |
43 cx_array_list *arl = (cx_array_list*) list; |
114 cx_array_list *arl = (cx_array_list *) list; |
44 cxFree(list->allocator, arl->data); |
115 cxFree(list->allocator, arl->data); |
45 } |
116 } |
46 |
117 |
47 static int cx_arl_add( |
118 static int cx_arl_add( |
48 struct cx_list_s *list, |
119 struct cx_list_s *list, |
49 void const *elem |
120 void const *elem |
50 ) { |
121 ) { |
51 return 1; |
122 cx_array_list *arl = (cx_array_list *) list; |
|
123 return cx_array_copy( |
|
124 &arl->data, |
|
125 &list->size, |
|
126 &list->capacity, |
|
127 list->size, |
|
128 elem, |
|
129 list->itemsize, |
|
130 1, |
|
131 &arl->reallocator |
|
132 ); |
52 } |
133 } |
53 |
134 |
54 static int cx_arl_insert( |
135 static int cx_arl_insert( |
55 struct cx_list_s *list, |
136 struct cx_list_s *list, |
56 size_t index, |
137 size_t index, |