1 /*
2 * Copyright 2001-2004 Brandon Long
3 * All Rights Reserved.
4 *
5 * ClearSilver Templating System
6 *
7 * This code is made available under the terms of the ClearSilver License.
8 * http://www.clearsilver.net/license.hdf
9 *
10 */
11
12 #include "cs_config.h"
13
14 #include <stdlib.h>
15 #include <string.h>
16 #include <errno.h>
17
18 #include "neo_misc.h"
19 #include "neo_err.h"
20 #include "ulist.h"
21
22 #define ULIST_DEFAULT_SIZE 10
23
check_resize(ULIST * ul,int size)24 static NEOERR *check_resize (ULIST *ul, int size)
25 {
26 if (size > ul->max)
27 {
28 void **new_items;
29 int new_size = 0;
30
31 new_size = ul->max*2;
32 if (size > new_size)
33 {
34 new_size = size + ul->max;
35 }
36
37 new_items = (void **) realloc ((void *)(ul->items), new_size * sizeof(void *));
38 if (new_items == NULL)
39 {
40 return nerr_raise(NERR_NOMEM,
41 "Unable to resize ULIST to %d: Out of memory", new_size);
42 }
43 ul->items = new_items;
44 ul->max = new_size;
45 }
46
47 return STATUS_OK;
48 }
49
50
uListInit(ULIST ** ul,int size,int flags)51 NEOERR *uListInit(ULIST **ul, int size, int flags)
52 {
53 ULIST *r_ul;
54
55 *ul = NULL;
56 if (size == 0)
57 {
58 size = ULIST_DEFAULT_SIZE;
59 }
60
61 r_ul = (ULIST *) calloc (1, sizeof (ULIST));
62 if (r_ul == NULL)
63 {
64 return nerr_raise(NERR_NOMEM, "Unable to create ULIST: Out of memory");
65 }
66 r_ul->items = (void **) calloc (size, sizeof(void *));
67 if (r_ul->items == NULL)
68 {
69 free (r_ul);
70 return nerr_raise(NERR_NOMEM, "Unable to create ULIST: Out of memory");
71 }
72
73 r_ul->num = 0;
74 r_ul->max = size;
75 r_ul->flags = flags;
76 *ul = r_ul;
77
78 return STATUS_OK;
79 }
80
uListvInit(ULIST ** ul,...)81 NEOERR *uListvInit(ULIST **ul, ...)
82 {
83 NEOERR *err;
84 va_list ap;
85 void *it;
86
87 err = uListInit (ul, 0, 0);
88 if (err) return nerr_pass (err);
89
90 va_start (ap, ul);
91
92 it = va_arg (ap, void *);
93
94 while (it)
95 {
96 err = uListAppend (*ul, it);
97 if (err)
98 {
99 uListDestroy(ul, 0);
100 return nerr_pass (err);
101 }
102 it = va_arg (ap, void *);
103 }
104 return STATUS_OK;
105 }
106
uListAppend(ULIST * ul,void * data)107 NEOERR *uListAppend (ULIST *ul, void *data)
108 {
109 NEOERR *r;
110
111 r = check_resize (ul, ul->num + 1);
112 if (r != STATUS_OK)
113 return r;
114
115 ul->items[ul->num] = data;
116 ul->num++;
117
118 return STATUS_OK;
119 }
120
uListPop(ULIST * ul,void ** data)121 NEOERR *uListPop (ULIST *ul, void **data)
122 {
123 if (ul->num == 0)
124 return nerr_raise(NERR_OUTOFRANGE, "uListPop: empty list");
125
126 *data = ul->items[ul->num - 1];
127 ul->num--;
128
129 return STATUS_OK;
130 }
131
uListInsert(ULIST * ul,int x,void * data)132 NEOERR *uListInsert (ULIST *ul, int x, void *data)
133 {
134 void **start;
135 NEOERR *r;
136
137 if (x < 0)
138 x = ul->num + x;
139
140 if (x >= ul->num)
141 return nerr_raise(NERR_OUTOFRANGE, "uListInsert: past end (%d > %d)",
142 x, ul->num);
143
144 r = check_resize (ul, ul->num + 1);
145 if (r != STATUS_OK)
146 return r;
147
148 start = &(ul->items[x]);
149 memmove (start + 1, start, (ul->num - x) * sizeof(void *));
150 ul->items[x] = data;
151 ++ul->num;
152
153 return STATUS_OK;
154 }
155
uListDelete(ULIST * ul,int x,void ** data)156 NEOERR *uListDelete (ULIST *ul, int x, void **data)
157 {
158 void **start;
159
160 if (x < 0)
161 x = ul->num + x;
162
163 if (x >= ul->num)
164 return nerr_raise(NERR_OUTOFRANGE, "uListDelete: past end (%d > %d)",
165 x, ul->num);
166
167 if (data != NULL)
168 *data = ul->items[x];
169
170 start = &(ul->items[x]);
171 memmove (start, start+1, (ul->num - x - 1) * sizeof(void *));
172 --ul->num;
173
174 return STATUS_OK;
175 }
176
uListGet(ULIST * ul,int x,void ** data)177 NEOERR *uListGet (ULIST *ul, int x, void **data)
178 {
179 if (x < 0)
180 x = ul->num + x;
181
182 if (x >= ul->num)
183 return nerr_raise(NERR_OUTOFRANGE, "uListGet: past end (%d > %d)",
184 x, ul->num);
185
186 if (x < 0)
187 return nerr_raise(NERR_OUTOFRANGE, "uListGet: past beginning (%d < 0)", x);
188
189 *data = ul->items[x];
190
191 return STATUS_OK;
192 }
193
uListSet(ULIST * ul,int x,void * data)194 NEOERR *uListSet (ULIST *ul, int x, void *data)
195 {
196 if (x >= ul->num)
197 return nerr_raise(NERR_OUTOFRANGE, "uListSet: past end (%d > %d)",
198 x, ul->num);
199
200 ul->items[x] = data;
201
202 return STATUS_OK;
203 }
204
uListReverse(ULIST * ul)205 NEOERR *uListReverse (ULIST *ul)
206 {
207 int i;
208
209 for (i = 0; i < ul->num/2; ++i) {
210 void *tmp = ul->items[i];
211 ul->items[i] = ul->items[ul->num-1-i];
212 ul->items[ul->num-1-i] = tmp;
213 }
214
215 return STATUS_OK;
216 }
217
uListSort(ULIST * ul,int (* compareFunc)(const void *,const void *))218 NEOERR *uListSort (ULIST *ul, int (*compareFunc)(const void *, const void*)) {
219 qsort(ul->items, ul->num, sizeof(void *), compareFunc);
220 return STATUS_OK;
221 }
222
uListSearch(ULIST * ul,const void * key,int (* compareFunc)(const void *,const void *))223 void *uListSearch (ULIST *ul, const void *key, int
224 (*compareFunc)(const void *, const void*)) {
225 return bsearch(key, ul->items, ul->num, sizeof(void *), compareFunc);
226 }
227
uListIn(ULIST * ul,const void * key,int (* compareFunc)(const void *,const void *))228 void *uListIn (ULIST *ul, const void *key, int (*compareFunc)(const void *, const void*)) {
229 int i;
230
231 for (i = 0; i < ul->num; ++i) {
232 if (!compareFunc(key, &ul->items[i])) {
233 return &ul->items[i];
234 }
235 }
236 return NULL;
237 }
238
uListIndex(ULIST * ul,const void * key,int (* compareFunc)(const void *,const void *))239 int uListIndex (ULIST *ul, const void *key, int (*compareFunc)(const void *, const void*)) {
240 void **p = uListIn(ul, key, compareFunc);
241 return p ? (p - ul->items) : -1;
242 }
243
244
245
uListDestroy(ULIST ** ul,int flags)246 NEOERR *uListDestroy (ULIST **ul, int flags)
247 {
248 if (flags & ULIST_FREE)
249 {
250 return uListDestroyFunc(ul, free);
251 }
252 else
253 {
254 return uListDestroyFunc(ul, NULL);
255 }
256 }
257
uListDestroyFunc(ULIST ** ul,void (* destroyFunc)(void *))258 NEOERR *uListDestroyFunc (ULIST **ul, void (*destroyFunc)(void *))
259 {
260 ULIST *r_ul;
261
262 r_ul = *ul;
263
264 if (r_ul == NULL)
265 return STATUS_OK;
266
267 if (destroyFunc != NULL)
268 {
269 int x;
270 for (x = 0; x < r_ul->num; x++)
271 {
272 (*destroyFunc)(r_ul->items[x]);
273 }
274 }
275 free (r_ul->items);
276 free (r_ul);
277 *ul = NULL;
278
279 return STATUS_OK;
280 }
281
uListLength(ULIST * ul)282 int uListLength (ULIST *ul)
283 {
284 if (ul == NULL) return 0;
285 return ul->num;
286 }
287