]> git.ipfire.org Git - location/libloc.git/blob - src/as-list.c
importer: Drop EDROP as it has been merged into DROP
[location/libloc.git] / src / as-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/as.h>
21 #include <loc/as-list.h>
22 #include <loc/private.h>
23
24 struct loc_as_list {
25 struct loc_ctx* ctx;
26 int refcount;
27
28 struct loc_as** elements;
29 size_t elements_size;
30
31 size_t size;
32 };
33
34 static int loc_as_list_grow(struct loc_as_list* list, size_t size) {
35 DEBUG(list->ctx, "Growing AS list %p by %zu to %zu\n",
36 list, size, list->elements_size + size);
37
38 struct loc_as** 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_as_list_new(struct loc_ctx* ctx,
50 struct loc_as_list** list) {
51 struct loc_as_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, "AS list allocated at %p\n", l);
59 *list = l;
60
61 return 0;
62 }
63
64 LOC_EXPORT struct loc_as_list* loc_as_list_ref(struct loc_as_list* list) {
65 list->refcount++;
66
67 return list;
68 }
69
70 static void loc_as_list_free(struct loc_as_list* list) {
71 DEBUG(list->ctx, "Releasing AS list at %p\n", list);
72
73 loc_as_list_clear(list);
74
75 loc_unref(list->ctx);
76 free(list);
77 }
78
79 LOC_EXPORT struct loc_as_list* loc_as_list_unref(struct loc_as_list* list) {
80 if (!list)
81 return NULL;
82
83 if (--list->refcount > 0)
84 return list;
85
86 loc_as_list_free(list);
87 return NULL;
88 }
89
90 LOC_EXPORT size_t loc_as_list_size(struct loc_as_list* list) {
91 return list->size;
92 }
93
94 LOC_EXPORT int loc_as_list_empty(struct loc_as_list* list) {
95 return list->size == 0;
96 }
97
98 LOC_EXPORT void loc_as_list_clear(struct loc_as_list* list) {
99 if (!list->elements)
100 return;
101
102 for (unsigned int i = 0; i < list->size; i++)
103 loc_as_unref(list->elements[i]);
104
105 free(list->elements);
106 list->elements = NULL;
107 list->elements_size = 0;
108
109 list->size = 0;
110 }
111
112 LOC_EXPORT struct loc_as* loc_as_list_get(struct loc_as_list* list, size_t index) {
113 // Check index
114 if (index >= list->size)
115 return NULL;
116
117 return loc_as_ref(list->elements[index]);
118 }
119
120 LOC_EXPORT int loc_as_list_append(
121 struct loc_as_list* list, struct loc_as* as) {
122 if (loc_as_list_contains(list, as))
123 return 0;
124
125 // Check if we have space left
126 if (list->size >= list->elements_size) {
127 int r = loc_as_list_grow(list, 64);
128 if (r)
129 return r;
130 }
131
132 DEBUG(list->ctx, "%p: Appending AS %p to list\n", list, as);
133
134 list->elements[list->size++] = loc_as_ref(as);
135
136 return 0;
137 }
138
139 LOC_EXPORT int loc_as_list_contains(
140 struct loc_as_list* list, struct loc_as* as) {
141 for (unsigned int i = 0; i < list->size; i++) {
142 if (loc_as_cmp(as, list->elements[i]) == 0)
143 return 1;
144 }
145
146 return 0;
147 }
148
149 LOC_EXPORT int loc_as_list_contains_number(
150 struct loc_as_list* list, uint32_t number) {
151 struct loc_as* as;
152
153 int r = loc_as_new(list->ctx, &as, number);
154 if (r)
155 return -1;
156
157 r = loc_as_list_contains(list, as);
158 loc_as_unref(as);
159
160 return r;
161 }