src/array_list.c

changeset 999
84fc42b04d3b
parent 998
bb196054f3fd
child 1018
c773da859bad
equal deleted inserted replaced
998:bb196054f3fd 999:84fc42b04d3b
87 }; 87 };
88 } 88 }
89 89
90 // LOW LEVEL ARRAY LIST FUNCTIONS 90 // LOW LEVEL ARRAY LIST FUNCTIONS
91 91
92 int cx_array_copy( 92 int cx_array_reserve(
93 void **target, 93 void **array,
94 void *size, 94 void *size,
95 void *capacity, 95 void *capacity,
96 unsigned width, 96 unsigned width,
97 size_t index,
98 const void *src,
99 size_t elem_size, 97 size_t elem_size,
100 size_t elem_count, 98 size_t elem_count,
101 CxArrayReallocator *reallocator 99 CxArrayReallocator *reallocator
102 ) { 100 ) {
103 // assert pointers 101 // assert pointers
104 assert(target != NULL); 102 assert(array != NULL);
105 assert(size != NULL); 103 assert(size != NULL);
106 assert(capacity != NULL); 104 assert(capacity != NULL);
107 assert(src != NULL);
108 assert(reallocator != NULL); 105 assert(reallocator != NULL);
109 106
110 // determine size and capacity 107 // determine size and capacity
111 size_t oldcap; 108 size_t oldcap;
112 size_t oldsize; 109 size_t oldsize;
135 errno = EINVAL; 132 errno = EINVAL;
136 return 1; 133 return 1;
137 } 134 }
138 135
139 // assert that the array is allocated when it has capacity 136 // assert that the array is allocated when it has capacity
137 assert(*array != NULL || oldcap == 0);
138
139 // determine new capacity
140 size_t newcap = oldsize + elem_count;
141
142 // check for overflow
143 if (newcap > max_size) {
144 errno = EOVERFLOW;
145 return 1;
146 }
147
148 // reallocate if possible
149 if (newcap > oldcap) {
150 // calculate new capacity (next number divisible by 16)
151 newcap = newcap - (newcap % 16) + 16;
152
153 // perform reallocation
154 void *newmem = reallocator->realloc(
155 *array, newcap, elem_size, reallocator
156 );
157 if (newmem == NULL) {
158 return 1;
159 }
160
161 // store new pointer
162 *array = newmem;
163
164 // store new capacity
165 if (width == 0 || width == __WORDSIZE) {
166 *(size_t*) capacity = newcap;
167 } else if (width == 16) {
168 *(uint16_t*) capacity = newcap;
169 } else if (width == 8) {
170 *(uint8_t*) capacity = newcap;
171 }
172 #if __WORDSIZE == 64
173 else if (width == 32) {
174 *(uint32_t*) capacity = newcap;
175 }
176 #endif
177 }
178
179 return 0;
180 }
181
182 int cx_array_copy(
183 void **target,
184 void *size,
185 void *capacity,
186 unsigned width,
187 size_t index,
188 const void *src,
189 size_t elem_size,
190 size_t elem_count,
191 CxArrayReallocator *reallocator
192 ) {
193 // assert pointers
194 assert(target != NULL);
195 assert(size != NULL);
196 assert(capacity != NULL);
197 assert(src != NULL);
198 assert(reallocator != NULL);
199
200 // determine size and capacity
201 size_t oldcap;
202 size_t oldsize;
203 size_t max_size;
204 if (width == 0 || width == __WORDSIZE) {
205 oldcap = *(size_t*) capacity;
206 oldsize = *(size_t*) size;
207 max_size = SIZE_MAX;
208 } else if (width == 16) {
209 oldcap = *(uint16_t*) capacity;
210 oldsize = *(uint16_t*) size;
211 max_size = UINT16_MAX;
212 } else if (width == 8) {
213 oldcap = *(uint8_t*) capacity;
214 oldsize = *(uint8_t*) size;
215 max_size = UINT8_MAX;
216 }
217 #if __WORDSIZE == 64
218 else if (width == 32) {
219 oldcap = *(uint32_t*) capacity;
220 oldsize = *(uint32_t*) size;
221 max_size = UINT32_MAX;
222 }
223 #endif
224 else {
225 errno = EINVAL;
226 return 1;
227 }
228
229 // assert that the array is allocated when it has capacity
140 assert(*target != NULL || oldcap == 0); 230 assert(*target != NULL || oldcap == 0);
141 231
142 // check if resize is required 232 // check if resize is required
143 size_t minsize = index + elem_count; 233 size_t minsize = index + elem_count;
144 size_t newsize = oldsize < minsize ? minsize : oldsize; 234 size_t newsize = oldsize < minsize ? minsize : oldsize;

mercurial