avl_strcmp is now part of libubox
[project/netifd.git] / utils.c
1 /*
2 * netifd - network interface daemon
3 * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2
7 * as published by the Free Software Foundation
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14 #include <string.h>
15 #include <stdlib.h>
16 #include "utils.h"
17
18 void
19 vlist_init(struct vlist_tree *tree, avl_tree_comp cmp, vlist_update_cb update)
20 {
21 tree->update = update;
22 tree->version = 1;
23
24 avl_init(&tree->avl, cmp, 0, tree);
25 }
26
27 void
28 vlist_delete(struct vlist_tree *tree, struct vlist_node *node)
29 {
30 if (!tree->no_delete)
31 avl_delete(&tree->avl, &node->avl);
32 tree->update(tree, NULL, node);
33 }
34
35 void
36 vlist_add(struct vlist_tree *tree, struct vlist_node *node, void *key)
37 {
38 struct vlist_node *old_node = NULL;
39 struct avl_node *anode;
40
41 node->avl.key = key;
42 node->version = tree->version;
43
44 anode = avl_find(&tree->avl, key);
45 if (anode) {
46 old_node = container_of(anode, struct vlist_node, avl);
47 if (tree->keep_old || tree->no_delete) {
48 old_node->version = tree->version;
49 goto update_only;
50 }
51
52 avl_delete(&tree->avl, anode);
53 }
54
55 avl_insert(&tree->avl, &node->avl);
56
57 update_only:
58 tree->update(tree, node, old_node);
59 }
60
61 void
62 vlist_flush(struct vlist_tree *tree)
63 {
64 struct vlist_node *node, *tmp;
65
66 avl_for_each_element_safe(&tree->avl, node, avl, tmp) {
67 if ((node->version == tree->version || node->version == -1) &&
68 tree->version != -1)
69 continue;
70
71 vlist_delete(tree, node);
72 }
73 }
74
75 void
76 vlist_flush_all(struct vlist_tree *tree)
77 {
78 tree->version = -1;
79 vlist_flush(tree);
80 }
81
82
83 void
84 __vlist_simple_init(struct vlist_simple_tree *tree, int offset)
85 {
86 INIT_LIST_HEAD(&tree->list);
87 tree->version = 1;
88 tree->head_offset = offset;
89 }
90
91 void
92 vlist_simple_delete(struct vlist_simple_tree *tree, struct vlist_simple_node *node)
93 {
94 char *ptr;
95
96 list_del(&node->list);
97 ptr = (char *) node - tree->head_offset;
98 free(ptr);
99 }
100
101 void
102 vlist_simple_flush(struct vlist_simple_tree *tree)
103 {
104 struct vlist_simple_node *n, *tmp;
105
106 list_for_each_entry_safe(n, tmp, &tree->list, list) {
107 if ((n->version == tree->version || n->version == -1) &&
108 tree->version != -1)
109 continue;
110
111 vlist_simple_delete(tree, n);
112 }
113 }
114
115 void
116 vlist_simple_replace(struct vlist_simple_tree *dest, struct vlist_simple_tree *old)
117 {
118 struct vlist_simple_node *n, *tmp;
119
120 vlist_simple_update(dest);
121 list_for_each_entry_safe(n, tmp, &old->list, list) {
122 list_del(&n->list);
123 vlist_simple_add(dest, n);
124 }
125 vlist_simple_flush(dest);
126 }
127
128 void
129 vlist_simple_flush_all(struct vlist_simple_tree *tree)
130 {
131 tree->version = -1;
132 vlist_simple_flush(tree);
133 }