]>
git.ipfire.org Git - location/libloc.git/blob - src/network-list.c
2 libloc - A library to determine the location of someone on the Internet
4 Copyright (C) 2020 IPFire Development Team <info@ipfire.org>
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.
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.
20 #include <loc/libloc.h>
21 #include <loc/network.h>
22 #include <loc/private.h>
24 struct loc_network_list
{
28 struct loc_network
** elements
;
34 static int loc_network_list_grow(struct loc_network_list
* list
, size_t size
) {
35 DEBUG(list
->ctx
, "Growing network list %p by %zu to %zu\n",
36 list
, size
, list
->elements_size
+ size
);
38 struct loc_network
** elements
= reallocarray(list
->elements
,
39 list
->elements_size
+ size
, sizeof(*list
->elements
));
43 list
->elements
= elements
;
44 list
->elements_size
+= size
;
49 LOC_EXPORT
int loc_network_list_new(struct loc_ctx
* ctx
,
50 struct loc_network_list
** list
) {
51 struct loc_network_list
* l
= calloc(1, sizeof(*l
));
55 l
->ctx
= loc_ref(ctx
);
58 DEBUG(l
->ctx
, "Network list allocated at %p\n", l
);
63 LOC_EXPORT
struct loc_network_list
* loc_network_list_ref(struct loc_network_list
* list
) {
69 static void loc_network_list_free(struct loc_network_list
* list
) {
70 DEBUG(list
->ctx
, "Releasing network list at %p\n", list
);
72 for (unsigned int i
= 0; i
< list
->size
; i
++)
73 loc_network_unref(list
->elements
[i
]);
79 LOC_EXPORT
struct loc_network_list
* loc_network_list_unref(struct loc_network_list
* list
) {
83 if (--list
->refcount
> 0)
86 loc_network_list_free(list
);
90 LOC_EXPORT
size_t loc_network_list_size(struct loc_network_list
* list
) {
94 LOC_EXPORT
int loc_network_list_empty(struct loc_network_list
* list
) {
95 return list
->size
== 0;
98 LOC_EXPORT
void loc_network_list_clear(struct loc_network_list
* list
) {
102 for (unsigned int i
= 0; i
< list
->size
; i
++)
103 loc_network_unref(list
->elements
[i
]);
105 free(list
->elements
);
106 list
->elements_size
= 0;
111 LOC_EXPORT
void loc_network_list_dump(struct loc_network_list
* list
) {
112 struct loc_network
* network
;
115 for (unsigned int i
= 0; i
< list
->size
; i
++) {
116 network
= list
->elements
[i
];
118 s
= loc_network_str(network
);
120 INFO(list
->ctx
, "%s\n", s
);
125 LOC_EXPORT
struct loc_network
* loc_network_list_get(struct loc_network_list
* list
, size_t index
) {
127 if (index
>= list
->size
)
130 return loc_network_ref(list
->elements
[index
]);
133 LOC_EXPORT
int loc_network_list_push(struct loc_network_list
* list
, struct loc_network
* network
) {
134 // Do not add networks that are already on the list
135 if (loc_network_list_contains(list
, network
))
138 // Check if we have space left
139 if (list
->size
>= list
->elements_size
) {
140 int r
= loc_network_list_grow(list
, 64);
145 DEBUG(list
->ctx
, "%p: Pushing network %p onto stack\n", list
, network
);
147 list
->elements
[list
->size
++] = loc_network_ref(network
);
152 LOC_EXPORT
struct loc_network
* loc_network_list_pop(struct loc_network_list
* list
) {
153 // Return nothing when empty
154 if (loc_network_list_empty(list
)) {
155 DEBUG(list
->ctx
, "%p: Popped empty stack\n", list
);
159 struct loc_network
* network
= list
->elements
[--list
->size
];
161 DEBUG(list
->ctx
, "%p: Popping network %p from stack\n", list
, network
);
166 LOC_EXPORT
struct loc_network
* loc_network_list_pop_first(struct loc_network_list
* list
) {
167 // Return nothing when empty
168 if (loc_network_list_empty(list
)) {
169 DEBUG(list
->ctx
, "%p: Popped empty stack\n", list
);
173 struct loc_network
* network
= list
->elements
[0];
175 // Move all elements to the top of the stack
176 for (unsigned int i
= 0; i
< --list
->size
; i
++) {
177 list
->elements
[i
] = list
->elements
[i
+1];
180 DEBUG(list
->ctx
, "%p: Popping network %p from stack\n", list
, network
);
185 LOC_EXPORT
int loc_network_list_contains(struct loc_network_list
* list
, struct loc_network
* network
) {
186 for (unsigned int i
= 0; i
< list
->size
; i
++) {
187 if (loc_network_eq(list
->elements
[i
], network
))
194 static void loc_network_list_swap(struct loc_network_list
* list
, unsigned int i1
, unsigned int i2
) {
195 // Do nothing for invalid indices
196 if (i1
>= list
->size
|| i2
>= list
->size
)
199 struct loc_network
* network1
= list
->elements
[i1
];
200 struct loc_network
* network2
= list
->elements
[i2
];
202 list
->elements
[i1
] = network2
;
203 list
->elements
[i2
] = network1
;
206 LOC_EXPORT
void loc_network_list_reverse(struct loc_network_list
* list
) {
208 unsigned int j
= list
->size
- 1;
211 loc_network_list_swap(list
, i
++, j
--);
215 LOC_EXPORT
void loc_network_list_sort(struct loc_network_list
* list
) {
216 unsigned int n
= list
->size
;
222 for (unsigned int i
= 1; i
< n
; i
++) {
223 if (loc_network_gt(list
->elements
[i
-1], list
->elements
[i
]) > 0) {
224 loc_network_list_swap(list
, i
-1, i
);
233 LOC_EXPORT
int loc_network_list_merge(
234 struct loc_network_list
* self
, struct loc_network_list
* other
) {
237 for (unsigned int i
= 0; i
< other
->size
; i
++) {
238 r
= loc_network_list_push(self
, other
->elements
[i
]);