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; |