]> git.ipfire.org Git - location/libloc.git/blame - src/as-list.c
network-list: Add greater elements after the current one
[location/libloc.git] / src / as-list.c
CommitLineData
84a2f0c2
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/as.h>
21#include <loc/as-list.h>
22#include <loc/private.h>
23
24struct loc_as_list {
25 struct loc_ctx* ctx;
26 int refcount;
27
1a415f8c
MT
28 struct loc_as** elements;
29 size_t elements_size;
30
84a2f0c2 31 size_t size;
84a2f0c2
MT
32};
33
1a415f8c
MT
34static 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
84a2f0c2
MT
49LOC_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
84a2f0c2
MT
58 DEBUG(l->ctx, "AS list allocated at %p\n", l);
59 *list = l;
60
61 return 0;
62}
63
64LOC_EXPORT struct loc_as_list* loc_as_list_ref(struct loc_as_list* list) {
65 list->refcount++;
66
67 return list;
68}
69
70static 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
79LOC_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
90LOC_EXPORT size_t loc_as_list_size(struct loc_as_list* list) {
91 return list->size;
92}
93
94LOC_EXPORT int loc_as_list_empty(struct loc_as_list* list) {
95 return list->size == 0;
96}
97
98LOC_EXPORT void loc_as_list_clear(struct loc_as_list* list) {
248f5e04
MT
99 if (!list->elements)
100 return;
101
84a2f0c2 102 for (unsigned int i = 0; i < list->size; i++)
1a415f8c 103 loc_as_unref(list->elements[i]);
248f5e04
MT
104
105 free(list->elements);
106 list->elements_size = 0;
107
108 list->size = 0;
84a2f0c2
MT
109}
110
111LOC_EXPORT struct loc_as* loc_as_list_get(struct loc_as_list* list, size_t index) {
112 // Check index
113 if (index >= list->size)
114 return NULL;
115
1a415f8c 116 return loc_as_ref(list->elements[index]);
84a2f0c2
MT
117}
118
119LOC_EXPORT int loc_as_list_append(
120 struct loc_as_list* list, struct loc_as* as) {
121 if (loc_as_list_contains(list, as))
122 return 0;
123
124 // Check if we have space left
1a415f8c
MT
125 if (list->size >= list->elements_size) {
126 int r = loc_as_list_grow(list, 64);
127 if (r)
128 return r;
84a2f0c2
MT
129 }
130
131 DEBUG(list->ctx, "%p: Appending AS %p to list\n", list, as);
132
1a415f8c 133 list->elements[list->size++] = loc_as_ref(as);
84a2f0c2
MT
134
135 return 0;
136}
137
138LOC_EXPORT int loc_as_list_contains(
139 struct loc_as_list* list, struct loc_as* as) {
140 for (unsigned int i = 0; i < list->size; i++) {
1a415f8c 141 if (loc_as_cmp(as, list->elements[i]) == 0)
84a2f0c2
MT
142 return 1;
143 }
144
145 return 0;
146}
147
148LOC_EXPORT int loc_as_list_contains_number(
149 struct loc_as_list* list, uint32_t number) {
150 struct loc_as* as;
151
152 int r = loc_as_new(list->ctx, &as, number);
153 if (r)
154 return -1;
155
156 r = loc_as_list_contains(list, as);
157 loc_as_unref(as);
158
159 return r;
160}