Line | Count | Source |
1 | | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | | /* Generic vector interface routine |
3 | | * Copyright (C) 1997 Kunihiro Ishiguro |
4 | | */ |
5 | | |
6 | | #include <zebra.h> |
7 | | |
8 | | #include "vector.h" |
9 | | #include "memory.h" |
10 | | |
11 | 8 | DEFINE_MTYPE_STATIC(LIB, VECTOR, "Vector"); |
12 | 8 | DEFINE_MTYPE_STATIC(LIB, VECTOR_INDEX, "Vector index"); |
13 | 8 | |
14 | 8 | /* Initialize vector : allocate memory and return vector. */ |
15 | 8 | vector vector_init(unsigned int size) |
16 | 304 | { |
17 | 304 | vector v = XCALLOC(MTYPE_VECTOR, sizeof(struct _vector)); |
18 | | |
19 | | /* allocate at least one slot */ |
20 | 304 | if (size == 0) |
21 | 0 | size = 1; |
22 | | |
23 | 304 | v->alloced = size; |
24 | 304 | v->active = 0; |
25 | 304 | v->count = 0; |
26 | 304 | v->index = XCALLOC(MTYPE_VECTOR_INDEX, sizeof(void *) * size); |
27 | 304 | return v; |
28 | 304 | } |
29 | | |
30 | | void vector_free(vector v) |
31 | 0 | { |
32 | 0 | XFREE(MTYPE_VECTOR_INDEX, v->index); |
33 | 0 | XFREE(MTYPE_VECTOR, v); |
34 | 0 | } |
35 | | |
36 | | vector vector_copy(vector v) |
37 | 0 | { |
38 | 0 | unsigned int size; |
39 | 0 | vector new = XCALLOC(MTYPE_VECTOR, sizeof(struct _vector)); |
40 | |
|
41 | 0 | new->active = v->active; |
42 | 0 | new->alloced = v->alloced; |
43 | 0 | new->count = v->count; |
44 | |
|
45 | 0 | size = sizeof(void *) * (v->alloced); |
46 | 0 | new->index = XCALLOC(MTYPE_VECTOR_INDEX, size); |
47 | 0 | memcpy(new->index, v->index, size); |
48 | |
|
49 | 0 | return new; |
50 | 0 | } |
51 | | |
52 | | /* Check assigned index, and if it runs short double index pointer */ |
53 | | void vector_ensure(vector v, unsigned int num) |
54 | 158 | { |
55 | 158 | if (v->alloced > num) |
56 | 130 | return; |
57 | | |
58 | 28 | v->index = XREALLOC(MTYPE_VECTOR_INDEX, v->index, |
59 | 28 | sizeof(void *) * (v->alloced * 2)); |
60 | 28 | memset(&v->index[v->alloced], 0, sizeof(void *) * v->alloced); |
61 | 28 | v->alloced *= 2; |
62 | | |
63 | 28 | if (v->alloced <= num) |
64 | 8 | vector_ensure(v, num); |
65 | 28 | } |
66 | | |
67 | | /* This function only returns next empty slot index. It dose not mean |
68 | | the slot's index memory is assigned, please call vector_ensure() |
69 | | after calling this function. */ |
70 | | int vector_empty_slot(vector v) |
71 | 75 | { |
72 | 75 | unsigned int i; |
73 | | |
74 | 75 | if (v->active == v->count) |
75 | 75 | return v->active; |
76 | | |
77 | 0 | if (v->active == 0) |
78 | 0 | return 0; |
79 | | |
80 | 0 | for (i = 0; i < v->active; i++) |
81 | 0 | if (v->index[i] == 0) |
82 | 0 | return i; |
83 | | |
84 | 0 | return i; |
85 | 0 | } |
86 | | |
87 | | /* Set value to the smallest empty slot. */ |
88 | | int vector_set(vector v, void *val) |
89 | 75 | { |
90 | 75 | unsigned int i; |
91 | | |
92 | 75 | i = vector_empty_slot(v); |
93 | 75 | vector_ensure(v, i); |
94 | | |
95 | 75 | if (v->index[i]) |
96 | 0 | v->count--; |
97 | 75 | if (val) |
98 | 75 | v->count++; |
99 | 75 | v->index[i] = val; |
100 | | |
101 | 75 | if (v->active <= i) |
102 | 75 | v->active = i + 1; |
103 | | |
104 | 75 | return i; |
105 | 75 | } |
106 | | |
107 | | /* Set value to specified index slot. */ |
108 | | int vector_set_index(vector v, unsigned int i, void *val) |
109 | 75 | { |
110 | 75 | vector_ensure(v, i); |
111 | | |
112 | 75 | if (v->index[i]) |
113 | 0 | v->count--; |
114 | 75 | if (val) |
115 | 75 | v->count++; |
116 | 75 | v->index[i] = val; |
117 | | |
118 | 75 | if (v->active <= i) |
119 | 21 | v->active = i + 1; |
120 | | |
121 | 75 | return i; |
122 | 75 | } |
123 | | |
124 | | /* Look up vector. */ |
125 | | void *vector_lookup(vector v, unsigned int i) |
126 | 0 | { |
127 | 0 | if (i >= v->active) |
128 | 0 | return NULL; |
129 | 0 | return v->index[i]; |
130 | 0 | } |
131 | | |
132 | | /* Lookup vector, ensure it. */ |
133 | | void *vector_lookup_ensure(vector v, unsigned int i) |
134 | 0 | { |
135 | 0 | vector_ensure(v, i); |
136 | 0 | return v->index[i]; |
137 | 0 | } |
138 | | |
139 | | /* Unset value at specified index slot. */ |
140 | | void vector_unset(vector v, unsigned int i) |
141 | 0 | { |
142 | 0 | if (i >= v->alloced) |
143 | 0 | return; |
144 | | |
145 | 0 | if (v->index[i]) |
146 | 0 | v->count--; |
147 | |
|
148 | 0 | v->index[i] = NULL; |
149 | |
|
150 | 0 | if (i + 1 == v->active) { |
151 | 0 | v->active--; |
152 | 0 | while (i && v->index[--i] == NULL && v->active--) |
153 | 0 | ; /* Is this ugly ? */ |
154 | 0 | } |
155 | 0 | } |
156 | | |
157 | | void vector_remove(vector v, unsigned int ix) |
158 | 0 | { |
159 | 0 | if (ix >= v->active) |
160 | 0 | return; |
161 | | |
162 | 0 | if (v->index[ix]) |
163 | 0 | v->count--; |
164 | |
|
165 | 0 | int n = (--v->active) - ix; |
166 | |
|
167 | 0 | memmove(&v->index[ix], &v->index[ix + 1], n * sizeof(void *)); |
168 | 0 | v->index[v->active] = NULL; |
169 | 0 | } |
170 | | |
171 | | void vector_compact(vector v) |
172 | 0 | { |
173 | 0 | for (unsigned int i = 0; i < vector_active(v); ++i) { |
174 | 0 | if (vector_slot(v, i) == NULL) { |
175 | 0 | vector_remove(v, i); |
176 | 0 | --i; |
177 | 0 | } |
178 | 0 | } |
179 | 0 | } |
180 | | |
181 | | void vector_unset_value(vector v, void *val) |
182 | 0 | { |
183 | 0 | size_t i; |
184 | |
|
185 | 0 | for (i = 0; i < v->active; i++) |
186 | 0 | if (v->index[i] == val) { |
187 | 0 | v->index[i] = NULL; |
188 | 0 | v->count--; |
189 | 0 | break; |
190 | 0 | } |
191 | |
|
192 | 0 | if (i + 1 == v->active) |
193 | 0 | do |
194 | 0 | v->active--; |
195 | 0 | while (i && v->index[--i] == NULL); |
196 | 0 | } |
197 | | |
198 | | void vector_to_array(vector v, void ***dest, int *argc) |
199 | 0 | { |
200 | 0 | *dest = XCALLOC(MTYPE_TMP, sizeof(void *) * v->active); |
201 | 0 | memcpy(*dest, v->index, sizeof(void *) * v->active); |
202 | 0 | *argc = v->active; |
203 | 0 | } |
204 | | |
205 | | vector array_to_vector(void **src, int argc) |
206 | 0 | { |
207 | 0 | vector v = vector_init(VECTOR_MIN_SIZE); |
208 | |
|
209 | 0 | for (int i = 0; i < argc; i++) |
210 | 0 | vector_set_index(v, i, src[i]); |
211 | 0 | return v; |
212 | 0 | } |