]>
git.ipfire.org Git - location/libloc.git/blob - src/network-list.c
1f6e80e5bf2f6d60756c86b59a2535849f605ae2
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
* list
[1024];
33 LOC_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
));
39 l
->ctx
= loc_ref(ctx
);
42 // Do not allow this list to grow larger than this
45 DEBUG(l
->ctx
, "Network list allocated at %p\n", l
);
50 LOC_EXPORT
struct loc_network_list
* loc_network_list_ref(struct loc_network_list
* list
) {
56 static void loc_network_list_free(struct loc_network_list
* list
) {
57 DEBUG(list
->ctx
, "Releasing network list at %p\n", list
);
59 for (unsigned int i
= 0; i
< list
->size
; i
++)
60 loc_network_unref(list
->list
[i
]);
66 LOC_EXPORT
struct loc_network_list
* loc_network_list_unref(struct loc_network_list
* list
) {
70 if (--list
->refcount
> 0)
73 loc_network_list_free(list
);
77 LOC_EXPORT
size_t loc_network_list_size(struct loc_network_list
* list
) {
81 LOC_EXPORT
int loc_network_list_empty(struct loc_network_list
* list
) {
82 return list
->size
== 0;
85 LOC_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
]);
92 LOC_EXPORT
void loc_network_list_dump(struct loc_network_list
* list
) {
93 struct loc_network
* network
;
96 for (unsigned int i
= 0; i
< list
->size
; i
++) {
97 network
= list
->list
[i
];
99 s
= loc_network_str(network
);
101 INFO(list
->ctx
, "%s\n", s
);
106 LOC_EXPORT
struct loc_network
* loc_network_list_get(struct loc_network_list
* list
, size_t index
) {
108 if (index
>= list
->size
)
111 return loc_network_ref(list
->list
[index
]);
114 LOC_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
))
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
);
125 DEBUG(list
->ctx
, "%p: Pushing network %p onto stack\n", list
, network
);
127 list
->list
[list
->size
++] = loc_network_ref(network
);
132 LOC_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
);
139 struct loc_network
* network
= list
->list
[--list
->size
];
141 DEBUG(list
->ctx
, "%p: Popping network %p from stack\n", list
, network
);
146 LOC_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
);
153 struct loc_network
* network
= list
->list
[0];
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];
160 DEBUG(list
->ctx
, "%p: Popping network %p from stack\n", list
, network
);
165 LOC_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
))
174 static 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
)
179 struct loc_network
* network1
= list
->list
[i1
];
180 struct loc_network
* network2
= list
->list
[i2
];
182 list
->list
[i1
] = network2
;
183 list
->list
[i2
] = network1
;
186 LOC_EXPORT
void loc_network_list_reverse(struct loc_network_list
* list
) {
188 unsigned int j
= list
->size
- 1;
191 loc_network_list_swap(list
, i
++, j
--);
195 LOC_EXPORT
void loc_network_list_sort(struct loc_network_list
* list
) {
196 unsigned int n
= list
->size
;
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
);
213 LOC_EXPORT
int loc_network_list_merge(
214 struct loc_network_list
* self
, struct loc_network_list
* other
) {
217 for (unsigned int i
= 0; i
< other
->size
; i
++) {
218 r
= loc_network_list_push(self
, other
->list
[i
]);