Mercurial > code
comparison parray.c @ 136:c6d9eb5702e8
array:
o add ARRAY_FASTREMOVE, use last object when removing,
o add ARRAY_CLEARBITS, set to 0 the bytes when removing
parray:
o add PARRAY_FASTREMOVE, use last object when removing,
o add PARRAY_NULLEND, always has a last NULL entry
author | David Demelier <markand@malikania.fr> |
---|---|
date | Mon, 26 Mar 2012 10:24:49 +0200 |
parents | 5917096facb9 |
children | 97c9c20535e2 |
comparison
equal
deleted
inserted
replaced
135:07800b7af208 | 136:c6d9eb5702e8 |
---|---|
32 /* Set defaults if needed */ | 32 /* Set defaults if needed */ |
33 arr->bsize = (arr->bsize <= 0) ? PARRAY_DEFAULT_BSIZE : arr->bsize; | 33 arr->bsize = (arr->bsize <= 0) ? PARRAY_DEFAULT_BSIZE : arr->bsize; |
34 arr->malloc = (arr->malloc == NULL) ? &malloc : arr->malloc; | 34 arr->malloc = (arr->malloc == NULL) ? &malloc : arr->malloc; |
35 arr->realloc = (arr->realloc == NULL) ? &realloc : arr->realloc; | 35 arr->realloc = (arr->realloc == NULL) ? &realloc : arr->realloc; |
36 | 36 |
37 arr->bsize += (arr->flags & PARRAY_NULLEND) ? 1 : 0; | |
37 arr->size = LENGTH(arr->bsize); | 38 arr->size = LENGTH(arr->bsize); |
38 | 39 |
39 if ((arr->data = arr->malloc(arr->size)) == NULL) | 40 if ((arr->data = arr->malloc(arr->size)) == NULL) |
40 return -1; | 41 return -1; |
41 | 42 |
42 memset(arr->data, 0, LENGTH(arr->bsize)); | 43 memset(arr->data, 0, arr->size); |
43 | 44 |
44 return 0; | 45 return 0; |
45 } | 46 } |
46 | 47 |
47 /* | 48 /* |
48 * Valid options that can be set for an array : | 49 * Valid options that can be set for an array : |
49 * l -> optional array block size of type int | 50 * l -> optional array block size of type int |
50 * m -> malloc function that must matches void * (*malloc)(size_t) | 51 * m -> malloc function that must matches void * (*malloc)(size_t) |
51 * r -> realloc function that must matches void * (*realloc)(void *, size_t) | 52 * r -> realloc function that must matches void * (*realloc)(void *, size_t) |
52 * t -> type of array of type int | 53 * f -> parray flags of type int |
53 */ | 54 */ |
54 | 55 |
55 void | 56 void |
56 parray_set(struct parray *arr, const char *fmt, ...) | 57 parray_set(struct parray *arr, const char *fmt, ...) |
57 { | 58 { |
68 arr->malloc = va_arg(ap, void * (*)(size_t)); | 69 arr->malloc = va_arg(ap, void * (*)(size_t)); |
69 break; | 70 break; |
70 case 'r': | 71 case 'r': |
71 arr->realloc = va_arg(ap, void * (*)(void *, size_t)); | 72 arr->realloc = va_arg(ap, void * (*)(void *, size_t)); |
72 break; | 73 break; |
73 case 't': | 74 case 'f': |
74 arr->type = va_arg(ap, int); | 75 arr->flags = va_arg(ap, int); |
75 break; | 76 break; |
76 default: | 77 default: |
77 break; | 78 break; |
78 } | 79 } |
79 } | 80 } |
90 if (grow(arr) < 0) | 91 if (grow(arr) < 0) |
91 return -1; | 92 return -1; |
92 | 93 |
93 memmove(&arr->data[1], &arr->data[0], LENGTH(arr->length++)); | 94 memmove(&arr->data[1], &arr->data[0], LENGTH(arr->length++)); |
94 arr->data[0] = data; | 95 arr->data[0] = data; |
96 | |
97 if (arr->flags & PARRAY_NULLEND) | |
98 arr->data[arr->length] = NULL; | |
95 | 99 |
96 return 0; | 100 return 0; |
97 } | 101 } |
98 | 102 |
99 /* | 103 /* |
112 /* Good place */ | 116 /* Good place */ |
113 memmove(&arr->data[index + 1], &arr->data[index], | 117 memmove(&arr->data[index + 1], &arr->data[index], |
114 LENGTH(arr->length++ - index)); | 118 LENGTH(arr->length++ - index)); |
115 arr->data[index] = data; | 119 arr->data[index] = data; |
116 | 120 |
121 if (arr->flags & PARRAY_NULLEND) | |
122 arr->data[arr->length] = NULL; | |
123 | |
117 return 0; | 124 return 0; |
118 } | 125 } |
119 | 126 |
120 /* | 127 /* |
121 * Append the data to the end of array. | 128 * Append the data to the end of array. |
127 if (grow(arr) < 0) | 134 if (grow(arr) < 0) |
128 return -1; | 135 return -1; |
129 | 136 |
130 arr->data[arr->length++] = data; | 137 arr->data[arr->length++] = data; |
131 | 138 |
139 if (arr->flags & PARRAY_NULLEND) | |
140 arr->data[arr->length] = NULL; | |
141 | |
132 return 0; | 142 return 0; |
133 } | 143 } |
134 | 144 |
135 /* | 145 /* |
136 * Remove the array's head. | 146 * Remove the array's head. |
137 */ | 147 */ |
138 | 148 |
139 void | 149 void |
140 parray_pop(struct parray *arr) | 150 parray_pop(struct parray *arr) |
141 { | 151 { |
142 if (arr->length > 0) { | 152 parray_iremove(arr, 0); |
143 memmove(&arr->data[0], &arr->data[1], LENGTH(--arr->length)); | 153 } |
144 arr->data[arr->length] = NULL; | 154 |
155 /* | |
156 * Remove the array's tail. | |
157 */ | |
158 | |
159 void | |
160 parray_unqueue(struct parray *arr) | |
161 { | |
162 parray_iremove(arr, arr->length - 1); | |
163 } | |
164 | |
165 /* | |
166 * Remove the data at the specified index. Bounds are checked. | |
167 */ | |
168 | |
169 void | |
170 parray_iremove(struct parray *arr, int index) | |
171 { | |
172 if (arr->length > 0 && index >= 0 && index < arr->length) { | |
173 if (arr->flags & PARRAY_FASTREMOVE) | |
174 arr->data[index] = arr->data[--arr->length]; | |
175 else | |
176 memmove(&arr->data[index], &arr->data[index + 1], | |
177 LENGTH(arr->length-- - index - 1)); | |
145 } | 178 } |
146 } | 179 |
147 | 180 arr->data[arr->length] = NULL; |
148 /* | |
149 * Remove the array's tail. | |
150 */ | |
151 | |
152 void | |
153 parray_unqueue(struct parray *arr) | |
154 { | |
155 if (arr->length > 0) | |
156 arr->data[--arr->length] = NULL; | |
157 } | |
158 | |
159 /* | |
160 * Remove the data at the specified index. Bounds are checked. | |
161 */ | |
162 | |
163 void | |
164 parray_iremove(struct parray *arr, int index) | |
165 { | |
166 if (arr->length > 0 && index >= 0 && index < arr->length) { | |
167 memmove(&arr->data[index], &arr->data[index + 1], | |
168 LENGTH(arr->length - index - 1)); | |
169 arr->data[--arr->length] = NULL; | |
170 } | |
171 } | 181 } |
172 | 182 |
173 /* | 183 /* |
174 * Remove the object referenced by the `data' argument. Useful when you | 184 * Remove the object referenced by the `data' argument. Useful when you |
175 * don't know the index. | 185 * don't know the index. |
270 *(void **)ptr = arr->data[i - 1]; | 280 *(void **)ptr = arr->data[i - 1]; |
271 | 281 |
272 return (st) ? i - 1 : -1; | 282 return (st) ? i - 1 : -1; |
273 } | 283 } |
274 | 284 |
285 void * | |
286 parray_first(const struct parray *arr) | |
287 { | |
288 return arr->data[0]; | |
289 } | |
290 | |
291 void * | |
292 parray_last(const struct parray *arr) | |
293 { | |
294 if (arr->length == 0) | |
295 return parray_first(arr); | |
296 | |
297 return arr->data[arr->length - 1]; | |
298 | |
299 } | |
300 | |
301 void * | |
302 parray_index(const struct parray *arr, int idx) | |
303 { | |
304 if (idx < 0) | |
305 return parray_first(arr); | |
306 if (idx >= arr->length) | |
307 return parray_last(arr); | |
308 | |
309 return arr->data[idx]; | |
310 } | |
311 | |
275 /* | 312 /* |
276 * Reset the array by setting each pointer to NULL and the length to 0. | 313 * Reset the array by setting each pointer to NULL and the length to 0. |
277 */ | 314 */ |
278 | 315 |
279 void | 316 void |
280 parray_clear(struct parray *arr) | 317 parray_clear(struct parray *arr) |
281 { | 318 { |
282 memset(arr->data, 0, arr->size); | 319 arr->data[0] = NULL; |
283 arr->length = 0; | 320 arr->length = 0; |
284 } | 321 } |
285 | 322 |
286 /* | 323 /* |
287 * Same as parray_clear except it also free the array object. | 324 * Same as parray_clear except it also free the array object. |
288 */ | 325 */ |
289 | 326 |
290 void | 327 void |
291 parray_free(struct parray *arr) | 328 parray_free(struct parray *arr) |
292 { | 329 { |
330 parray_clear(arr); | |
293 free(arr->data); | 331 free(arr->data); |
332 | |
333 arr->data = NULL; | |
334 arr->size = 0; | |
294 } | 335 } |
295 | 336 |
296 /* | 337 /* |
297 * Increate the array storage when it is full. If the buffer is fixed size | 338 * Increate the array storage when it is full. If the buffer is fixed size |
298 * it returns -1 on full buffer otherwise 0 is returned if allocation | 339 * it returns -1 on full buffer otherwise 0 is returned if allocation |
300 */ | 341 */ |
301 | 342 |
302 static int | 343 static int |
303 grow(struct parray *arr) | 344 grow(struct parray *arr) |
304 { | 345 { |
305 if ((arr->size / sizeof (void *)) > (size_t) arr->length) | 346 int toadd; |
347 | |
348 toadd = (arr->flags & PARRAY_NULLEND) ? 2 : 1; | |
349 | |
350 if ((arr->size / sizeof (void *)) - arr->length >= toadd) | |
306 return 0; | 351 return 0; |
307 | 352 |
308 if (arr->type == PARRAY_AUTO) { | 353 if (!(arr->flags & PARRAY_FIXED)) { |
309 if ((arr->data = arr->realloc(arr->data, arr->size + | 354 if ((arr->data = arr->realloc(arr->data, arr->size + |
310 LENGTH(arr->bsize))) == NULL) | 355 LENGTH(arr->bsize))) == NULL) { |
356 arr->size = arr->length = 0; | |
311 return -1; | 357 return -1; |
358 } | |
312 | 359 |
313 arr->size += LENGTH(arr->bsize); | 360 arr->size += LENGTH(arr->bsize); |
314 } else | 361 } else |
315 return -1; | 362 return -1; |
316 | 363 |