]> git.ipfire.org Git - people/ms/libloc.git/blobdiff - src/network-list.c
importer: Refactor feed parsing
[people/ms/libloc.git] / src / network-list.c
index 095d82f8988dbe98e43f2430af3b03d4daa364ab..bca44221c011ec881bc9c95d242057add83f2fa8 100644 (file)
@@ -33,14 +33,18 @@ struct loc_network_list {
        size_t size;
 };
 
-static int loc_network_list_grow(struct loc_network_list* list, size_t size) {
+static int loc_network_list_grow(struct loc_network_list* list) {
+       size_t size = list->elements_size * 2;
+       if (size < 1024)
+               size = 1024;
+
        DEBUG(list->ctx, "Growing network list %p by %zu to %zu\n",
                list, size, list->elements_size + size);
 
        struct loc_network** elements = reallocarray(list->elements,
                        list->elements_size + size, sizeof(*list->elements));
        if (!elements)
-               return -errno;
+               return 1;
 
        list->elements = elements;
        list->elements_size += size;
@@ -79,9 +83,6 @@ static void loc_network_list_free(struct loc_network_list* list) {
 }
 
 LOC_EXPORT struct loc_network_list* loc_network_list_unref(struct loc_network_list* list) {
-       if (!list)
-               return NULL;
-
        if (--list->refcount > 0)
                return list;
 
@@ -113,15 +114,12 @@ LOC_EXPORT void loc_network_list_clear(struct loc_network_list* list) {
 
 LOC_EXPORT void loc_network_list_dump(struct loc_network_list* list) {
        struct loc_network* network;
-       char* s;
 
        for (unsigned int i = 0; i < list->size; i++) {
                network = list->elements[i];
 
-               s = loc_network_str(network);
-
-               INFO(list->ctx, "%4d: %s\n", i, s);
-               free(s);
+               INFO(list->ctx, "%4d: %s\n",
+                       i, loc_network_str(network));
        }
 }
 
@@ -224,7 +222,7 @@ LOC_EXPORT int loc_network_list_push(struct loc_network_list* list, struct loc_n
 
        // Check if we have space left
        if (list->size >= list->elements_size) {
-               int r = loc_network_list_grow(list, 64);
+               int r = loc_network_list_grow(list);
                if (r)
                        return r;
        }
@@ -278,6 +276,29 @@ LOC_EXPORT struct loc_network* loc_network_list_pop_first(struct loc_network_lis
        return network;
 }
 
+int loc_network_list_remove(struct loc_network_list* list, struct loc_network* network) {
+       int found = 0;
+
+       // Find the network on the list
+       off_t index = loc_network_list_find(list, network, &found);
+
+       // Nothing to do if the network wasn't found
+       if (!found)
+               return 0;
+
+       // Dereference the network at the position
+       loc_network_unref(list->elements[index]);
+
+       // Move all other elements back
+       for (unsigned int i = index; i < list->size - 1; i++)
+               list->elements[i] = list->elements[i+1];
+
+       // The list is shorter now
+       --list->size;
+
+       return 0;
+}
+
 LOC_EXPORT int loc_network_list_contains(struct loc_network_list* list, struct loc_network* network) {
        int found = 0;
 
@@ -308,6 +329,8 @@ int loc_network_list_summarize(struct loc_ctx* ctx,
                return 1;
        }
 
+       DEBUG(ctx, "Summarizing %s - %s\n", loc_address_str(first), loc_address_str(last));
+
        const int family1 = loc_address_family(first);
        const int family2 = loc_address_family(last);
 
@@ -362,13 +385,7 @@ int loc_network_list_summarize(struct loc_ctx* ctx,
                if (r)
                        return r;
 
-#ifdef ENABLE_DEBUG
-               char* n = loc_network_str(network);
-               if (n) {
-                       DEBUG(ctx, "Found network %s\n", n);
-                       free(n);
-               }
-#endif
+               DEBUG(ctx, "Found network %s\n", loc_network_str(network));
 
                // Push network on the list
                r = loc_network_list_push(*list, network);
@@ -379,8 +396,44 @@ int loc_network_list_summarize(struct loc_ctx* ctx,
 
                // The next network starts right after this one
                start = *loc_network_get_last_address(network);
+
+               // If we have reached the end of possible IP addresses, we stop
+               if (loc_address_all_ones(&start))
+                       break;
+
                loc_address_increment(&start);
        }
 
        return 0;
 }
+
+void loc_network_list_remove_with_prefix_smaller_than(
+               struct loc_network_list* list, const unsigned int prefix) {
+       unsigned int p = 0;
+
+       // Count how many networks were removed
+       unsigned int removed = 0;
+
+       for (unsigned int i = 0; i < list->size; i++) {
+               // Fetch the prefix
+               p = loc_network_prefix(list->elements[i]);
+
+               if (p > prefix) {
+                       // Drop this network
+                       loc_network_unref(list->elements[i]);
+
+                       // Increment counter
+                       removed++;
+
+                       continue;
+               }
+
+               // Move pointers backwards to keep the list filled
+               list->elements[i - removed] = list->elements[i];
+       }
+
+       // Adjust size
+       list->size -= removed;
+
+       return;
+}