mirror of
https://github.com/anope/anope.git
synced 2026-06-25 05:36:37 +02:00
811ce26663
git-svn-id: svn://svn.anope.org/anope/trunk@4 31f1291d-b8d6-0310-a050-a5561fc1590b git-svn-id: http://anope.svn.sourceforge.net/svnroot/anope/trunk@2 5417fbe8-f217-4b02-8779-1006273d7864
326 lines
8.5 KiB
C
326 lines
8.5 KiB
C
/* Services list handler implementation.
|
|
*
|
|
* (C) 2003 Anope Team
|
|
* Contact us at info@anope.org
|
|
*
|
|
* Please read COPYING and README for furhter details.
|
|
*
|
|
* Based on the original code of Epona by Lara.
|
|
* Based on the original code of Services by Andy Church.
|
|
*
|
|
* $Id$
|
|
*
|
|
*/
|
|
|
|
#include "services.h"
|
|
#include "slist.h"
|
|
|
|
static SListOpts slist_defopts = { 0, NULL, NULL, NULL };
|
|
|
|
/*************************************************************************/
|
|
|
|
/* Adds a pointer to the list. Returns the index of the new item.
|
|
Returns -2 if there are too many items in the list, -3 if the
|
|
item already exists when the flags of the list contain SLISTF_NODUP. */
|
|
|
|
int slist_add(SList * slist, void *item)
|
|
{
|
|
if (slist->limit != 0 && slist->count >= slist->limit)
|
|
return -2;
|
|
if (slist->opts && (slist->opts->flags & SLISTF_NODUP)
|
|
&& slist_indexof(slist, item) != -1)
|
|
return -3;
|
|
if (slist->capacity == slist->count)
|
|
slist_setcapacity(slist, slist->capacity + 1);
|
|
|
|
if (slist->opts && (slist->opts->flags & SLISTF_SORT)
|
|
&& slist->opts->compareitem) {
|
|
int i;
|
|
|
|
for (i = 0; i < slist->count; i++) {
|
|
if (slist->opts->compareitem(slist, item, slist->list[i]) <= 0) {
|
|
memmove(&slist->list[i + 1], &slist->list[i],
|
|
sizeof(void *) * (slist->count - i));
|
|
slist->list[i] = item;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i == slist->count)
|
|
slist->list[slist->count] = item;
|
|
} else {
|
|
slist->list[slist->count] = item;
|
|
}
|
|
|
|
return slist->count++;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
/* Clears the list. If free is 1, the freeitem function will be called
|
|
* for each item before clearing.
|
|
*/
|
|
|
|
void slist_clear(SList * slist, int mustfree)
|
|
{
|
|
if (mustfree && slist->opts && slist->opts->freeitem && slist->count) {
|
|
int i;
|
|
|
|
for (i = 0; i < slist->count; i++)
|
|
if (slist->list[i])
|
|
slist->opts->freeitem(slist, slist->list[i]);
|
|
}
|
|
|
|
if (slist->list) {
|
|
free(slist->list);
|
|
slist->list = NULL;
|
|
}
|
|
slist->capacity = 0;
|
|
slist->count = 0;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
/* Deletes an item from the list, by index. Returns 1 if successful,
|
|
0 otherwise. */
|
|
|
|
int slist_delete(SList * slist, int index)
|
|
{
|
|
/* Range check */
|
|
if (index >= slist->count)
|
|
return 0;
|
|
|
|
if (slist->list[index] && slist->opts && slist->opts->freeitem)
|
|
slist->opts->freeitem(slist, slist->list[index]);
|
|
|
|
slist->list[index] = NULL;
|
|
slist->count--;
|
|
|
|
if (index < slist->count)
|
|
memmove(&slist->list[index], &slist->list[index + 1],
|
|
sizeof(void *) * (slist->count - index));
|
|
|
|
slist_setcapacity(slist, slist->capacity - 1);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
/* Deletes a range of entries. Return -1 if the permission was denied,
|
|
* 0 if no records were deleted, or the number of records deleted
|
|
*/
|
|
|
|
int slist_delete_range(SList * slist, char *range, slist_delcheckcb_t cb,
|
|
...)
|
|
{
|
|
int count = 0, i, n1, n2;
|
|
va_list args;
|
|
|
|
va_start(args, cb);
|
|
|
|
for (;;) {
|
|
n1 = n2 = strtol(range, (char **) &range, 10);
|
|
range += strcspn(range, "0123456789,-");
|
|
|
|
if (*range == '-') {
|
|
range++;
|
|
range += strcspn(range, "0123456789,");
|
|
if (isdigit(*range)) {
|
|
n2 = strtol(range, (char **) &range, 10);
|
|
range += strcspn(range, "0123456789,-");
|
|
}
|
|
}
|
|
|
|
for (i = n1; i <= n2 && i > 0 && i <= slist->count; i++) {
|
|
if (!slist->list[i - 1])
|
|
continue;
|
|
if (cb && !cb(slist, slist->list[i - 1], args))
|
|
return -1;
|
|
|
|
if (slist->opts && slist->opts->freeitem)
|
|
slist->opts->freeitem(slist, slist->list[i - 1]);
|
|
slist->list[i - 1] = NULL;
|
|
|
|
count++;
|
|
}
|
|
|
|
range += strcspn(range, ",");
|
|
if (*range)
|
|
range++;
|
|
else
|
|
break;
|
|
}
|
|
|
|
/* We only really delete the items from the list after having processed
|
|
* everything because it would change the position of the items in the
|
|
* list otherwise.
|
|
*/
|
|
slist_pack(slist);
|
|
|
|
va_end(args);
|
|
return count;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
/* Enumerates all entries of the list. If range is not NULL, will only
|
|
* enumerate entries that are in the range. Returns the total number
|
|
* of entries enumerated.
|
|
*/
|
|
|
|
int slist_enum(SList * slist, char *range, slist_enumcb_t cb, ...)
|
|
{
|
|
int count = 0, i, res;
|
|
va_list args;
|
|
|
|
va_start(args, cb);
|
|
|
|
if (!range) {
|
|
for (i = 0; i < slist->count; i++) {
|
|
if (!slist->list[i]) {
|
|
alog("SList: warning: NULL pointer in the list (?)");
|
|
continue;
|
|
}
|
|
|
|
res = cb(slist, i + 1, slist->list[i], args);
|
|
if (res < 0)
|
|
break;
|
|
count += res;
|
|
}
|
|
} else {
|
|
int n1, n2;
|
|
|
|
for (;;) {
|
|
res = 0;
|
|
n1 = n2 = strtol(range, (char **) &range, 10);
|
|
range += strcspn(range, "0123456789,-");
|
|
if (*range == '-') {
|
|
range++;
|
|
range += strcspn(range, "0123456789,");
|
|
if (isdigit(*range)) {
|
|
n2 = strtol(range, (char **) &range, 10);
|
|
range += strcspn(range, "0123456789,-");
|
|
}
|
|
}
|
|
for (i = n1; i <= n2 && i > 0 && i <= slist->count; i++) {
|
|
if (!slist->list[i - 1]) {
|
|
alog("SList: warning: NULL pointer in the list (?)");
|
|
continue;
|
|
}
|
|
|
|
res = cb(slist, i, slist->list[i - 1], args);
|
|
if (res < 0)
|
|
break;
|
|
count += res;
|
|
}
|
|
if (res < -1)
|
|
break;
|
|
range += strcspn(range, ",");
|
|
if (*range)
|
|
range++;
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
|
|
va_end(args);
|
|
|
|
return count;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
/* Determines whether the list is full. */
|
|
|
|
int slist_full(SList * slist)
|
|
{
|
|
if (slist->limit != 0 && slist->count >= slist->limit)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
/* Initialization of the list. */
|
|
|
|
void slist_init(SList * slist)
|
|
{
|
|
memset(slist, 0, sizeof(SList));
|
|
slist->limit = SLIST_DEFAULT_LIMIT;
|
|
slist->opts = &slist_defopts;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
/* Returns the index of an item in the list, -1 if inexistant. */
|
|
|
|
int slist_indexof(SList * slist, void *item)
|
|
{
|
|
int16 i;
|
|
void *entry;
|
|
|
|
if (slist->count == 0)
|
|
return -1;
|
|
|
|
for (i = 0, entry = slist->list[0]; i < slist->count;
|
|
i++, entry = slist->list[i]) {
|
|
if ((slist->opts
|
|
&& slist->opts->isequal) ? (slist->opts->isequal(slist, item,
|
|
entry))
|
|
: (item == entry))
|
|
return i;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
/* Removes all NULL pointers from the list. */
|
|
|
|
void slist_pack(SList * slist)
|
|
{
|
|
int i;
|
|
|
|
for (i = slist->count - 1; i >= 0; i--)
|
|
if (!slist->list[i])
|
|
slist_delete(slist, i);
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
/* Removes a specific item from the list. Returns the old index of the
|
|
deleted item, or -1 if the item was not found. */
|
|
|
|
int slist_remove(SList * slist, void *item)
|
|
{
|
|
int index = slist_indexof(slist, item);
|
|
if (index == -1)
|
|
return -1;
|
|
slist_delete(slist, index);
|
|
return index;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
/* Sets the maximum capacity of the list */
|
|
|
|
int slist_setcapacity(SList * slist, int16 capacity)
|
|
{
|
|
if (slist->capacity == capacity)
|
|
return 1;
|
|
slist->capacity = capacity;
|
|
if (slist->capacity)
|
|
slist->list =
|
|
srealloc(slist->list, sizeof(void *) * slist->capacity);
|
|
else {
|
|
free(slist->list);
|
|
slist->list = NULL;
|
|
}
|
|
if (slist->capacity < slist->count)
|
|
slist->count = slist->capacity;
|
|
return 1;
|
|
}
|