slist.c

Go to the documentation of this file.
00001 /* Services list handler implementation.
00002  *
00003  * (C) 2003-2007 Anope Team
00004  * Contact us at info@anope.org
00005  *
00006  * Please read COPYING and README for further details.
00007  *
00008  * Based on the original code of Epona by Lara.
00009  * Based on the original code of Services by Andy Church. 
00010  * 
00011  * $Id: slist.c 1265 2007-08-26 15:33:06Z geniusdex $ 
00012  *
00013  */
00014 
00015 #include "services.h"
00016 #include "slist.h"
00017 
00018 static SListOpts slist_defopts = { 0, NULL, NULL, NULL };
00019 
00020 /*************************************************************************/
00021 
00030 int slist_add(SList * slist, void *item)
00031 {
00032     if (slist->limit != 0 && slist->count >= slist->limit)
00033         return -2;
00034     if (slist->opts && (slist->opts->flags & SLISTF_NODUP)
00035         && slist_indexof(slist, item) != -1)
00036         return -3;
00037     if (slist->capacity == slist->count)
00038         slist_setcapacity(slist, slist->capacity + 1);
00039 
00040     if (slist->opts && (slist->opts->flags & SLISTF_SORT)
00041         && slist->opts->compareitem) {
00042         int i;
00043 
00044         for (i = 0; i < slist->count; i++) {
00045             if (slist->opts->compareitem(slist, item, slist->list[i]) <= 0) {
00046                 memmove(&slist->list[i + 1], &slist->list[i],
00047                         sizeof(void *) * (slist->count - i));
00048                 slist->list[i] = item;
00049                 break;
00050             }
00051         }
00052 
00053         if (i == slist->count)
00054             slist->list[slist->count] = item;
00055     } else {
00056         slist->list[slist->count] = item;
00057     }
00058 
00059     return slist->count++;
00060 }
00061 
00062 /*************************************************************************/
00063 
00071 void slist_clear(SList * slist, int mustfree)
00072 {
00073     if (mustfree && slist->opts && slist->opts->freeitem && slist->count) {
00074         int i;
00075 
00076         for (i = 0; i < slist->count; i++)
00077             if (slist->list[i])
00078                 slist->opts->freeitem(slist, slist->list[i]);
00079     }
00080 
00081     if (slist->list) {
00082         free(slist->list);
00083         slist->list = NULL;
00084     }
00085     slist->capacity = 0;
00086     slist->count = 0;
00087 }
00088 
00089 /*************************************************************************/
00090 
00098 int slist_delete(SList * slist, int index)
00099 {
00100     /* Range check */
00101     if (index >= slist->count)
00102         return 0;
00103 
00104     if (slist->list[index] && slist->opts && slist->opts->freeitem)
00105         slist->opts->freeitem(slist, slist->list[index]);
00106 
00107     slist->list[index] = NULL;
00108     slist->count--;
00109 
00110     if (index < slist->count)
00111         memmove(&slist->list[index], &slist->list[index + 1],
00112                 sizeof(void *) * (slist->count - index));
00113 
00114     slist_setcapacity(slist, slist->capacity - 1);
00115 
00116     return 1;
00117 }
00118 
00119 /*************************************************************************/
00120 
00130 int slist_delete_range(SList * slist, char *range, slist_delcheckcb_t cb,
00131                        ...)
00132 {
00133     int count = 0, i, n1, n2;
00134     va_list args, preserve;
00135 
00136     va_start(args, cb);
00137 
00138     for (;;) {
00139         n1 = n2 = strtol(range, (char **) &range, 10);
00140         range += strcspn(range, "0123456789,-");
00141 
00142         if (*range == '-') {
00143             range++;
00144             range += strcspn(range, "0123456789,");
00145             if (isdigit(*range)) {
00146                 n2 = strtol(range, (char **) &range, 10);
00147                 range += strcspn(range, "0123456789,-");
00148             }
00149         }
00150 
00151         for (i = n1; i <= n2 && i > 0 && i <= slist->count; i++) {
00152 
00153             if (!slist->list[i - 1])
00154                 continue;
00155 
00156             /* copy this off the stack for safety's sake --nenolod */
00157             VA_COPY(preserve, args);
00158 
00159             if (cb && !cb(slist, slist->list[i - 1], preserve)) {
00160                 va_end(preserve);
00161                 return -1;
00162             }
00163 
00164             /* if it's to be freed, lets free it */
00165             if (slist->opts && slist->opts->freeitem)
00166                 slist->opts->freeitem(slist, slist->list[i - 1]);
00167             slist->list[i - 1] = NULL;
00168 
00169             /* and release the copied list */
00170             va_end(preserve);
00171 
00172             count++;
00173         }
00174 
00175         range += strcspn(range, ",");
00176         if (*range)
00177             range++;
00178         else
00179             break;
00180     }
00181 
00182     /* We only really delete the items from the list after having processed
00183      * everything because it would change the position of the items in the
00184      * list otherwise.
00185      */
00186     slist_pack(slist);
00187 
00188     va_end(args);
00189     return count;
00190 }
00191 
00192 /*************************************************************************/
00193 
00204 int slist_enum(SList * slist, char *range, slist_enumcb_t cb, ...)
00205 {
00206     int count = 0, i, res;
00207     va_list args, preserve;
00208 
00209     va_start(args, cb);
00210 
00211     if (!range) {
00212         for (i = 0; i < slist->count; i++) {
00213             if (!slist->list[i]) {
00214                 alog("SList: warning: NULL pointer in the list (?)");
00215                 continue;
00216             }
00217 
00218             /* copy off stack for safety */
00219             VA_COPY(preserve, args);
00220 
00221             res = cb(slist, i + 1, slist->list[i], preserve);
00222             if (res < 0) {
00223                 va_end(preserve);
00224                 break;
00225             }
00226 
00227             /* and release our copy */
00228             va_end(preserve);
00229 
00230             count += res;
00231         }
00232     } else {
00233         int n1, n2;
00234 
00235         for (;;) {
00236             res = 0;
00237             n1 = n2 = strtol(range, (char **) &range, 10);
00238             range += strcspn(range, "0123456789,-");
00239             if (*range == '-') {
00240                 range++;
00241                 range += strcspn(range, "0123456789,");
00242                 if (isdigit(*range)) {
00243                     n2 = strtol(range, (char **) &range, 10);
00244                     range += strcspn(range, "0123456789,-");
00245                 }
00246             }
00247             for (i = n1; i <= n2 && i > 0 && i <= slist->count; i++) {
00248                 if (!slist->list[i - 1]) {
00249                     alog("SList: warning: NULL pointer in the list (?)");
00250                     continue;
00251                 }
00252 
00253                 /* copy off stack for safety */
00254                 VA_COPY(preserve, args);
00255 
00256                 res = cb(slist, i, slist->list[i - 1], preserve);
00257                 if (res < 0) {
00258                     va_end(preserve);
00259                     break;
00260                 }
00261                 count += res;
00262 
00263                 /* and release our copy */
00264                 va_end(preserve);
00265             }
00266             if (res < -1)
00267                 break;
00268             range += strcspn(range, ",");
00269             if (*range)
00270                 range++;
00271             else
00272                 break;
00273         }
00274     }
00275 
00276     va_end(args);
00277 
00278     return count;
00279 }
00280 
00281 /*************************************************************************/
00282 
00288 int slist_full(SList * slist)
00289 {
00290     if (slist->limit != 0 && slist->count >= slist->limit)
00291         return 1;
00292     else
00293         return 0;
00294 }
00295 
00296 /*************************************************************************/
00297 
00303 void slist_init(SList * slist)
00304 {
00305     memset(slist, 0, sizeof(SList));
00306     slist->limit = SLIST_DEFAULT_LIMIT;
00307     slist->opts = &slist_defopts;
00308 }
00309 
00310 /*************************************************************************/
00311 
00318 int slist_indexof(SList * slist, void *item)
00319 {
00320     int16 i;
00321     void *entry;
00322 
00323     if (slist->count == 0)
00324         return -1;
00325 
00326     for (i = 0, entry = slist->list[0]; i < slist->count;
00327          i++, entry = slist->list[i]) {
00328         if ((slist->opts
00329              && slist->opts->isequal) ? (slist->opts->isequal(slist, item,
00330                                                               entry))
00331             : (item == entry))
00332             return i;
00333     }
00334 
00335     return -1;
00336 }
00337 
00338 /*************************************************************************/
00339 
00345 void slist_pack(SList * slist)
00346 {
00347     int i;
00348 
00349     for (i = slist->count - 1; i >= 0; i--)
00350         if (!slist->list[i])
00351             slist_delete(slist, i);
00352 }
00353 
00354 /*************************************************************************/
00355 
00363 int slist_remove(SList * slist, void *item)
00364 {
00365     int index = slist_indexof(slist, item);
00366     if (index == -1)
00367         return -1;
00368     slist_delete(slist, index);
00369     return index;
00370 }
00371 
00372 /*************************************************************************/
00373 
00380 int slist_setcapacity(SList * slist, int16 capacity)
00381 {
00382     if (slist->capacity == capacity)
00383         return 1;
00384     slist->capacity = capacity;
00385     if (slist->capacity)
00386         slist->list =
00387             srealloc(slist->list, sizeof(void *) * slist->capacity);
00388     else {
00389         free(slist->list);
00390         slist->list = NULL;
00391     }
00392     if (slist->capacity < slist->count)
00393         slist->count = slist->capacity;
00394     return 1;
00395 }

Generated on Sun Dec 30 09:26:53 2007 for Anope by  doxygen 1.5.1-20070107