]> git.ipfire.org Git - location/debian/libloc.git/blame - src/as-list.c
Update upstream source from tag 'upstream/0.9.15'
[location/debian/libloc.git] / src / as-list.c
CommitLineData
1f2c3ccb
JS
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
1f2c3ccb
JS
17#include <stdlib.h>
18
19#include <libloc/as.h>
20#include <libloc/as-list.h>
aa9346d8 21#include <libloc/compat.h>
1f2c3ccb
JS
22#include <libloc/private.h>
23
24struct 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
34static int loc_as_list_grow(struct loc_as_list* list) {
35 size_t size = list->elements_size * 2;
36 if (size < 1024)
37 size = 1024;
38
39 DEBUG(list->ctx, "Growing AS list %p by %zu to %zu\n",
40 list, size, list->elements_size + size);
41
42 struct loc_as** elements = reallocarray(list->elements,
43 list->elements_size + size, sizeof(*list->elements));
44 if (!elements)
aa9346d8 45 return 1;
1f2c3ccb
JS
46
47 list->elements = elements;
48 list->elements_size += size;
49
50 return 0;
51}
52
53LOC_EXPORT int loc_as_list_new(struct loc_ctx* ctx,
54 struct loc_as_list** list) {
55 struct loc_as_list* l = calloc(1, sizeof(*l));
56 if (!l)
aa9346d8 57 return 1;
1f2c3ccb
JS
58
59 l->ctx = loc_ref(ctx);
60 l->refcount = 1;
61
62 DEBUG(l->ctx, "AS list allocated at %p\n", l);
63 *list = l;
64
65 return 0;
66}
67
68LOC_EXPORT struct loc_as_list* loc_as_list_ref(struct loc_as_list* list) {
69 list->refcount++;
70
71 return list;
72}
73
74static void loc_as_list_free(struct loc_as_list* list) {
75 DEBUG(list->ctx, "Releasing AS list at %p\n", list);
76
77 loc_as_list_clear(list);
78
79 loc_unref(list->ctx);
80 free(list);
81}
82
83LOC_EXPORT struct loc_as_list* loc_as_list_unref(struct loc_as_list* list) {
84 if (!list)
85 return NULL;
86
87 if (--list->refcount > 0)
88 return list;
89
90 loc_as_list_free(list);
91 return NULL;
92}
93
94LOC_EXPORT size_t loc_as_list_size(struct loc_as_list* list) {
95 return list->size;
96}
97
98LOC_EXPORT int loc_as_list_empty(struct loc_as_list* list) {
99 return list->size == 0;
100}
101
102LOC_EXPORT void loc_as_list_clear(struct loc_as_list* list) {
103 if (!list->elements)
104 return;
105
106 for (unsigned int i = 0; i < list->size; i++)
107 loc_as_unref(list->elements[i]);
108
109 free(list->elements);
110 list->elements = NULL;
111 list->elements_size = 0;
112
113 list->size = 0;
114}
115
116LOC_EXPORT struct loc_as* loc_as_list_get(struct loc_as_list* list, size_t index) {
117 // Check index
118 if (index >= list->size)
119 return NULL;
120
121 return loc_as_ref(list->elements[index]);
122}
123
124LOC_EXPORT int loc_as_list_append(
125 struct loc_as_list* list, struct loc_as* as) {
126 if (loc_as_list_contains(list, as))
127 return 0;
128
129 // Check if we have space left
130 if (list->size >= list->elements_size) {
131 int r = loc_as_list_grow(list);
132 if (r)
133 return r;
134 }
135
136 DEBUG(list->ctx, "%p: Appending AS %p to list\n", list, as);
137
138 list->elements[list->size++] = loc_as_ref(as);
139
140 return 0;
141}
142
143LOC_EXPORT int loc_as_list_contains(
144 struct loc_as_list* list, struct loc_as* as) {
145 for (unsigned int i = 0; i < list->size; i++) {
146 if (loc_as_cmp(as, list->elements[i]) == 0)
147 return 1;
148 }
149
150 return 0;
151}
152
153LOC_EXPORT int loc_as_list_contains_number(
154 struct loc_as_list* list, uint32_t number) {
155 struct loc_as* as;
156
157 int r = loc_as_new(list->ctx, &as, number);
158 if (r)
159 return -1;
160
161 r = loc_as_list_contains(list, as);
162 loc_as_unref(as);
163
164 return r;
165}
166
167static int __loc_as_cmp(const void* as1, const void* as2) {
168 return loc_as_cmp(*(struct loc_as**)as1, *(struct loc_as**)as2);
169}
170
171LOC_EXPORT void loc_as_list_sort(struct loc_as_list* list) {
172 // Sort everything
173 qsort(list->elements, list->size, sizeof(*list->elements), __loc_as_cmp);
174}