summaryrefslogtreecommitdiff
path: root/slist.c
diff options
context:
space:
mode:
Diffstat (limited to 'slist.c')
-rw-r--r--slist.c325
1 files changed, 325 insertions, 0 deletions
diff --git a/slist.c b/slist.c
new file mode 100644
index 000000000..7d41a0d71
--- /dev/null
+++ b/slist.c
@@ -0,0 +1,325 @@
+/* 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: slist.c,v 1.6 2003/07/20 01:15:50 dane Exp $
+ *
+ */
+
+#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;
+}