]> git.ipfire.org Git - location/libloc.git/blame - src/country-list.c
as-list/country-list: Set elements list to zero after freeing it
[location/libloc.git] / src / country-list.c
CommitLineData
e646a8f3
MT
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
24struct loc_country_list {
25 struct loc_ctx* ctx;
26 int refcount;
27
d5205091
MT
28 struct loc_country** elements;
29 size_t elements_size;
30
e646a8f3 31 size_t size;
e646a8f3
MT
32};
33
d5205091
MT
34static 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
e646a8f3
MT
49LOC_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
e646a8f3
MT
58 DEBUG(l->ctx, "Country list allocated at %p\n", l);
59 *list = l;
60
61 return 0;
62}
63
64LOC_EXPORT struct loc_country_list* loc_country_list_ref(struct loc_country_list* list) {
65 list->refcount++;
66
67 return list;
68}
69
70static 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
79LOC_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
90LOC_EXPORT size_t loc_country_list_size(struct loc_country_list* list) {
91 return list->size;
92}
93
94LOC_EXPORT int loc_country_list_empty(struct loc_country_list* list) {
95 return list->size == 0;
96}
97
98LOC_EXPORT void loc_country_list_clear(struct loc_country_list* list) {
248f5e04
MT
99 if (!list->elements)
100 return;
101
e646a8f3 102 for (unsigned int i = 0; i < list->size; i++)
d5205091 103 loc_country_unref(list->elements[i]);
248f5e04
MT
104
105 free(list->elements);
a6dc9324 106 list->elements = NULL;
248f5e04
MT
107 list->elements_size = 0;
108
109 list->size = 0;
e646a8f3
MT
110}
111
112LOC_EXPORT struct loc_country* loc_country_list_get(struct loc_country_list* list, size_t index) {
113 // Check index
114 if (index >= list->size)
115 return NULL;
116
d5205091 117 return loc_country_ref(list->elements[index]);
e646a8f3
MT
118}
119
120LOC_EXPORT int loc_country_list_append(
121 struct loc_country_list* list, struct loc_country* country) {
122 if (loc_country_list_contains(list, country))
123 return 0;
124
125 // Check if we have space left
d5205091
MT
126 if (list->size >= list->elements_size) {
127 int r = loc_country_list_grow(list, 64);
128 if (r)
129 return r;
e646a8f3
MT
130 }
131
132 DEBUG(list->ctx, "%p: Appending country %p to list\n", list, country);
133
d5205091 134 list->elements[list->size++] = loc_country_ref(country);
e646a8f3
MT
135
136 return 0;
137}
138
139LOC_EXPORT int loc_country_list_contains(
140 struct loc_country_list* list, struct loc_country* country) {
141 for (unsigned int i = 0; i < list->size; i++) {
d5205091 142 if (loc_country_cmp(country, list->elements[i]) == 0)
e646a8f3
MT
143 return 1;
144 }
145
146 return 0;
147}
148
149LOC_EXPORT int loc_country_list_contains_code(
150 struct loc_country_list* list, const char* code) {
151 struct loc_country* country;
152
153 int r = loc_country_new(list->ctx, &country, code);
154 if (r)
155 return -1;
156
157 r = loc_country_list_contains(list, country);
158 loc_country_unref(country);
159
160 return r;
161}