Mercurial > code
annotate array.c @ 163:66d317ba4b80
Added a new _qsort function for array and parray
author | David Demelier <markand@malikania.fr> |
---|---|
date | Mon, 03 Sep 2012 21:40:54 +0200 |
parents | 94847374833b |
children | 970e491d93cb |
rev | line source |
---|---|
62 | 1 /* |
2 * array.c -- manipulate dynamic arrays | |
3 * | |
98 | 4 * Copyright (c) 2011, 2012, David Demelier <markand@malikania.fr> |
62 | 5 * |
6 * Permission to use, copy, modify, and/or distribute this software for any | |
7 * purpose with or without fee is hereby granted, provided that the above | |
8 * copyright notice and this permission notice appear in all copies. | |
9 * | |
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
17 */ | |
18 | |
19 #include <stdio.h> | |
20 #include <stdlib.h> | |
21 #include <string.h> | |
22 | |
23 #include "array.h" | |
24 | |
25 #define OFFSET(x) (arr->unit * (x)) | |
26 | |
163
66d317ba4b80
Added a new _qsort function for array and parray
David Demelier <markand@malikania.fr>
parents:
159
diff
changeset
|
27 static int grow(struct array *); |
62 | 28 |
91
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
29 int |
93
9ebea85c7765
Use pointer instead of copying variable in ARRAY_FOREACH, then you can modify it
David Demelier <markand@malikania.fr>
parents:
92
diff
changeset
|
30 array_init(struct array *arr, size_t unit) |
62 | 31 { |
91
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
32 if (unit == 0) |
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
33 return -1; |
62 | 34 |
35 arr->unit = unit; | |
163
66d317ba4b80
Added a new _qsort function for array and parray
David Demelier <markand@malikania.fr>
parents:
159
diff
changeset
|
36 arr->size = OFFSET(arr->chksize); |
62 | 37 |
92 | 38 /* Set defaults if needed */ |
163
66d317ba4b80
Added a new _qsort function for array and parray
David Demelier <markand@malikania.fr>
parents:
159
diff
changeset
|
39 arr->chksize = (arr->chksize <= 0) ? ARRAY_DEFAULT_CHKSIZE : arr->chksize; |
91
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
40 arr->malloc = (arr->malloc == NULL) ? &malloc : arr->malloc; |
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
41 arr->realloc = (arr->realloc == NULL) ? &realloc : arr->realloc; |
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
42 |
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
43 if ((arr->data = arr->malloc(arr->size)) == NULL) |
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
44 return -1; |
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
45 |
136 | 46 if (arr->flags & ARRAY_CLEARBITS) |
47 memset(arr->data, 0, arr->size); | |
48 | |
91
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
49 return 0; |
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
50 } |
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
51 |
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
52 /* |
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
53 * Valid options that can be set for an array : |
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
54 * l -> optional array block size of type int |
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
55 * m -> malloc function that must matches void * (*malloc)(size_t) |
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
56 * r -> realloc function that must matches void * (*realloc)(void *, size_t) |
136 | 57 * f -> array flags of type int |
91
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
58 */ |
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
59 void |
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
60 array_set(struct array *arr, const char *fmt, ...) |
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
61 { |
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
62 va_list ap; |
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
63 const char *p; |
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
64 |
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
65 va_start(ap, fmt); |
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
66 for (p = fmt; *p != '\0'; ++p) |
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
67 switch (*p) { |
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
68 case 'l': |
163
66d317ba4b80
Added a new _qsort function for array and parray
David Demelier <markand@malikania.fr>
parents:
159
diff
changeset
|
69 arr->chksize = va_arg(ap, int); |
91
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
70 break; |
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
71 case 'm': |
93
9ebea85c7765
Use pointer instead of copying variable in ARRAY_FOREACH, then you can modify it
David Demelier <markand@malikania.fr>
parents:
92
diff
changeset
|
72 arr->malloc = va_arg(ap, void *(*)(size_t)); |
91
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
73 break; |
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
74 case 'r': |
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
75 arr->realloc = va_arg(ap, void *(*)(void *, size_t)); |
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
76 break; |
136 | 77 case 'f': |
78 arr->flags = va_arg(ap, int); | |
99
d534fdcbb319
Remove #ifdef __cplusplus
David Demelier <markand@malikania.fr>
parents:
98
diff
changeset
|
79 break; |
91
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
80 default: |
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
81 break; |
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
82 } |
62 | 83 } |
84 | |
85 /* | |
86 * Add to the head of array. NOTE: this may be very slow when adding a lot | |
87 * of object (about 100000). If you need to add a lot of data please consider | |
142
e3cf5ac9a5aa
[p]array_insert now returns -1 or index of added element
David Demelier <markand@malikania.fr>
parents:
136
diff
changeset
|
88 * using linked list instead. Returns -1 on failure or 0 on success. |
62 | 89 */ |
90 int | |
91 array_push(struct array *arr, const void *data) | |
92 { | |
124
5917096facb9
Use enum and add #ifdef __cplusplus
David Demelier <markand@malikania.fr>
parents:
123
diff
changeset
|
93 if (grow(arr) < 0) |
62 | 94 return -1; |
95 | |
64
9cc5d6d0563e
Add more cast for old gcc and other cc
David Demelier <markand@malikania.fr>
parents:
62
diff
changeset
|
96 memmove((char *)arr->data + arr->unit, arr->data, OFFSET(arr->length++)); |
9cc5d6d0563e
Add more cast for old gcc and other cc
David Demelier <markand@malikania.fr>
parents:
62
diff
changeset
|
97 memcpy((char *)arr->data, data, arr->unit); |
62 | 98 |
99 return 0; | |
100 } | |
101 | |
102 /* | |
103 * Insert the data at the specified index. The function returns -1 on | |
142
e3cf5ac9a5aa
[p]array_insert now returns -1 or index of added element
David Demelier <markand@malikania.fr>
parents:
136
diff
changeset
|
104 * allocation failure or the position of the added element. |
62 | 105 */ |
106 int | |
107 array_insert(struct array *arr, const void *data, int index) | |
108 { | |
147
535f12e0a5af
Add a flag to prevent insertions at out of bounds
David Demelier <markand@malikania.fr>
parents:
142
diff
changeset
|
109 if (arr->flags & ARRAY_INSERTSAFE) |
535f12e0a5af
Add a flag to prevent insertions at out of bounds
David Demelier <markand@malikania.fr>
parents:
142
diff
changeset
|
110 if (index < 0 || index > arr->length) |
535f12e0a5af
Add a flag to prevent insertions at out of bounds
David Demelier <markand@malikania.fr>
parents:
142
diff
changeset
|
111 return -1; |
535f12e0a5af
Add a flag to prevent insertions at out of bounds
David Demelier <markand@malikania.fr>
parents:
142
diff
changeset
|
112 |
118 | 113 if (index < 0) |
114 return array_push(arr, data); | |
115 if (index >= arr->length) | |
116 return array_append(arr, data); | |
62 | 117 |
118 | 118 /* Good place */ |
64
9cc5d6d0563e
Add more cast for old gcc and other cc
David Demelier <markand@malikania.fr>
parents:
62
diff
changeset
|
119 memmove((char *)arr->data + OFFSET(index + 1), |
9cc5d6d0563e
Add more cast for old gcc and other cc
David Demelier <markand@malikania.fr>
parents:
62
diff
changeset
|
120 (char *)arr->data + OFFSET(index), OFFSET(arr->length++ - index)); |
9cc5d6d0563e
Add more cast for old gcc and other cc
David Demelier <markand@malikania.fr>
parents:
62
diff
changeset
|
121 memcpy((char *)arr->data + OFFSET(index), data, arr->unit); |
62 | 122 |
142
e3cf5ac9a5aa
[p]array_insert now returns -1 or index of added element
David Demelier <markand@malikania.fr>
parents:
136
diff
changeset
|
123 return index; |
62 | 124 } |
125 | |
126 /* | |
142
e3cf5ac9a5aa
[p]array_insert now returns -1 or index of added element
David Demelier <markand@malikania.fr>
parents:
136
diff
changeset
|
127 * Append the data to the end of array. Returns -1 on failure or the position |
e3cf5ac9a5aa
[p]array_insert now returns -1 or index of added element
David Demelier <markand@malikania.fr>
parents:
136
diff
changeset
|
128 * of the added element. |
62 | 129 */ |
130 int | |
131 array_append(struct array *arr, const void *data) | |
132 { | |
124
5917096facb9
Use enum and add #ifdef __cplusplus
David Demelier <markand@malikania.fr>
parents:
123
diff
changeset
|
133 if (grow(arr) < 0) |
62 | 134 return -1; |
135 | |
64
9cc5d6d0563e
Add more cast for old gcc and other cc
David Demelier <markand@malikania.fr>
parents:
62
diff
changeset
|
136 memcpy((char *)arr->data + OFFSET(arr->length++), data, arr->unit); |
62 | 137 |
142
e3cf5ac9a5aa
[p]array_insert now returns -1 or index of added element
David Demelier <markand@malikania.fr>
parents:
136
diff
changeset
|
138 return (arr->length - 1); |
62 | 139 } |
140 | |
141 /* | |
142 * Remove the array's head. | |
143 */ | |
144 void | |
145 array_pop(struct array *arr) | |
146 { | |
136 | 147 array_iremove(arr, 0); |
62 | 148 } |
149 | |
150 /* | |
151 * Remove the array's tail. | |
152 */ | |
153 void | |
154 array_unqueue(struct array *arr) | |
155 { | |
136 | 156 array_iremove(arr, arr->length - 1); |
62 | 157 } |
158 | |
159 /* | |
160 * Remove the data at the specified index. Bounds are checked. | |
161 */ | |
162 void | |
119 | 163 array_iremove(struct array *arr, int index) |
62 | 164 { |
165 if (arr->length > 0 && index >= 0 && index < arr->length) { | |
136 | 166 if (arr->flags & ARRAY_FASTREMOVE) |
167 memmove((char *)arr->data + OFFSET(index), | |
168 (char *)arr->data + OFFSET(--arr->length), | |
169 arr->unit); | |
170 else | |
171 memmove((char *)arr->data + OFFSET(index), | |
172 (char *)arr->data + OFFSET(index + 1), | |
173 OFFSET(arr->length-- - index - 1)); | |
62 | 174 } |
136 | 175 |
176 if (arr->flags & ARRAY_CLEARBITS) | |
177 memset((char *)arr->data + OFFSET(arr->length), 0, arr->unit); | |
62 | 178 } |
179 | |
180 /* | |
181 * Remove the object referenced by the `data' argument. Useful when you | |
182 * don't know the index. | |
183 */ | |
184 void | |
119 | 185 array_premove(struct array *arr, const void *data) |
62 | 186 { |
187 void *elm; | |
188 int i; | |
189 | |
190 for (i = 0; i < arr->length; ++i) { | |
64
9cc5d6d0563e
Add more cast for old gcc and other cc
David Demelier <markand@malikania.fr>
parents:
62
diff
changeset
|
191 elm = (char *)arr->data + OFFSET(i); |
62 | 192 |
136 | 193 if (memcmp(elm, data, arr->unit) == 0) { |
123 | 194 array_iremove(arr, i); |
136 | 195 break; |
196 } | |
62 | 197 } |
198 } | |
199 | |
200 /* | |
201 * Swap the two elements referenced by index `i1' and `i2'. This function needs | |
202 * to allocate data to swap elements thus if the functions fails it returns -1 | |
203 * otherwise 0 is returned. | |
204 */ | |
205 int | |
206 array_iswap(struct array *arr, int i1, int i2) | |
207 { | |
208 void *tmp; | |
209 | |
210 /* Out of bounds */ | |
211 if (i1 >= arr->length || i1 < 0 || i2 >= arr->length || i2 < 0) | |
212 return -1; | |
213 | |
91
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
214 if ((tmp = arr->malloc(arr->unit)) == NULL) |
62 | 215 return -1; |
216 | |
64
9cc5d6d0563e
Add more cast for old gcc and other cc
David Demelier <markand@malikania.fr>
parents:
62
diff
changeset
|
217 memcpy((char *)tmp, (char *)arr->data + OFFSET(i1), arr->unit); |
9cc5d6d0563e
Add more cast for old gcc and other cc
David Demelier <markand@malikania.fr>
parents:
62
diff
changeset
|
218 memcpy((char *)arr->data + OFFSET(i1), (char *)arr->data + OFFSET(i2), |
62 | 219 arr->unit); |
64
9cc5d6d0563e
Add more cast for old gcc and other cc
David Demelier <markand@malikania.fr>
parents:
62
diff
changeset
|
220 memcpy((char *)arr->data + OFFSET(i2), (char *)tmp, arr->unit); |
62 | 221 |
222 /* | |
223 * Clear bytes for safety you probably don't want a password or | |
224 * secure data to be left somewhere in the memory. | |
225 */ | |
226 | |
136 | 227 if (arr->flags & ARRAY_CLEARBITS) |
228 memset(tmp, 0, arr->unit); | |
62 | 229 free(tmp); |
230 | |
231 return 0; | |
232 } | |
233 | |
234 /* | |
235 * Swap the two elements referenced by data `o1' and `o2'. This function | |
236 * may be slow on large arrays since it must travel all the object | |
237 * to find the indexes. | |
238 */ | |
239 int | |
240 array_pswap(struct array *arr, const void *o1, const void *o2) | |
241 { | |
242 int found, i1, i2; | |
243 | |
244 for (i1 = found = 0; !found && i1 < arr->length; ++i1) | |
64
9cc5d6d0563e
Add more cast for old gcc and other cc
David Demelier <markand@malikania.fr>
parents:
62
diff
changeset
|
245 found = memcmp((char *)arr->data + OFFSET(i1), o1, arr->unit) == 0; |
62 | 246 |
247 if (!found) | |
248 return -1; | |
249 | |
250 for (i2 = found = 0; !found && i2 < arr->length; ++i2) | |
64
9cc5d6d0563e
Add more cast for old gcc and other cc
David Demelier <markand@malikania.fr>
parents:
62
diff
changeset
|
251 found = memcmp((char *)arr->data + OFFSET(i2), o2, arr->unit) == 0; |
62 | 252 |
253 if (!found) | |
254 return -1; | |
255 | |
256 return array_iswap(arr, --i1, --i2); | |
257 } | |
258 | |
259 /* | |
260 * Apply the function `fn' on each object and give the optional `udata' | |
261 * argument to the function too. | |
262 */ | |
263 void | |
142
e3cf5ac9a5aa
[p]array_insert now returns -1 or index of added element
David Demelier <markand@malikania.fr>
parents:
136
diff
changeset
|
264 array_map(const struct array *arr, array_map_t fn, void *udata) |
62 | 265 { |
266 int i; | |
267 | |
268 for (i = 0; i < arr->length; ++i) | |
64
9cc5d6d0563e
Add more cast for old gcc and other cc
David Demelier <markand@malikania.fr>
parents:
62
diff
changeset
|
269 fn((char *)arr->data + OFFSET(i), udata); |
62 | 270 } |
271 | |
272 /* | |
163
66d317ba4b80
Added a new _qsort function for array and parray
David Demelier <markand@malikania.fr>
parents:
159
diff
changeset
|
273 * Call qsort function to sort the array. |
66d317ba4b80
Added a new _qsort function for array and parray
David Demelier <markand@malikania.fr>
parents:
159
diff
changeset
|
274 */ |
66d317ba4b80
Added a new _qsort function for array and parray
David Demelier <markand@malikania.fr>
parents:
159
diff
changeset
|
275 void |
66d317ba4b80
Added a new _qsort function for array and parray
David Demelier <markand@malikania.fr>
parents:
159
diff
changeset
|
276 array_sort(struct array *arr, array_cmp_t fn) |
66d317ba4b80
Added a new _qsort function for array and parray
David Demelier <markand@malikania.fr>
parents:
159
diff
changeset
|
277 { |
66d317ba4b80
Added a new _qsort function for array and parray
David Demelier <markand@malikania.fr>
parents:
159
diff
changeset
|
278 qsort(arr->data, arr->length, arr->unit, fn); |
66d317ba4b80
Added a new _qsort function for array and parray
David Demelier <markand@malikania.fr>
parents:
159
diff
changeset
|
279 } |
66d317ba4b80
Added a new _qsort function for array and parray
David Demelier <markand@malikania.fr>
parents:
159
diff
changeset
|
280 |
66d317ba4b80
Added a new _qsort function for array and parray
David Demelier <markand@malikania.fr>
parents:
159
diff
changeset
|
281 /* |
62 | 282 * Compare each object with the user supplied function. If the `fn' function |
106
06c968b92090
Use pointer to pointer in array_find, better to reuse
David Demelier <markand@malikania.fr>
parents:
99
diff
changeset
|
283 * returns 1, 1 is returned and dst points to the correct object, dst should |
06c968b92090
Use pointer to pointer in array_find, better to reuse
David Demelier <markand@malikania.fr>
parents:
99
diff
changeset
|
284 * be a pointer to a pointer of object, like (int **) for a array of int. |
62 | 285 */ |
67
cff6869fbc94
Modified [p]array_find to return the index for a better usage
David Demelier <markand@malikania.fr>
parents:
64
diff
changeset
|
286 int |
142
e3cf5ac9a5aa
[p]array_insert now returns -1 or index of added element
David Demelier <markand@malikania.fr>
parents:
136
diff
changeset
|
287 array_find(const struct array *arr, array_cmp_t fn, void *dst, void *u) |
62 | 288 { |
289 int st, i; | |
290 | |
120 | 291 for (i = st = 0; i < arr->length && st != 1; ++i) |
64
9cc5d6d0563e
Add more cast for old gcc and other cc
David Demelier <markand@malikania.fr>
parents:
62
diff
changeset
|
292 st = fn((char *)arr->data + OFFSET(i), u); |
62 | 293 |
120 | 294 if (st && dst) |
295 *(char **)dst = (char *)arr->data + OFFSET(i - 1); | |
62 | 296 |
120 | 297 return (st) ? i - 1 : -1; |
62 | 298 } |
299 | |
136 | 300 void * |
301 array_first(const struct array *arr) | |
302 { | |
303 return arr->data; | |
304 } | |
305 | |
306 void * | |
307 array_last(const struct array *arr) | |
308 { | |
309 if (arr->length == 0) | |
310 return array_first(arr); | |
311 | |
312 return (char *)arr->data + OFFSET(arr->length - 1); | |
313 | |
314 } | |
315 | |
316 void * | |
163
66d317ba4b80
Added a new _qsort function for array and parray
David Demelier <markand@malikania.fr>
parents:
159
diff
changeset
|
317 array_get(const struct array *arr, int idx) |
136 | 318 { |
319 if (idx < 0) | |
320 return array_first(arr); | |
321 if (idx >= arr->length) | |
322 return array_last(arr); | |
323 | |
324 return (char *)arr->data + OFFSET(idx); | |
325 } | |
326 | |
62 | 327 /* |
328 * Erase every bytes and set the length to 0. | |
329 */ | |
330 void | |
331 array_clear(struct array *arr) | |
332 { | |
159
94847374833b
Fix array.c for _clear
David Demelier <markand@malikania.fr>
parents:
147
diff
changeset
|
333 memset(arr->data, 0, arr->size); |
62 | 334 arr->length = 0; |
335 } | |
336 | |
337 /* | |
338 * Same as array_clear except it also free the array object. | |
339 */ | |
340 void | |
341 array_free(struct array *arr) | |
342 { | |
136 | 343 array_clear(arr); |
109
4efd3873a457
Remove useless bits in _free()
David Demelier <markand@malikania.fr>
parents:
106
diff
changeset
|
344 free(arr->data); |
136 | 345 |
346 arr->data = NULL; | |
347 arr->size = 0; | |
62 | 348 } |
349 | |
350 /* | |
351 * Increate the array storage when it is full. If the buffer is fixed size | |
352 * it returns -1 on full buffer otherwise 0 is returned if allocation | |
353 * succeeded. | |
354 */ | |
355 static int | |
124
5917096facb9
Use enum and add #ifdef __cplusplus
David Demelier <markand@malikania.fr>
parents:
123
diff
changeset
|
356 grow(struct array *arr) |
62 | 357 { |
136 | 358 if ((arr->size / arr->unit) > (size_t)arr->length) |
62 | 359 return 0; |
360 | |
136 | 361 if (!(arr->flags & ARRAY_FIXED)) { |
91
b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
David Demelier <markand@malikania.fr>
parents:
67
diff
changeset
|
362 if ((arr->data = arr->realloc(arr->data, arr->size + |
163
66d317ba4b80
Added a new _qsort function for array and parray
David Demelier <markand@malikania.fr>
parents:
159
diff
changeset
|
363 OFFSET(arr->chksize))) == NULL) { |
136 | 364 arr->size = arr->length = 0; |
62 | 365 return -1; |
136 | 366 } |
62 | 367 |
163
66d317ba4b80
Added a new _qsort function for array and parray
David Demelier <markand@malikania.fr>
parents:
159
diff
changeset
|
368 arr->size += OFFSET(arr->chksize); |
62 | 369 } else |
370 return -1; | |
371 | |
372 return 0; | |
373 } |