]> git.ipfire.org Git - people/ms/libloc.git/blame - src/network-list.c
Move network lists into an own file
[people/ms/libloc.git] / src / network-list.c
CommitLineData
e0b9ff5f
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/libloc.h>
21#include <loc/network.h>
22#include <loc/private.h>
23
24struct loc_network_list {
25 struct loc_ctx* ctx;
26 int refcount;
27
28 struct loc_network* list[1024];
29 size_t size;
30 size_t max_size;
31};
32
33LOC_EXPORT int loc_network_list_new(struct loc_ctx* ctx,
34 struct loc_network_list** list) {
35 struct loc_network_list* l = calloc(1, sizeof(*l));
36 if (!l)
37 return -ENOMEM;
38
39 l->ctx = loc_ref(ctx);
40 l->refcount = 1;
41
42 // Do not allow this list to grow larger than this
43 l->max_size = 1024;
44
45 DEBUG(l->ctx, "Network list allocated at %p\n", l);
46 *list = l;
47 return 0;
48}
49
50LOC_EXPORT struct loc_network_list* loc_network_list_ref(struct loc_network_list* list) {
51 list->refcount++;
52
53 return list;
54}
55
56static void loc_network_list_free(struct loc_network_list* list) {
57 DEBUG(list->ctx, "Releasing network list at %p\n", list);
58
59 for (unsigned int i = 0; i < list->size; i++)
60 loc_network_unref(list->list[i]);
61
62 loc_unref(list->ctx);
63 free(list);
64}
65
66LOC_EXPORT struct loc_network_list* loc_network_list_unref(struct loc_network_list* list) {
67 if (!list)
68 return NULL;
69
70 if (--list->refcount > 0)
71 return list;
72
73 loc_network_list_free(list);
74 return NULL;
75}
76
77LOC_EXPORT size_t loc_network_list_size(struct loc_network_list* list) {
78 return list->size;
79}
80
81LOC_EXPORT int loc_network_list_empty(struct loc_network_list* list) {
82 return list->size == 0;
83}
84
85LOC_EXPORT void loc_network_list_clear(struct loc_network_list* list) {
86 for (unsigned int i = 0; i < list->size; i++)
87 loc_network_unref(list->list[i]);
88
89 list->size = 0;
90}
91
92LOC_EXPORT void loc_network_list_dump(struct loc_network_list* list) {
93 struct loc_network* network;
94 char* s;
95
96 for (unsigned int i = 0; i < list->size; i++) {
97 network = list->list[i];
98
99 s = loc_network_str(network);
100
101 INFO(list->ctx, "%s\n", s);
102 free(s);
103 }
104}
105
106LOC_EXPORT struct loc_network* loc_network_list_get(struct loc_network_list* list, size_t index) {
107 // Check index
108 if (index >= list->size)
109 return NULL;
110
111 return loc_network_ref(list->list[index]);
112}
113
114LOC_EXPORT int loc_network_list_push(struct loc_network_list* list, struct loc_network* network) {
115 // Do not add networks that are already on the list
116 if (loc_network_list_contains(list, network))
117 return 0;
118
119 // Check if we have space left
120 if (list->size == list->max_size) {
121 ERROR(list->ctx, "%p: Could not push network onto the stack: Stack full\n", list);
122 return -ENOMEM;
123 }
124
125 DEBUG(list->ctx, "%p: Pushing network %p onto stack\n", list, network);
126
127 list->list[list->size++] = loc_network_ref(network);
128
129 return 0;
130}
131
132LOC_EXPORT struct loc_network* loc_network_list_pop(struct loc_network_list* list) {
133 // Return nothing when empty
134 if (loc_network_list_empty(list)) {
135 DEBUG(list->ctx, "%p: Popped empty stack\n", list);
136 return NULL;
137 }
138
139 struct loc_network* network = list->list[--list->size];
140
141 DEBUG(list->ctx, "%p: Popping network %p from stack\n", list, network);
142
143 return network;
144}
145
146LOC_EXPORT struct loc_network* loc_network_list_pop_first(struct loc_network_list* list) {
147 // Return nothing when empty
148 if (loc_network_list_empty(list)) {
149 DEBUG(list->ctx, "%p: Popped empty stack\n", list);
150 return NULL;
151 }
152
153 struct loc_network* network = list->list[0];
154
155 // Move all elements to the top of the stack
156 for (unsigned int i = 0; i < --list->size; i++) {
157 list->list[i] = list->list[i+1];
158 }
159
160 DEBUG(list->ctx, "%p: Popping network %p from stack\n", list, network);
161
162 return network;
163}
164
165LOC_EXPORT int loc_network_list_contains(struct loc_network_list* list, struct loc_network* network) {
166 for (unsigned int i = 0; i < list->size; i++) {
167 if (loc_network_eq(list->list[i], network))
168 return 1;
169 }
170
171 return 0;
172}
173
174static void loc_network_list_swap(struct loc_network_list* list, unsigned int i1, unsigned int i2) {
175 // Do nothing for invalid indices
176 if (i1 >= list->size || i2 >= list->size)
177 return;
178
179 struct loc_network* network1 = list->list[i1];
180 struct loc_network* network2 = list->list[i2];
181
182 list->list[i1] = network2;
183 list->list[i2] = network1;
184}
185
186LOC_EXPORT void loc_network_list_reverse(struct loc_network_list* list) {
187 unsigned int i = 0;
188 unsigned int j = list->size - 1;
189
190 while (i < j) {
191 loc_network_list_swap(list, i++, j--);
192 }
193}
194
195LOC_EXPORT void loc_network_list_sort(struct loc_network_list* list) {
196 unsigned int n = list->size;
197 int swapped;
198
199 do {
200 swapped = 0;
201
202 for (unsigned int i = 1; i < n; i++) {
203 if (loc_network_gt(list->list[i-1], list->list[i]) > 0) {
204 loc_network_list_swap(list, i-1, i);
205 swapped = 1;
206 }
207 }
208
209 n--;
210 } while (swapped);
211}
212
213LOC_EXPORT int loc_network_list_merge(
214 struct loc_network_list* self, struct loc_network_list* other) {
215 int r;
216
217 for (unsigned int i = 0; i < other->size; i++) {
218 r = loc_network_list_push(self, other->list[i]);
219 if (r)
220 return r;
221 }
222
223 return 0;
224}