]> git.proxmox.com Git - ovs.git/blame - lib/svec.c
dpif-netdev: Add ovs-appctl dpif-netdev/pmd-rxq-rebalance.
[ovs.git] / lib / svec.c
CommitLineData
064af421 1/*
cb22974d 2 * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
064af421 3 *
a14bc59f
BP
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
064af421 7 *
a14bc59f
BP
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
064af421
BP
15 */
16
17#include <config.h>
18#include "svec.h"
064af421
BP
19#include <ctype.h>
20#include <stdlib.h>
21#include <string.h>
3e8a2ad1 22#include "openvswitch/dynamic-string.h"
064af421 23#include "util.h"
e6211adc 24#include "openvswitch/vlog.h"
064af421 25
d98e6007 26VLOG_DEFINE_THIS_MODULE(svec);
5136ce49 27
064af421
BP
28void
29svec_init(struct svec *svec)
30{
31 svec->names = NULL;
32 svec->n = 0;
33 svec->allocated = 0;
34}
35
36void
37svec_clone(struct svec *svec, const struct svec *other)
38{
39 svec_init(svec);
40 svec_append(svec, other);
41}
42
43void
44svec_destroy(struct svec *svec)
45{
46 svec_clear(svec);
47 free(svec->names);
48}
49
50void
d295e8e9 51svec_clear(struct svec *svec)
064af421
BP
52{
53 size_t i;
54
55 for (i = 0; i < svec->n; i++) {
56 free(svec->names[i]);
57 }
58 svec->n = 0;
59}
60
8ecd5308
BP
61bool
62svec_is_empty(const struct svec *svec)
63{
64 return svec->n == 0;
65}
66
064af421
BP
67void
68svec_add(struct svec *svec, const char *name)
69{
70 svec_add_nocopy(svec, xstrdup(name));
71}
72
73void
74svec_del(struct svec *svec, const char *name)
75{
76 size_t offset;
77
78 offset = svec_find(svec, name);
79 if (offset != SIZE_MAX) {
80 free(svec->names[offset]);
81 memmove(&svec->names[offset], &svec->names[offset + 1],
82 sizeof *svec->names * (svec->n - offset - 1));
83 svec->n--;
84 }
85}
86
87static void
88svec_expand(struct svec *svec)
89{
90 if (svec->n >= svec->allocated) {
91 svec->names = x2nrealloc(svec->names, &svec->allocated,
92 sizeof *svec->names);
93 }
94}
95
96void
97svec_add_nocopy(struct svec *svec, char *name)
98{
99 svec_expand(svec);
100 svec->names[svec->n++] = name;
101}
102
103void
104svec_append(struct svec *svec, const struct svec *other)
105{
106 size_t i;
107 for (i = 0; i < other->n; i++) {
108 svec_add(svec, other->names[i]);
109 }
110}
111
112void
113svec_terminate(struct svec *svec)
114{
115 svec_expand(svec);
116 svec->names[svec->n] = NULL;
117}
118
119static int
120compare_strings(const void *a_, const void *b_)
121{
122 char *const *a = a_;
123 char *const *b = b_;
124 return strcmp(*a, *b);
125}
126
127void
128svec_sort(struct svec *svec)
129{
316d0932
LR
130 if (svec->n) {
131 qsort(svec->names, svec->n, sizeof *svec->names, compare_strings);
132 }
064af421
BP
133}
134
135void
136svec_sort_unique(struct svec *svec)
137{
138 svec_sort(svec);
139 svec_unique(svec);
140}
141
142void
143svec_unique(struct svec *svec)
144{
cb22974d 145 ovs_assert(svec_is_sorted(svec));
064af421
BP
146 if (svec->n > 1) {
147 /* This algorithm is lazy and sub-optimal, but it's "obviously correct"
148 * and asymptotically optimal . */
149 struct svec tmp;
150 size_t i;
151
152 svec_init(&tmp);
153 svec_add(&tmp, svec->names[0]);
154 for (i = 1; i < svec->n; i++) {
155 if (strcmp(svec->names[i - 1], svec->names[i])) {
156 svec_add(&tmp, svec->names[i]);
157 }
158 }
159 svec_swap(&tmp, svec);
160 svec_destroy(&tmp);
161 }
162}
163
164void
165svec_compact(struct svec *svec)
166{
167 size_t i, j;
168
169 for (i = j = 0; i < svec->n; i++) {
170 if (svec->names[i] != NULL) {
171 svec->names[j++] = svec->names[i];
172 }
173 }
174 svec->n = j;
175}
176
177void
178svec_diff(const struct svec *a, const struct svec *b,
179 struct svec *a_only, struct svec *both, struct svec *b_only)
180{
181 size_t i, j;
182
cb22974d
BP
183 ovs_assert(svec_is_sorted(a));
184 ovs_assert(svec_is_sorted(b));
064af421
BP
185 if (a_only) {
186 svec_init(a_only);
187 }
188 if (both) {
189 svec_init(both);
190 }
191 if (b_only) {
192 svec_init(b_only);
193 }
194 for (i = j = 0; i < a->n && j < b->n; ) {
195 int cmp = strcmp(a->names[i], b->names[j]);
196 if (cmp < 0) {
197 if (a_only) {
198 svec_add(a_only, a->names[i]);
199 }
200 i++;
201 } else if (cmp > 0) {
202 if (b_only) {
203 svec_add(b_only, b->names[j]);
204 }
205 j++;
206 } else {
207 if (both) {
208 svec_add(both, a->names[i]);
209 }
210 i++;
211 j++;
212 }
213 }
214 if (a_only) {
215 for (; i < a->n; i++) {
216 svec_add(a_only, a->names[i]);
217 }
218 }
219 if (b_only) {
220 for (; j < b->n; j++) {
221 svec_add(b_only, b->names[j]);
222 }
223 }
224}
225
226bool
227svec_contains(const struct svec *svec, const char *name)
228{
229 return svec_find(svec, name) != SIZE_MAX;
230}
231
232size_t
233svec_find(const struct svec *svec, const char *name)
234{
235 char **p;
236
cb22974d 237 ovs_assert(svec_is_sorted(svec));
064af421
BP
238 p = bsearch(&name, svec->names, svec->n, sizeof *svec->names,
239 compare_strings);
240 return p ? p - svec->names : SIZE_MAX;
241}
242
243bool
244svec_is_sorted(const struct svec *svec)
245{
246 size_t i;
247
248 for (i = 1; i < svec->n; i++) {
249 if (strcmp(svec->names[i - 1], svec->names[i]) > 0) {
250 return false;
251 }
252 }
253 return true;
254}
255
256bool
257svec_is_unique(const struct svec *svec)
258{
259 return svec_get_duplicate(svec) == NULL;
260}
261
262const char *
263svec_get_duplicate(const struct svec *svec)
264{
cb22974d 265 ovs_assert(svec_is_sorted(svec));
064af421
BP
266 if (svec->n > 1) {
267 size_t i;
268 for (i = 1; i < svec->n; i++) {
269 if (!strcmp(svec->names[i - 1], svec->names[i])) {
270 return svec->names[i];
271 }
272 }
273 }
274 return NULL;
275}
276
277void
278svec_swap(struct svec *a, struct svec *b)
279{
280 struct svec tmp = *a;
281 *a = *b;
282 *b = tmp;
283}
284
285void
286svec_print(const struct svec *svec, const char *title)
287{
288 size_t i;
289
290 printf("%s:\n", title);
291 for (i = 0; i < svec->n; i++) {
292 printf("\"%s\"\n", svec->names[i]);
293 }
294}
295
296/* Breaks 'words' into words at white space, respecting shell-like quoting
297 * conventions, and appends the words to 'svec'. */
298void
299svec_parse_words(struct svec *svec, const char *words)
300{
301 struct ds word = DS_EMPTY_INITIALIZER;
302 const char *p, *q;
303
304 for (p = words; *p != '\0'; p = q) {
305 int quote = 0;
306
307 while (isspace((unsigned char) *p)) {
308 p++;
309 }
310 if (*p == '\0') {
311 break;
312 }
313
314 ds_clear(&word);
315 for (q = p; *q != '\0'; q++) {
316 if (*q == quote) {
317 quote = 0;
318 } else if (*q == '\'' || *q == '"') {
319 quote = *q;
320 } else if (*q == '\\' && (!quote || quote == '"')) {
321 q++;
322 if (*q == '\0') {
323 VLOG_WARN("%s: ends in trailing backslash", words);
324 break;
325 }
326 ds_put_char(&word, *q);
327 } else if (isspace((unsigned char) *q) && !quote) {
328 q++;
329 break;
330 } else {
331 ds_put_char(&word, *q);
332 }
333 }
334 svec_add(svec, ds_cstr(&word));
335 if (quote) {
336 VLOG_WARN("%s: word ends inside quoted string", words);
337 }
338 }
339 ds_destroy(&word);
340}
341
342bool
343svec_equal(const struct svec *a, const struct svec *b)
344{
345 size_t i;
346
347 if (a->n != b->n) {
348 return false;
349 }
350 for (i = 0; i < a->n; i++) {
351 if (strcmp(a->names[i], b->names[i])) {
352 return false;
353 }
354 }
355 return true;
356}
357
358char *
359svec_join(const struct svec *svec,
360 const char *delimiter, const char *terminator)
361{
362 struct ds ds;
363 size_t i;
364
365 ds_init(&ds);
366 for (i = 0; i < svec->n; i++) {
367 if (i) {
368 ds_put_cstr(&ds, delimiter);
369 }
370 ds_put_cstr(&ds, svec->names[i]);
371 }
372 ds_put_cstr(&ds, terminator);
373 return ds_cstr(&ds);
374}
375
376const char *
377svec_back(const struct svec *svec)
378{
cb22974d 379 ovs_assert(svec->n);
064af421
BP
380 return svec->names[svec->n - 1];
381}
382
383void
384svec_pop_back(struct svec *svec)
385{
cb22974d 386 ovs_assert(svec->n);
064af421
BP
387 free(svec->names[--svec->n]);
388}