]>
git.ipfire.org Git - location/libloc.git/blob - src/country-list.c
2 libloc - A library to determine the location of someone on the Internet
4 Copyright (C) 2020 IPFire Development Team <info@ipfire.org>
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
20 #include <libloc/compat.h>
21 #include <libloc/country.h>
22 #include <libloc/country-list.h>
23 #include <libloc/private.h>
25 struct loc_country_list
{
29 struct loc_country
** elements
;
35 static int loc_country_list_grow(struct loc_country_list
* list
) {
36 size_t size
= list
->elements_size
* 2;
40 DEBUG(list
->ctx
, "Growing country list %p by %zu to %zu\n",
41 list
, size
, list
->elements_size
+ size
);
43 struct loc_country
** elements
= reallocarray(list
->elements
,
44 list
->elements_size
+ size
, sizeof(*list
->elements
));
48 list
->elements
= elements
;
49 list
->elements_size
+= size
;
54 LOC_EXPORT
int loc_country_list_new(struct loc_ctx
* ctx
,
55 struct loc_country_list
** list
) {
56 struct loc_country_list
* l
= calloc(1, sizeof(*l
));
60 l
->ctx
= loc_ref(ctx
);
63 DEBUG(l
->ctx
, "Country list allocated at %p\n", l
);
69 LOC_EXPORT
struct loc_country_list
* loc_country_list_ref(struct loc_country_list
* list
) {
75 static void loc_country_list_free(struct loc_country_list
* list
) {
76 DEBUG(list
->ctx
, "Releasing country list at %p\n", list
);
78 loc_country_list_clear(list
);
84 LOC_EXPORT
struct loc_country_list
* loc_country_list_unref(struct loc_country_list
* list
) {
85 if (--list
->refcount
> 0)
88 loc_country_list_free(list
);
92 LOC_EXPORT
size_t loc_country_list_size(struct loc_country_list
* list
) {
96 LOC_EXPORT
int loc_country_list_empty(struct loc_country_list
* list
) {
97 return list
->size
== 0;
100 LOC_EXPORT
void loc_country_list_clear(struct loc_country_list
* list
) {
104 for (unsigned int i
= 0; i
< list
->size
; i
++)
105 loc_country_unref(list
->elements
[i
]);
107 free(list
->elements
);
108 list
->elements
= NULL
;
109 list
->elements_size
= 0;
114 LOC_EXPORT
struct loc_country
* loc_country_list_get(struct loc_country_list
* list
, size_t index
) {
116 if (index
>= list
->size
)
119 return loc_country_ref(list
->elements
[index
]);
122 LOC_EXPORT
int loc_country_list_append(
123 struct loc_country_list
* list
, struct loc_country
* country
) {
124 if (loc_country_list_contains(list
, country
))
127 // Check if we have space left
128 if (list
->size
>= list
->elements_size
) {
129 int r
= loc_country_list_grow(list
);
134 DEBUG(list
->ctx
, "%p: Appending country %p to list\n", list
, country
);
136 list
->elements
[list
->size
++] = loc_country_ref(country
);
141 LOC_EXPORT
int loc_country_list_contains(
142 struct loc_country_list
* list
, struct loc_country
* country
) {
143 for (unsigned int i
= 0; i
< list
->size
; i
++) {
144 if (loc_country_cmp(country
, list
->elements
[i
]) == 0)
151 LOC_EXPORT
int loc_country_list_contains_code(
152 struct loc_country_list
* list
, const char* code
) {
153 struct loc_country
* country
;
155 int r
= loc_country_new(list
->ctx
, &country
, code
);
157 // Ignore invalid country codes which would never match
164 r
= loc_country_list_contains(list
, country
);
165 loc_country_unref(country
);
170 static int __loc_country_cmp(const void* country1
, const void* country2
) {
171 return loc_country_cmp(*(struct loc_country
**)country1
, *(struct loc_country
**)country2
);
174 LOC_EXPORT
void loc_country_list_sort(struct loc_country_list
* list
) {
176 qsort(list
->elements
, list
->size
, sizeof(*list
->elements
), __loc_country_cmp
);