Wed, 16 Nov 2022 22:27:46 +0100
#219 array list: implement add and at
Add uses the low level cx_array_copy function which is
now also implemented, but not tested by individual unit
tests.
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
29 #include "cx/array_list.h"
30 #include <assert.h>
31 #include <string.h>
33 /* LOW LEVEL ARRAY LIST FUNCTIONS */
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);
50 /* determine capacity */
51 size_t cap = capacity == NULL ? *size : *capacity;
53 /* check if resize is required */
54 size_t newsize = index + elem_count;
55 bool needrealloc = newsize > cap;
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 }
64 /* increase capacity linearly */
65 cap += 16;
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 }
75 /* store new pointer and capacity */
76 *target = newmem;
77 *capacity = cap;
78 }
80 /* determine target pointer */
81 char *start = *target;
82 start += index * elem_size;
84 /* copy elements and set new size */
85 memcpy(start, src, elem_count * elem_size);
86 *size = newsize;
88 /* return successfully */
89 return CX_ARRAY_COPY_SUCCESS;
90 }
92 /* HIGH LEVEL ARRAY LIST FUNCTIONS */
94 typedef struct {
95 struct cx_list_s base;
96 void *data;
97 struct cx_array_reallocator_s reallocator;
98 } cx_array_list;
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;
109 /* use the list allocator to reallocate the memory */
110 return cxRealloc(al, array, capacity * elem_size);
111 }
113 static void cx_arl_destructor(struct cx_list_s *list) {
114 cx_array_list *arl = (cx_array_list *) list;
115 cxFree(list->allocator, arl->data);
116 }
118 static int cx_arl_add(
119 struct cx_list_s *list,
120 void const *elem
121 ) {
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 );
133 }
135 static int cx_arl_insert(
136 struct cx_list_s *list,
137 size_t index,
138 void const *elem
139 ) {
140 return 1;
141 }
143 static int cx_arl_insert_iter(
144 struct cx_iterator_s *iter,
145 void const *elem,
146 int prepend
147 ) {
148 return 1;
149 }
151 static int cx_arl_remove(
152 struct cx_list_s *list,
153 size_t index
154 ) {
155 return 1;
156 }
158 static void *cx_arl_at(
159 struct cx_list_s const *list,
160 size_t index
161 ) {
162 if (index < list->size) {
163 cx_array_list const *arl = (cx_array_list const *) list;
164 char *space = arl->data;
165 return space + index * list->itemsize;
166 } else {
167 return NULL;
168 }
169 }
171 static size_t cx_arl_find(
172 struct cx_list_s const *list,
173 void const *elem
174 ) {
175 return 0;
176 }
178 static void cx_arl_sort(struct cx_list_s *list) {
180 }
182 static int cx_arl_compare(
183 struct cx_list_s const *list,
184 struct cx_list_s const *other
185 ) {
187 }
189 static void cx_arl_reverse(struct cx_list_s *list) {
191 }
193 static struct cx_iterator_s cx_arl_iterator(
194 struct cx_list_s *list,
195 size_t index
196 ) {
197 struct cx_iterator_s iter;
199 return iter;
200 }
202 static cx_list_class cx_array_list_class = {
203 cx_arl_destructor,
204 cx_arl_add,
205 cx_arl_insert,
206 cx_arl_insert_iter,
207 cx_arl_remove,
208 cx_arl_at,
209 cx_arl_find,
210 cx_arl_sort,
211 cx_arl_compare,
212 cx_arl_reverse,
213 cx_arl_iterator,
214 };
216 CxList *cxArrayListCreate(
217 CxAllocator const *allocator,
218 CxListComparator comparator,
219 size_t item_size,
220 size_t initial_capacity
221 ) {
222 cx_array_list *list = cxCalloc(allocator, 1, sizeof(cx_array_list));
223 if (list == NULL) return NULL;
225 list->data = cxCalloc(allocator, initial_capacity, item_size);
226 if (list->data == NULL) {
227 cxFree(allocator, list);
228 return NULL;
229 }
231 list->base.cl = &cx_array_list_class;
232 list->base.allocator = allocator;
233 list->base.cmpfunc = comparator;
234 list->base.itemsize = item_size;
235 list->base.capacity = initial_capacity;
237 /* configure the reallocator */
238 list->reallocator.realloc = cx_arl_realloc;
239 list->reallocator.ptr1 = (void *) allocator;
241 return (CxList *) list;
242 }