Anope IRC Services  Version 1.8
slist.c
Go to the documentation of this file.
1 /* Services list handler implementation.
2  *
3  * (C) 2003-2014 Anope Team
4  * Contact us at team@anope.org
5  *
6  * Please read COPYING and README for further details.
7  *
8  * Based on the original code of Epona by Lara.
9  * Based on the original code of Services by Andy Church.
10  *
11  *
12  */
13 
14 #include "services.h"
15 #include "slist.h"
16 
17 static SListOpts slist_defopts = { 0, NULL, NULL, NULL };
18 
19 /*************************************************************************/
20 
29 int slist_add(SList * slist, void *item)
30 {
31  if (slist->limit != 0 && slist->count >= slist->limit)
32  return -2;
33  if (slist->opts && (slist->opts->flags & SLISTF_NODUP)
34  && slist_indexof(slist, item) != -1)
35  return -3;
36  if (slist->capacity == slist->count)
37  slist_setcapacity(slist, slist->capacity + 1);
38 
39  if (slist->opts && (slist->opts->flags & SLISTF_SORT)
40  && slist->opts->compareitem) {
41  int i;
42 
43  for (i = 0; i < slist->count; i++) {
44  if (slist->opts->compareitem(slist, item, slist->list[i]) <= 0) {
45  memmove(&slist->list[i + 1], &slist->list[i],
46  sizeof(void *) * (slist->count - i));
47  slist->list[i] = item;
48  break;
49  }
50  }
51 
52  if (i == slist->count)
53  slist->list[slist->count] = item;
54  } else {
55  slist->list[slist->count] = item;
56  }
57 
58  return slist->count++;
59 }
60 
61 /*************************************************************************/
62 
70 void slist_clear(SList * slist, int mustfree)
71 {
72  if (mustfree && slist->opts && slist->opts->freeitem && slist->count) {
73  int i;
74 
75  for (i = 0; i < slist->count; i++)
76  if (slist->list[i])
77  slist->opts->freeitem(slist, slist->list[i]);
78  }
79 
80  if (slist->list) {
81  free(slist->list);
82  slist->list = NULL;
83  }
84  slist->capacity = 0;
85  slist->count = 0;
86 }
87 
88 /*************************************************************************/
89 
97 int slist_delete(SList * slist, int index)
98 {
99  /* Range check */
100  if (index >= slist->count)
101  return 0;
102 
103  if (slist->list[index] && slist->opts && slist->opts->freeitem)
104  slist->opts->freeitem(slist, slist->list[index]);
105 
106  slist->list[index] = NULL;
107  slist->count--;
108 
109  if (index < slist->count)
110  memmove(&slist->list[index], &slist->list[index + 1],
111  sizeof(void *) * (slist->count - index));
112 
113  slist_setcapacity(slist, slist->capacity - 1);
114 
115  return 1;
116 }
117 
118 /*************************************************************************/
119 
129 int slist_delete_range(SList * slist, char *range, slist_delcheckcb_t cb,
130  ...)
131 {
132  int count = 0, i, n1, n2;
133  va_list args, preserve;
134 
135  va_start(args, cb);
136 
137  for (;;) {
138  n1 = n2 = strtol(range, (char **) &range, 10);
139  range += strcspn(range, "0123456789,-");
140 
141  if (*range == '-') {
142  range++;
143  range += strcspn(range, "0123456789,");
144  if (isdigit(*range)) {
145  n2 = strtol(range, (char **) &range, 10);
146  range += strcspn(range, "0123456789,-");
147  }
148  }
149 
150  for (i = n1; i <= n2 && i > 0 && i <= slist->count; i++) {
151 
152  if (!slist->list[i - 1])
153  continue;
154 
155  /* copy this off the stack for safety's sake --nenolod */
156  VA_COPY(preserve, args);
157 
158  if (cb && !cb(slist, slist->list[i - 1], preserve)) {
159  va_end(preserve);
160  return -1;
161  }
162 
163  /* if it's to be freed, lets free it */
164  if (slist->opts && slist->opts->freeitem)
165  slist->opts->freeitem(slist, slist->list[i - 1]);
166  slist->list[i - 1] = NULL;
167 
168  /* and release the copied list */
169  va_end(preserve);
170 
171  count++;
172  }
173 
174  range += strcspn(range, ",");
175  if (*range)
176  range++;
177  else
178  break;
179  }
180 
181  /* We only really delete the items from the list after having processed
182  * everything because it would change the position of the items in the
183  * list otherwise.
184  */
185  slist_pack(slist);
186 
187  va_end(args);
188  return count;
189 }
190 
191 /*************************************************************************/
192 
203 int slist_enum(SList * slist, char *range, slist_enumcb_t cb, ...)
204 {
205  int count = 0, i, res;
206  va_list args, preserve;
207 
208  va_start(args, cb);
209 
210  if (!range) {
211  for (i = 0; i < slist->count; i++) {
212  if (!slist->list[i]) {
213  alog("SList: warning: NULL pointer in the list (?)");
214  continue;
215  }
216 
217  /* copy off stack for safety */
218  VA_COPY(preserve, args);
219 
220  res = cb(slist, i + 1, slist->list[i], preserve);
221  if (res < 0) {
222  va_end(preserve);
223  break;
224  }
225 
226  /* and release our copy */
227  va_end(preserve);
228 
229  count += res;
230  }
231  } else {
232  int n1, n2;
233 
234  for (;;) {
235  res = 0;
236  n1 = n2 = strtol(range, (char **) &range, 10);
237  range += strcspn(range, "0123456789,-");
238  if (*range == '-') {
239  range++;
240  range += strcspn(range, "0123456789,");
241  if (isdigit(*range)) {
242  n2 = strtol(range, (char **) &range, 10);
243  range += strcspn(range, "0123456789,-");
244  }
245  }
246  for (i = n1; i <= n2 && i > 0 && i <= slist->count; i++) {
247  if (!slist->list[i - 1]) {
248  alog("SList: warning: NULL pointer in the list (?)");
249  continue;
250  }
251 
252  /* copy off stack for safety */
253  VA_COPY(preserve, args);
254 
255  res = cb(slist, i, slist->list[i - 1], preserve);
256  if (res < 0) {
257  va_end(preserve);
258  break;
259  }
260  count += res;
261 
262  /* and release our copy */
263  va_end(preserve);
264  }
265  if (res < -1)
266  break;
267  range += strcspn(range, ",");
268  if (*range)
269  range++;
270  else
271  break;
272  }
273  }
274 
275  va_end(args);
276 
277  return count;
278 }
279 
280 /*************************************************************************/
281 
287 int slist_full(SList * slist)
288 {
289  if (slist->limit != 0 && slist->count >= slist->limit)
290  return 1;
291  else
292  return 0;
293 }
294 
295 /*************************************************************************/
296 
302 void slist_init(SList * slist)
303 {
304  memset(slist, 0, sizeof(SList));
305  slist->limit = SLIST_DEFAULT_LIMIT;
306  slist->opts = &slist_defopts;
307 }
308 
309 /*************************************************************************/
310 
317 int slist_indexof(SList * slist, void *item)
318 {
319  int16 i;
320  void *entry;
321 
322  if (slist->count == 0)
323  return -1;
324 
325  for (i = 0; i < slist->count; i++) {
326  entry = slist->list[i];
327  if ((slist->opts
328  && slist->opts->isequal) ? (slist->opts->isequal(slist, item,
329  entry))
330  : (item == entry))
331  return i;
332  }
333 
334  return -1;
335 }
336 
337 /*************************************************************************/
338 
344 void slist_pack(SList * slist)
345 {
346  int i;
347 
348  for (i = slist->count - 1; i >= 0; i--)
349  if (!slist->list[i])
350  slist_delete(slist, i);
351 }
352 
353 /*************************************************************************/
354 
362 int slist_remove(SList * slist, void *item)
363 {
364  int index = slist_indexof(slist, item);
365  if (index == -1)
366  return -1;
367  slist_delete(slist, index);
368  return index;
369 }
370 
371 /*************************************************************************/
372 
379 int slist_setcapacity(SList * slist, int16 capacity)
380 {
381  if (slist->capacity == capacity)
382  return 1;
383  slist->capacity = capacity;
384  if (slist->capacity)
385  slist->list =
386  srealloc(slist->list, sizeof(void *) * slist->capacity);
387  else {
388  free(slist->list);
389  slist->list = NULL;
390  }
391  if (slist->capacity < slist->count)
392  slist->count = slist->capacity;
393  return 1;
394 }
#define VA_COPY(DEST, SRC)
Definition: services.h:153
int slist_enum(SList *slist, char *range, slist_enumcb_t cb,...)
Definition: slist.c:203
void slist_clear(SList *slist, int mustfree)
Definition: slist.c:70
void slist_pack(SList *slist)
Definition: slist.c:344
int slist_full(SList *slist)
Definition: slist.c:287
#define SLIST_DEFAULT_LIMIT
Definition: slist.h:38
int(* isequal)(SList *slist, void *item1, void *item2)
Definition: slist.h:34
SListOpts * opts
Definition: slist.h:27
int slist_indexof(SList *slist, void *item)
Definition: slist.c:317
void ** list
Definition: slist.h:21
int16 limit
Definition: slist.h:25
int16 count
Definition: slist.h:23
int(* slist_enumcb_t)(SList *slist, int number, void *item, va_list args)
Definition: slist.h:44
int slist_remove(SList *slist, void *item)
Definition: slist.c:362
int slist_setcapacity(SList *slist, int16 capacity)
Definition: slist.c:379
int32 flags
Definition: slist.h:31
static SListOpts slist_defopts
Definition: slist.c:17
E void alog(const char *fmt,...) FORMAT(printf
int16_t int16
Definition: db-merger.c:120
void slist_init(SList *slist)
Definition: slist.c:302
Definition: slist.h:20
int(* slist_delcheckcb_t)(SList *slist, void *item, va_list args)
Definition: slist.h:46
#define SLISTF_NODUP
Definition: slist.h:40
int slist_delete(SList *slist, int index)
Definition: slist.c:97
E void * srealloc(void *oldptr, long newsize)
Definition: memory.c:80
void(* freeitem)(SList *slist, void *item)
Definition: slist.h:35
int16 capacity
Definition: slist.h:24
int(* compareitem)(SList *slist, void *item1, void *item2)
Definition: slist.h:33
#define SLISTF_SORT
Definition: slist.h:41
int slist_delete_range(SList *slist, char *range, slist_delcheckcb_t cb,...)
Definition: slist.c:129
int slist_add(SList *slist, void *item)
Definition: slist.c:29