]> git.ipfire.org Git - people/ms/libloc.git/blobdiff - src/as-list.c
importer: Drop EDROP as it has been merged into DROP
[people/ms/libloc.git] / src / as-list.c
index 7c69eb02e4d1cd1724744904a3d0cd8fc421543d..50805e771b2d7c09ada7bf94b93bf511b1c4ad7e 100644 (file)
        Lesser General Public License for more details.
 */
 
-#include <errno.h>
 #include <stdlib.h>
 
-#include <loc/as.h>
-#include <loc/as-list.h>
-#include <loc/private.h>
+#include <libloc/as.h>
+#include <libloc/as-list.h>
+#include <libloc/compat.h>
+#include <libloc/private.h>
 
 struct loc_as_list {
        struct loc_ctx* ctx;
        int refcount;
 
-       struct loc_as* list[1024];
+       struct loc_as** elements;
+       size_t elements_size;
+
        size_t size;
-       size_t max_size;
 };
 
+static int loc_as_list_grow(struct loc_as_list* list) {
+       size_t size = list->elements_size * 2;
+       if (size < 1024)
+               size = 1024;
+
+       DEBUG(list->ctx, "Growing AS list %p by %zu to %zu\n",
+               list, size, list->elements_size + size);
+
+       struct loc_as** elements = reallocarray(list->elements,
+                       list->elements_size + size, sizeof(*list->elements));
+       if (!elements)
+               return 1;
+
+       list->elements = elements;
+       list->elements_size += size;
+
+       return 0;
+}
+
 LOC_EXPORT int loc_as_list_new(struct loc_ctx* ctx,
                struct loc_as_list** list) {
        struct loc_as_list* l = calloc(1, sizeof(*l));
        if (!l)
-               return -ENOMEM;
+               return 1;
 
        l->ctx = loc_ref(ctx);
        l->refcount = 1;
 
-       // Do not allow this list to grow larger than this
-       l->max_size = 1024;
-
        DEBUG(l->ctx, "AS list allocated at %p\n", l);
        *list = l;
 
@@ -83,8 +100,17 @@ LOC_EXPORT int loc_as_list_empty(struct loc_as_list* list) {
 }
 
 LOC_EXPORT void loc_as_list_clear(struct loc_as_list* list) {
+       if (!list->elements)
+               return;
+
        for (unsigned int i = 0; i < list->size; i++)
-               loc_as_unref(list->list[i]);
+               loc_as_unref(list->elements[i]);
+
+       free(list->elements);
+       list->elements = NULL;
+       list->elements_size = 0;
+
+       list->size = 0;
 }
 
 LOC_EXPORT struct loc_as* loc_as_list_get(struct loc_as_list* list, size_t index) {
@@ -92,7 +118,7 @@ LOC_EXPORT struct loc_as* loc_as_list_get(struct loc_as_list* list, size_t index
        if (index >= list->size)
                return NULL;
 
-       return loc_as_ref(list->list[index]);
+       return loc_as_ref(list->elements[index]);
 }
 
 LOC_EXPORT int loc_as_list_append(
@@ -101,14 +127,15 @@ LOC_EXPORT int loc_as_list_append(
                return 0;
 
        // Check if we have space left
-       if (list->size == list->max_size) {
-               ERROR(list->ctx, "%p: Could not append AS to the list. List full\n", list);
-               return -ENOMEM;
+       if (list->size >= list->elements_size) {
+               int r = loc_as_list_grow(list);
+               if (r)
+                       return r;
        }
 
        DEBUG(list->ctx, "%p: Appending AS %p to list\n", list, as);
 
-       list->list[list->size++] = loc_as_ref(as);
+       list->elements[list->size++] = loc_as_ref(as);
 
        return 0;
 }
@@ -116,7 +143,7 @@ LOC_EXPORT int loc_as_list_append(
 LOC_EXPORT int loc_as_list_contains(
                struct loc_as_list* list, struct loc_as* as) {
        for (unsigned int i = 0; i < list->size; i++) {
-               if (loc_as_cmp(as, list->list[i]) == 0)
+               if (loc_as_cmp(as, list->elements[i]) == 0)
                        return 1;
        }
 
@@ -136,3 +163,12 @@ LOC_EXPORT int loc_as_list_contains_number(
 
        return r;
 }
+
+static int __loc_as_cmp(const void* as1, const void* as2) {
+       return loc_as_cmp(*(struct loc_as**)as1, *(struct loc_as**)as2);
+}
+
+LOC_EXPORT void loc_as_list_sort(struct loc_as_list* list) {
+       // Sort everything
+       qsort(list->elements, list->size, sizeof(*list->elements), __loc_as_cmp);
+}