Mercurial > code
comparison array.c @ 8:127254037b30
Switch to a void * array instead of void **
author | David Demelier <markand@malikania.fr> |
---|---|
date | Wed, 07 Sep 2011 20:12:40 +0200 |
parents | e8829146ebc7 |
children | bf25ed2cf42a |
comparison
equal
deleted
inserted
replaced
7:e8829146ebc7 | 8:127254037b30 |
---|---|
9 * | 9 * |
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | 14 * WHSIZESOEVER RESULTING FROM LOSS OF USE, DSIZEA OR PROFITS, WHETHER IN AN |
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
17 */ | 17 */ |
18 | 18 |
19 #include <stdio.h> | 19 #include <stdio.h> |
20 #include <stdlib.h> | 20 #include <stdlib.h> |
21 #include <string.h> | 21 #include <string.h> |
22 | 22 |
23 #include "array.h" | 23 #include "array.h" |
24 | 24 |
25 #define SIZE(x) (sizeof (void *) * (x)) | 25 #define SIZE(x) (arr->unit * (x)) |
26 | 26 |
27 static int array_grow(struct array *); | 27 static int array_grow(struct array *); |
28 | 28 |
29 struct array * | 29 struct array * |
30 array_new(const void *data, size_t bsize, int flags) | 30 array_new(const void *data, size_t unit, size_t bsize, int flags) |
31 { | 31 { |
32 struct array *arr; | 32 struct array *arr; |
33 | 33 |
34 if (!(arr = malloc(sizeof (struct array)))) | 34 if (unit == 0 || !(arr = malloc(sizeof (struct array)))) |
35 return NULL; | 35 return NULL; |
36 | 36 |
37 memset(arr, 0, sizeof (struct array)); | |
38 arr->bsize = (bsize == 0) ? ARRAY_DEFAULT_BSIZE : bsize; | 37 arr->bsize = (bsize == 0) ? ARRAY_DEFAULT_BSIZE : bsize; |
39 arr->size = bsize + 1; | |
40 arr->flags = flags; | 38 arr->flags = flags; |
41 | 39 arr->unit = unit; |
42 if (!(arr->data = calloc(bsize + 1, sizeof (void *)))) { | 40 arr->size = SIZE(bsize); |
41 arr->length = 0; | |
42 | |
43 if (!(arr->data = malloc(arr->size))) { | |
43 free(arr); | 44 free(arr); |
44 return NULL; | 45 return NULL; |
45 } | 46 } |
46 | 47 |
47 if (data) | 48 if (data) |
48 arr->data[arr->length++] = (void *) data; | 49 memcpy(&arr->data[0], data, arr->unit); |
49 | 50 |
50 return arr; | 51 return arr; |
51 } | 52 } |
52 | 53 |
53 /* | 54 /* |
61 array_push(struct array *arr, const void *data) | 62 array_push(struct array *arr, const void *data) |
62 { | 63 { |
63 if (array_grow(arr) < 0) | 64 if (array_grow(arr) < 0) |
64 return -1; | 65 return -1; |
65 | 66 |
66 memmove(arr->data + 1, arr->data, SIZE(arr->length++)); | 67 memmove(&arr->data[SIZE(1)], arr->data, SIZE(arr->length++)); |
67 arr->data[0] = (void *) data; | 68 memcpy(&arr->data[0], data, arr->unit); |
68 | 69 |
69 return 0; | 70 return 0; |
70 } | 71 } |
71 | 72 |
72 /* | 73 /* |
79 array_insert(struct array *arr, const void *data, int index) | 80 array_insert(struct array *arr, const void *data, int index) |
80 { | 81 { |
81 if (index > arr->length - 1 || index < 0 || array_grow(arr) < 0) | 82 if (index > arr->length - 1 || index < 0 || array_grow(arr) < 0) |
82 return -1; | 83 return -1; |
83 | 84 |
84 memmove(arr->data + index + 1, arr->data + index, | 85 memmove(&arr->data[SIZE(index + 1)], &arr->data[SIZE(index)], |
85 SIZE(arr->length++ - index)); | 86 SIZE(arr->length++ - index)); |
86 arr->data[index] = (void *) data; | 87 memcpy(&arr->data[SIZE(index)], data, arr->unit); |
87 | 88 |
88 return 0; | 89 return 0; |
89 } | 90 } |
90 | 91 |
91 /* | 92 /* |
96 array_append(struct array *arr, const void *data) | 97 array_append(struct array *arr, const void *data) |
97 { | 98 { |
98 if (array_grow(arr) < 0) | 99 if (array_grow(arr) < 0) |
99 return -1; | 100 return -1; |
100 | 101 |
101 arr->data[arr->length++] = (void *) data; | 102 memcpy(&arr->data[SIZE(arr->length++)], data, arr->unit); |
102 | 103 |
103 return 0; | 104 return 0; |
104 } | 105 } |
105 | 106 |
106 /* | 107 /* |
114 void *data; | 115 void *data; |
115 | 116 |
116 if (arr->length == 0) | 117 if (arr->length == 0) |
117 return NULL; | 118 return NULL; |
118 | 119 |
119 data = arr->data[0]; | 120 data = &arr->data[0]; |
120 memmove(arr->data, arr->data + 1, SIZE(arr->length)); | 121 memmove(&arr->data[0], &arr->data[SIZE(1)], SIZE(arr->length)); |
121 arr->data[--arr->length] = NULL; | 122 memset(&arr->data[SIZE(--arr->length)], 0, arr->unit); |
122 | 123 |
123 return data; | 124 return data; |
124 } | 125 } |
125 | 126 |
126 /* | 127 /* |
134 void *data; | 135 void *data; |
135 | 136 |
136 if (arr->length == 0) | 137 if (arr->length == 0) |
137 return NULL; | 138 return NULL; |
138 | 139 |
139 data = arr->data[--arr->length]; | 140 data = &arr->data[SIZE(--arr->length)]; |
140 arr->data[arr->length] = NULL; | 141 memset(&arr->data[SIZE(arr->length)], 0, arr->unit); |
141 | 142 |
142 return data; | 143 return data; |
143 } | 144 } |
144 | 145 |
145 /* | 146 /* |
153 void *data; | 154 void *data; |
154 | 155 |
155 if (arr->length == 0 || index < 0 || index > arr->length - 1) | 156 if (arr->length == 0 || index < 0 || index > arr->length - 1) |
156 return NULL; | 157 return NULL; |
157 | 158 |
158 data = arr->data[index]; | 159 data = &arr->data[index]; |
159 memmove(arr->data + index, arr->data + index + 1, | 160 memmove(&arr->data[index], &arr->data[index + 1], |
160 SIZE(arr->length - index)); | 161 SIZE(arr->length - index)); |
161 arr->data[--arr->length] = NULL; | 162 memset(&arr->data[SIZE(--arr->length)], 0, arr->unit); |
162 | 163 |
163 return data; | 164 return data; |
164 } | 165 } |
165 | 166 |
166 /* | 167 /* |
169 */ | 170 */ |
170 | 171 |
171 void | 172 void |
172 array_map(struct array *arr, void (*fn)(void *, void *), void *udata) | 173 array_map(struct array *arr, void (*fn)(void *, void *), void *udata) |
173 { | 174 { |
174 size_t i; | 175 int i; |
175 | 176 |
176 for (i = 0; arr->data[i]; ++i) | 177 for (i = 0; i < arr->length; ++i) |
177 fn(arr->data[i], udata); | 178 fn(&arr->data[i], udata); |
178 } | 179 } |
179 | 180 |
180 /* | 181 /* |
181 * Compare each object with the user supplied function. If the `fn' function | 182 * Compare each object with the user supplied function. If the `fn' function |
182 * returns 1 then the data is returned. Optional idx argument can be set to | 183 * returns 1 then the data is returned. Optional idx argument can be set to |
185 */ | 186 */ |
186 | 187 |
187 void * | 188 void * |
188 array_find(struct array *arr, int (*fn)(void *, void *), void *udata, int *idx) | 189 array_find(struct array *arr, int (*fn)(void *, void *), void *udata, int *idx) |
189 { | 190 { |
190 size_t i; | 191 int st, i; |
191 int st; | 192 void *data; |
192 void *data; | 193 |
193 | 194 for (i = st = 0; i < arr->length && !st; ++i) |
194 for (i = st = 0; arr->data[i] && !st; ++i) | 195 st = fn(&arr->data[i], udata); |
195 st = fn(arr->data[i], udata); | |
196 | 196 |
197 if (st) { | 197 if (st) { |
198 data = arr->data[--i]; | 198 data = &arr->data[--i]; |
199 if (idx) | 199 if (idx) |
200 *idx = i; | 200 *idx = i; |
201 } else | 201 } else |
202 data = NULL; | 202 data = NULL; |
203 | 203 |
208 * Reset the array, if the trash argument is set it will free the object | 208 * Reset the array, if the trash argument is set it will free the object |
209 * too, otherwise the array is just truncated to 0 length. | 209 * too, otherwise the array is just truncated to 0 length. |
210 */ | 210 */ |
211 | 211 |
212 void | 212 void |
213 array_clear(struct array *arr, int trashit) | 213 array_clear(struct array *arr) |
214 { | 214 { |
215 if (trashit) { | 215 memset(arr->data, 0, arr->size); |
216 size_t i; | |
217 | |
218 for (i = 0; arr->data[i]; ++i) | |
219 free(arr->data[i]); | |
220 } | |
221 | |
222 memset(arr->data, 0, SIZE(arr->size)); | |
223 arr->length = 0; | 216 arr->length = 0; |
224 } | 217 } |
225 | 218 |
226 /* | 219 /* |
227 * Same as array_clear except it also free the array object. | 220 * Same as array_clear except it also free the array object. |
228 */ | 221 */ |
229 | 222 |
230 void | 223 void |
231 array_free(struct array *arr, int trashit) | 224 array_free(struct array *arr) |
232 { | 225 { |
233 array_clear(arr, trashit); | 226 array_clear(arr); |
234 | 227 |
235 free(arr->data); | 228 free(arr->data); |
236 free(arr); | 229 free(arr); |
237 } | 230 } |
238 | 231 |
243 */ | 236 */ |
244 | 237 |
245 static int | 238 static int |
246 array_grow(struct array *arr) | 239 array_grow(struct array *arr) |
247 { | 240 { |
248 if (arr->size - 1 > arr->length) | 241 if (arr->size / arr->unit > arr->length) |
249 return 0; | 242 return 0; |
250 | 243 |
251 if (arr->flags & ARRAY_AUTO) { | 244 if (arr->flags & ARRAY_AUTO) { |
252 if (!(arr->data = realloc(arr->data, SIZE(arr->size + arr->bsize)))) | 245 if (!(arr->data = realloc(arr->data, arr->size + |
246 SIZE(arr->bsize)))) | |
253 return -1; | 247 return -1; |
254 | 248 |
255 arr->size += arr->bsize; | 249 arr->size += arr->bsize; |
256 } else | 250 } else |
257 return (arr->size - 1 == arr->length) ? -1 : 0; | 251 return ((arr->size / arr->unit) <= arr->length) ? -1 : 0; |
258 | 252 |
259 memset(arr->data + arr->length, 0, SIZE(arr->size - arr->length)); | 253 return 0; |
260 | 254 } |
261 return 0; | |
262 } |