]> git.ipfire.org Git - location/libloc.git/blobdiff - src/network.c
location-importer.in: skip networks with unknown country codes
[location/libloc.git] / src / network.c
index 19c387d2998cdbeba3b7fa99d6c2d9ff1bdfc4a2..a6b679c84f4e8909ff737d84fb353cf7dbe19479 100644 (file)
@@ -533,6 +533,10 @@ LOC_EXPORT int loc_network_subnets(struct loc_network* network,
                loc_network_set_asn(*subnet2, asn);
        }
 
+       // Copy flags
+       loc_network_set_flag(*subnet1, network->flags);
+       loc_network_set_flag(*subnet2, network->flags);
+
        return 0;
 }
 
@@ -679,8 +683,10 @@ LOC_EXPORT struct loc_network_list* loc_network_exclude_list(
                return NULL;
        }
 
+       off_t smallest_subnet = 0;
+
        while (!loc_network_list_empty(to_check)) {
-               struct loc_network* subnet_to_check = loc_network_list_pop(to_check);
+               struct loc_network* subnet_to_check = loc_network_list_pop_first(to_check);
 
                // Check whether the subnet to check is part of the input list
                if (loc_network_list_contains(list, subnet_to_check)) {
@@ -691,18 +697,18 @@ LOC_EXPORT struct loc_network_list* loc_network_exclude_list(
                // Marks whether this subnet passed all checks
                int passed = 1;
 
-               for (unsigned int i = 0; i < loc_network_list_size(list); i++) {
+               for (unsigned int i = smallest_subnet; i < loc_network_list_size(list); i++) {
                        subnet = loc_network_list_get(list, i);
 
                        // Drop this subnet if is a subnet of another subnet
-                       if (loc_network_is_subnet(subnet_to_check, subnet)) {
+                       if (loc_network_is_subnet(subnet, subnet_to_check)) {
                                passed = 0;
                                loc_network_unref(subnet);
                                break;
                        }
 
                        // Break it down if it overlaps
-                       if (loc_network_overlaps(subnet_to_check, subnet)) {
+                       if (loc_network_overlaps(subnet, subnet_to_check)) {
                                passed = 0;
 
                                __loc_network_exclude_to_list(subnet_to_check, subnet, to_check);
@@ -711,6 +717,19 @@ LOC_EXPORT struct loc_network_list* loc_network_exclude_list(
                                break;
                        }
 
+                       // If the subnet is strictly greater, we do not need to continue the search
+                       r = loc_network_cmp(subnet, subnet_to_check);
+                       if (r > 0) {
+                               loc_network_unref(subnet);
+                               break;
+
+                       // If it is strictly smaller, we can continue the search from here next
+                       // time because all networks that are to be checked can only be larger
+                       // than this one.
+                       } else if (r < 0) {
+                               smallest_subnet = i;
+                       }
+
                        loc_network_unref(subnet);
                }
 
@@ -723,9 +742,6 @@ LOC_EXPORT struct loc_network_list* loc_network_exclude_list(
 
        loc_network_list_unref(to_check);
 
-       // Sort the result
-       loc_network_list_sort(subnets);
-
        return subnets;
 }