• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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