]> git.ipfire.org Git - people/ms/libloc.git/blob - src/country-list.c
Actually clear all lists
[people/ms/libloc.git] / src / country-list.c
1 /*
2 libloc - A library to determine the location of someone on the Internet
3
4 Copyright (C) 2020 IPFire Development Team <info@ipfire.org>
5
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.
10
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.
15 */
16
17 #include <errno.h>
18 #include <stdlib.h>
19
20 #include <loc/country.h>
21 #include <loc/country-list.h>
22 #include <loc/private.h>
23
24 struct loc_country_list {
25 struct loc_ctx* ctx;
26 int refcount;
27
28 struct loc_country** elements;
29 size_t elements_size;
30
31 size_t size;
32 };
33
34 static int loc_country_list_grow(struct loc_country_list* list, size_t size) {
35 DEBUG(list->ctx, "Growing country list %p by %zu to %zu\n",
36 list, size, list->elements_size + size);
37
38 struct loc_country** elements = reallocarray(list->elements,
39 list->elements_size + size, sizeof(*list->elements));
40 if (!elements)
41 return -errno;
42
43 list->elements = elements;
44 list->elements_size += size;
45
46 return 0;
47 }
48
49 LOC_EXPORT int loc_country_list_new(struct loc_ctx* ctx,
50 struct loc_country_list** list) {
51 struct loc_country_list* l = calloc(1, sizeof(*l));
52 if (!l)
53 return -ENOMEM;
54
55 l->ctx = loc_ref(ctx);
56 l->refcount = 1;
57
58 DEBUG(l->ctx, "Country list allocated at %p\n", l);
59 *list = l;
60
61 return 0;
62 }
63
64 LOC_EXPORT struct loc_country_list* loc_country_list_ref(struct loc_country_list* list) {
65 list->refcount++;
66
67 return list;
68 }
69
70 static void loc_country_list_free(struct loc_country_list* list) {
71 DEBUG(list->ctx, "Releasing country list at %p\n", list);
72
73 loc_country_list_clear(list);
74
75 loc_unref(list->ctx);
76 free(list);
77 }
78
79 LOC_EXPORT struct loc_country_list* loc_country_list_unref(struct loc_country_list* list) {
80 if (!list)
81 return NULL;
82
83 if (--list->refcount > 0)
84 return list;
85
86 loc_country_list_free(list);
87 return NULL;
88 }
89
90 LOC_EXPORT size_t loc_country_list_size(struct loc_country_list* list) {
91 return list->size;
92 }
93
94 LOC_EXPORT int loc_country_list_empty(struct loc_country_list* list) {
95 return list->size == 0;
96 }
97
98 LOC_EXPORT void loc_country_list_clear(struct loc_country_list* list) {
99 if (!list->elements)
100 return;
101
102 for (unsigned int i = 0; i < list->size; i++)
103 loc_country_unref(list->elements[i]);
104
105 free(list->elements);
106 list->elements_size = 0;
107
108 list->size = 0;
109 }
110
111 LOC_EXPORT struct loc_country* loc_country_list_get(struct loc_country_list* list, size_t index) {
112 // Check index
113 if (index >= list->size)
114 return NULL;
115
116 return loc_country_ref(list->elements[index]);
117 }
118
119 LOC_EXPORT int loc_country_list_append(
120 struct loc_country_list* list, struct loc_country* country) {
121 if (loc_country_list_contains(list, country))
122 return 0;
123
124 // Check if we have space left
125 if (list->size >= list->elements_size) {
126 int r = loc_country_list_grow(list, 64);
127 if (r)
128 return r;
129 }
130
131 DEBUG(list->ctx, "%p: Appending country %p to list\n", list, country);
132
133 list->elements[list->size++] = loc_country_ref(country);
134
135 return 0;
136 }
137
138 LOC_EXPORT int loc_country_list_contains(
139 struct loc_country_list* list, struct loc_country* country) {
140 for (unsigned int i = 0; i < list->size; i++) {
141 if (loc_country_cmp(country, list->elements[i]) == 0)
142 return 1;
143 }
144
145 return 0;
146 }
147
148 LOC_EXPORT int loc_country_list_contains_code(
149 struct loc_country_list* list, const char* code) {
150 struct loc_country* country;
151
152 int r = loc_country_new(list->ctx, &country, code);
153 if (r)
154 return -1;
155
156 r = loc_country_list_contains(list, country);
157 loc_country_unref(country);
158
159 return r;
160 }