Line data Source code
1 : /* Generic vector interface routine
2 : * Copyright (C) 1997 Kunihiro Ishiguro
3 : *
4 : * This file is part of GNU Zebra.
5 : *
6 : * GNU Zebra is free software; you can redistribute it and/or modify it
7 : * under the terms of the GNU General Public License as published by the
8 : * Free Software Foundation; either version 2, or (at your option) any
9 : * later version.
10 : *
11 : * GNU Zebra is distributed in the hope that it will be useful, but
12 : * WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : * General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU General Public License along
17 : * with this program; see the file COPYING; if not, write to the Free Software
18 : * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 : */
20 :
21 : #include <zebra.h>
22 :
23 : #include "vector.h"
24 : #include "memory.h"
25 :
26 36 : DEFINE_MTYPE_STATIC(LIB, VECTOR, "Vector");
27 36 : DEFINE_MTYPE_STATIC(LIB, VECTOR_INDEX, "Vector index");
28 :
29 : /* Initialize vector : allocate memory and return vector. */
30 120192 : vector vector_init(unsigned int size)
31 : {
32 120192 : vector v = XCALLOC(MTYPE_VECTOR, sizeof(struct _vector));
33 :
34 : /* allocate at least one slot */
35 120192 : if (size == 0)
36 : size = 1;
37 :
38 120192 : v->alloced = size;
39 120192 : v->active = 0;
40 120192 : v->count = 0;
41 120192 : v->index = XCALLOC(MTYPE_VECTOR_INDEX, sizeof(void *) * size);
42 120192 : return v;
43 : }
44 :
45 120192 : void vector_free(vector v)
46 : {
47 120192 : XFREE(MTYPE_VECTOR_INDEX, v->index);
48 120192 : XFREE(MTYPE_VECTOR, v);
49 120192 : }
50 :
51 0 : vector vector_copy(vector v)
52 : {
53 0 : unsigned int size;
54 0 : vector new = XCALLOC(MTYPE_VECTOR, sizeof(struct _vector));
55 :
56 0 : new->active = v->active;
57 0 : new->alloced = v->alloced;
58 0 : new->count = v->count;
59 :
60 0 : size = sizeof(void *) * (v->alloced);
61 0 : new->index = XCALLOC(MTYPE_VECTOR_INDEX, size);
62 0 : memcpy(new->index, v->index, size);
63 :
64 0 : return new;
65 : }
66 :
67 : /* Check assigned index, and if it runs short double index pointer */
68 235635 : void vector_ensure(vector v, unsigned int num)
69 : {
70 235659 : if (v->alloced > num)
71 : return;
72 :
73 39913 : v->index = XREALLOC(MTYPE_VECTOR_INDEX, v->index,
74 : sizeof(void *) * (v->alloced * 2));
75 39913 : memset(&v->index[v->alloced], 0, sizeof(void *) * v->alloced);
76 39913 : v->alloced *= 2;
77 :
78 39913 : if (v->alloced <= num)
79 : vector_ensure(v, num);
80 : }
81 :
82 : /* This function only returns next empty slot index. It dose not mean
83 : the slot's index memory is assigned, please call vector_ensure()
84 : after calling this function. */
85 234575 : int vector_empty_slot(vector v)
86 : {
87 234575 : unsigned int i;
88 :
89 234575 : if (v->active == v->count)
90 228575 : return v->active;
91 :
92 6000 : if (v->active == 0)
93 : return 0;
94 :
95 64 : for (i = 0; i < v->active; i++)
96 32 : if (v->index[i] == 0)
97 0 : return i;
98 :
99 32 : return i;
100 : }
101 :
102 : /* Set value to the smallest empty slot. */
103 234575 : int vector_set(vector v, void *val)
104 : {
105 234575 : unsigned int i;
106 :
107 234575 : i = vector_empty_slot(v);
108 234575 : vector_ensure(v, i);
109 :
110 234575 : if (v->index[i])
111 0 : v->count--;
112 234575 : if (val)
113 234575 : v->count++;
114 234575 : v->index[i] = val;
115 :
116 234575 : if (v->active <= i)
117 234575 : v->active = i + 1;
118 :
119 234575 : return i;
120 : }
121 :
122 : /* Set value to specified index slot. */
123 1060 : int vector_set_index(vector v, unsigned int i, void *val)
124 : {
125 1060 : vector_ensure(v, i);
126 :
127 1060 : if (v->index[i])
128 0 : v->count--;
129 1060 : if (val)
130 1060 : v->count++;
131 1060 : v->index[i] = val;
132 :
133 1060 : if (v->active <= i)
134 872 : v->active = i + 1;
135 :
136 1060 : return i;
137 : }
138 :
139 : /* Look up vector. */
140 6123 : void *vector_lookup(vector v, unsigned int i)
141 : {
142 6123 : if (i >= v->active)
143 : return NULL;
144 6123 : return v->index[i];
145 : }
146 :
147 : /* Lookup vector, ensure it. */
148 0 : void *vector_lookup_ensure(vector v, unsigned int i)
149 : {
150 0 : vector_ensure(v, i);
151 0 : return v->index[i];
152 : }
153 :
154 : /* Unset value at specified index slot. */
155 40757 : void vector_unset(vector v, unsigned int i)
156 : {
157 40757 : if (i >= v->alloced)
158 : return;
159 :
160 40757 : if (v->index[i])
161 40672 : v->count--;
162 :
163 40757 : v->index[i] = NULL;
164 :
165 40757 : if (i + 1 == v->active) {
166 7553 : v->active--;
167 40757 : while (i && v->index[--i] == NULL && v->active--)
168 : ; /* Is this ugly ? */
169 : }
170 : }
171 :
172 0 : void vector_remove(vector v, unsigned int ix)
173 : {
174 0 : if (ix >= v->active)
175 : return;
176 :
177 0 : if (v->index[ix])
178 0 : v->count--;
179 :
180 0 : int n = (--v->active) - ix;
181 :
182 0 : memmove(&v->index[ix], &v->index[ix + 1], n * sizeof(void *));
183 0 : v->index[v->active] = NULL;
184 : }
185 :
186 212 : void vector_compact(vector v)
187 : {
188 719 : for (unsigned int i = 0; i < vector_active(v); ++i) {
189 507 : if (vector_slot(v, i) == NULL) {
190 0 : vector_remove(v, i);
191 0 : --i;
192 : }
193 : }
194 212 : }
195 :
196 0 : void vector_unset_value(vector v, void *val)
197 : {
198 0 : size_t i;
199 :
200 0 : for (i = 0; i < v->active; i++)
201 0 : if (v->index[i] == val) {
202 0 : v->index[i] = NULL;
203 0 : v->count--;
204 0 : break;
205 : }
206 :
207 0 : if (i + 1 == v->active)
208 0 : do
209 0 : v->active--;
210 0 : while (i && v->index[--i] == NULL);
211 0 : }
212 :
213 0 : void vector_to_array(vector v, void ***dest, int *argc)
214 : {
215 0 : *dest = XCALLOC(MTYPE_TMP, sizeof(void *) * v->active);
216 0 : memcpy(*dest, v->index, sizeof(void *) * v->active);
217 0 : *argc = v->active;
218 0 : }
219 :
220 212 : vector array_to_vector(void **src, int argc)
221 : {
222 212 : vector v = vector_init(VECTOR_MIN_SIZE);
223 :
224 804 : for (int i = 0; i < argc; i++)
225 592 : vector_set_index(v, i, src[i]);
226 212 : return v;
227 : }
|