]> git.ipfire.org Git - people/ms/libloc.git/blobdiff - src/country-list.c
importer: Drop EDROP as it has been merged into DROP
[people/ms/libloc.git] / src / country-list.c
index 1ce2d06b6ba16d92f48c2f1eb46c3da1841afcb3..536fd9e121c08ff6b98784de36b99e121647a8ba 100644 (file)
 #include <errno.h>
 #include <stdlib.h>
 
-#include <loc/country.h>
-#include <loc/country-list.h>
-#include <loc/private.h>
+#include <libloc/compat.h>
+#include <libloc/country.h>
+#include <libloc/country-list.h>
+#include <libloc/private.h>
 
 struct loc_country_list {
        struct loc_ctx* ctx;
@@ -31,14 +32,18 @@ struct loc_country_list {
        size_t size;
 };
 
-static int loc_country_list_grow(struct loc_country_list* list, size_t size) {
+static int loc_country_list_grow(struct loc_country_list* list) {
+       size_t size = list->elements_size * 2;
+       if (size < 1024)
+               size = 1024;
+
        DEBUG(list->ctx, "Growing country list %p by %zu to %zu\n",
                list, size, list->elements_size + size);
 
        struct loc_country** elements = reallocarray(list->elements,
                        list->elements_size + size, sizeof(*list->elements));
        if (!elements)
-               return -errno;
+               return 1;
 
        list->elements = elements;
        list->elements_size += size;
@@ -77,9 +82,6 @@ static void loc_country_list_free(struct loc_country_list* list) {
 }
 
 LOC_EXPORT struct loc_country_list* loc_country_list_unref(struct loc_country_list* list) {
-       if (!list)
-               return NULL;
-
        if (--list->refcount > 0)
                return list;
 
@@ -96,8 +98,17 @@ LOC_EXPORT int loc_country_list_empty(struct loc_country_list* list) {
 }
 
 LOC_EXPORT void loc_country_list_clear(struct loc_country_list* list) {
+       if (!list->elements)
+               return;
+
        for (unsigned int i = 0; i < list->size; i++)
                loc_country_unref(list->elements[i]);
+
+       free(list->elements);
+       list->elements = NULL;
+       list->elements_size = 0;
+
+       list->size = 0;
 }
 
 LOC_EXPORT struct loc_country* loc_country_list_get(struct loc_country_list* list, size_t index) {
@@ -115,7 +126,7 @@ LOC_EXPORT int loc_country_list_append(
 
        // Check if we have space left
        if (list->size >= list->elements_size) {
-               int r = loc_country_list_grow(list, 64);
+               int r = loc_country_list_grow(list);
                if (r)
                        return r;
        }
@@ -142,11 +153,25 @@ LOC_EXPORT int loc_country_list_contains_code(
        struct loc_country* country;
 
        int r = loc_country_new(list->ctx, &country, code);
-       if (r)
-               return -1;
+       if (r) {
+               // Ignore invalid country codes which would never match
+               if (errno == EINVAL)
+                       return 0;
+
+               return r;
+       }
 
        r = loc_country_list_contains(list, country);
        loc_country_unref(country);
 
        return r;
 }
+
+static int __loc_country_cmp(const void* country1, const void* country2) {
+       return loc_country_cmp(*(struct loc_country**)country1, *(struct loc_country**)country2);
+}
+
+LOC_EXPORT void loc_country_list_sort(struct loc_country_list* list) {
+       // Sort everything
+       qsort(list->elements, list->size, sizeof(*list->elements), __loc_country_cmp);
+}