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