]>
git.ipfire.org Git - people/ms/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
) {
99 for (unsigned int i
= 0; i
< list
->size
; i
++)
100 loc_network_unref(list
->elements
[i
]);
105 LOC_EXPORT
void loc_network_list_dump(struct loc_network_list
* list
) {
106 struct loc_network
* network
;
109 for (unsigned int i
= 0; i
< list
->size
; i
++) {
110 network
= list
->elements
[i
];
112 s
= loc_network_str(network
);
114 INFO(list
->ctx
, "%s\n", s
);
119 LOC_EXPORT
struct loc_network
* loc_network_list_get(struct loc_network_list
* list
, size_t index
) {
121 if (index
>= list
->size
)
124 return loc_network_ref(list
->elements
[index
]);
127 LOC_EXPORT
int loc_network_list_push(struct loc_network_list
* list
, struct loc_network
* network
) {
128 // Do not add networks that are already on the list
129 if (loc_network_list_contains(list
, network
))
132 // Check if we have space left
133 if (list
->size
>= list
->elements_size
) {
134 int r
= loc_network_list_grow(list
, 64);
139 DEBUG(list
->ctx
, "%p: Pushing network %p onto stack\n", list
, network
);
141 list
->elements
[list
->size
++] = loc_network_ref(network
);
146 LOC_EXPORT
struct loc_network
* loc_network_list_pop(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
);
153 struct loc_network
* network
= list
->elements
[--list
->size
];
155 DEBUG(list
->ctx
, "%p: Popping network %p from stack\n", list
, network
);
160 LOC_EXPORT
struct loc_network
* loc_network_list_pop_first(struct loc_network_list
* list
) {
161 // Return nothing when empty
162 if (loc_network_list_empty(list
)) {
163 DEBUG(list
->ctx
, "%p: Popped empty stack\n", list
);
167 struct loc_network
* network
= list
->elements
[0];
169 // Move all elements to the top of the stack
170 for (unsigned int i
= 0; i
< --list
->size
; i
++) {
171 list
->elements
[i
] = list
->elements
[i
+1];
174 DEBUG(list
->ctx
, "%p: Popping network %p from stack\n", list
, network
);
179 LOC_EXPORT
int loc_network_list_contains(struct loc_network_list
* list
, struct loc_network
* network
) {
180 for (unsigned int i
= 0; i
< list
->size
; i
++) {
181 if (loc_network_eq(list
->elements
[i
], network
))
188 static void loc_network_list_swap(struct loc_network_list
* list
, unsigned int i1
, unsigned int i2
) {
189 // Do nothing for invalid indices
190 if (i1
>= list
->size
|| i2
>= list
->size
)
193 struct loc_network
* network1
= list
->elements
[i1
];
194 struct loc_network
* network2
= list
->elements
[i2
];
196 list
->elements
[i1
] = network2
;
197 list
->elements
[i2
] = network1
;
200 LOC_EXPORT
void loc_network_list_reverse(struct loc_network_list
* list
) {
202 unsigned int j
= list
->size
- 1;
205 loc_network_list_swap(list
, i
++, j
--);
209 LOC_EXPORT
void loc_network_list_sort(struct loc_network_list
* list
) {
210 unsigned int n
= list
->size
;
216 for (unsigned int i
= 1; i
< n
; i
++) {
217 if (loc_network_gt(list
->elements
[i
-1], list
->elements
[i
]) > 0) {
218 loc_network_list_swap(list
, i
-1, i
);
227 LOC_EXPORT
int loc_network_list_merge(
228 struct loc_network_list
* self
, struct loc_network_list
* other
) {
231 for (unsigned int i
= 0; i
< other
->size
; i
++) {
232 r
= loc_network_list_push(self
, other
->elements
[i
]);