]>
git.proxmox.com Git - mirror_ovs.git/blob - lib/svec.c
2 * Copyright (c) 2008, 2009, 2010 Nicira Networks.
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:
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 #include "dynamic-string.h"
27 VLOG_DEFINE_THIS_MODULE(svec
)
30 svec_init(struct svec
*svec
)
38 svec_clone(struct svec
*svec
, const struct svec
*other
)
41 svec_append(svec
, other
);
45 svec_destroy(struct svec
*svec
)
52 svec_clear(struct svec
*svec
)
56 for (i
= 0; i
< svec
->n
; i
++) {
63 svec_is_empty(const struct svec
*svec
)
69 svec_add(struct svec
*svec
, const char *name
)
71 svec_add_nocopy(svec
, xstrdup(name
));
75 svec_del(struct svec
*svec
, const char *name
)
79 offset
= svec_find(svec
, name
);
80 if (offset
!= SIZE_MAX
) {
81 free(svec
->names
[offset
]);
82 memmove(&svec
->names
[offset
], &svec
->names
[offset
+ 1],
83 sizeof *svec
->names
* (svec
->n
- offset
- 1));
89 svec_expand(struct svec
*svec
)
91 if (svec
->n
>= svec
->allocated
) {
92 svec
->names
= x2nrealloc(svec
->names
, &svec
->allocated
,
98 svec_add_nocopy(struct svec
*svec
, char *name
)
101 svec
->names
[svec
->n
++] = name
;
105 svec_append(struct svec
*svec
, const struct svec
*other
)
108 for (i
= 0; i
< other
->n
; i
++) {
109 svec_add(svec
, other
->names
[i
]);
114 svec_terminate(struct svec
*svec
)
117 svec
->names
[svec
->n
] = NULL
;
121 compare_strings(const void *a_
, const void *b_
)
125 return strcmp(*a
, *b
);
129 svec_sort(struct svec
*svec
)
131 qsort(svec
->names
, svec
->n
, sizeof *svec
->names
, compare_strings
);
135 svec_sort_unique(struct svec
*svec
)
142 svec_unique(struct svec
*svec
)
144 assert(svec_is_sorted(svec
));
146 /* This algorithm is lazy and sub-optimal, but it's "obviously correct"
147 * and asymptotically optimal . */
152 svec_add(&tmp
, svec
->names
[0]);
153 for (i
= 1; i
< svec
->n
; i
++) {
154 if (strcmp(svec
->names
[i
- 1], svec
->names
[i
])) {
155 svec_add(&tmp
, svec
->names
[i
]);
158 svec_swap(&tmp
, svec
);
164 svec_compact(struct svec
*svec
)
168 for (i
= j
= 0; i
< svec
->n
; i
++) {
169 if (svec
->names
[i
] != NULL
) {
170 svec
->names
[j
++] = svec
->names
[i
];
177 svec_diff(const struct svec
*a
, const struct svec
*b
,
178 struct svec
*a_only
, struct svec
*both
, struct svec
*b_only
)
182 assert(svec_is_sorted(a
));
183 assert(svec_is_sorted(b
));
193 for (i
= j
= 0; i
< a
->n
&& j
< b
->n
; ) {
194 int cmp
= strcmp(a
->names
[i
], b
->names
[j
]);
197 svec_add(a_only
, a
->names
[i
]);
200 } else if (cmp
> 0) {
202 svec_add(b_only
, b
->names
[j
]);
207 svec_add(both
, a
->names
[i
]);
214 for (; i
< a
->n
; i
++) {
215 svec_add(a_only
, a
->names
[i
]);
219 for (; j
< b
->n
; j
++) {
220 svec_add(b_only
, b
->names
[j
]);
226 svec_contains(const struct svec
*svec
, const char *name
)
228 return svec_find(svec
, name
) != SIZE_MAX
;
232 svec_find(const struct svec
*svec
, const char *name
)
236 assert(svec_is_sorted(svec
));
237 p
= bsearch(&name
, svec
->names
, svec
->n
, sizeof *svec
->names
,
239 return p
? p
- svec
->names
: SIZE_MAX
;
243 svec_is_sorted(const struct svec
*svec
)
247 for (i
= 1; i
< svec
->n
; i
++) {
248 if (strcmp(svec
->names
[i
- 1], svec
->names
[i
]) > 0) {
256 svec_is_unique(const struct svec
*svec
)
258 return svec_get_duplicate(svec
) == NULL
;
262 svec_get_duplicate(const struct svec
*svec
)
264 assert(svec_is_sorted(svec
));
267 for (i
= 1; i
< svec
->n
; i
++) {
268 if (!strcmp(svec
->names
[i
- 1], svec
->names
[i
])) {
269 return svec
->names
[i
];
277 svec_swap(struct svec
*a
, struct svec
*b
)
279 struct svec tmp
= *a
;
285 svec_print(const struct svec
*svec
, const char *title
)
289 printf("%s:\n", title
);
290 for (i
= 0; i
< svec
->n
; i
++) {
291 printf("\"%s\"\n", svec
->names
[i
]);
295 /* Breaks 'words' into words at white space, respecting shell-like quoting
296 * conventions, and appends the words to 'svec'. */
298 svec_parse_words(struct svec
*svec
, const char *words
)
300 struct ds word
= DS_EMPTY_INITIALIZER
;
303 for (p
= words
; *p
!= '\0'; p
= q
) {
306 while (isspace((unsigned char) *p
)) {
314 for (q
= p
; *q
!= '\0'; q
++) {
317 } else if (*q
== '\'' || *q
== '"') {
319 } else if (*q
== '\\' && (!quote
|| quote
== '"')) {
322 VLOG_WARN("%s: ends in trailing backslash", words
);
325 ds_put_char(&word
, *q
);
326 } else if (isspace((unsigned char) *q
) && !quote
) {
330 ds_put_char(&word
, *q
);
333 svec_add(svec
, ds_cstr(&word
));
335 VLOG_WARN("%s: word ends inside quoted string", words
);
342 svec_equal(const struct svec
*a
, const struct svec
*b
)
349 for (i
= 0; i
< a
->n
; i
++) {
350 if (strcmp(a
->names
[i
], b
->names
[i
])) {
358 svec_join(const struct svec
*svec
,
359 const char *delimiter
, const char *terminator
)
365 for (i
= 0; i
< svec
->n
; i
++) {
367 ds_put_cstr(&ds
, delimiter
);
369 ds_put_cstr(&ds
, svec
->names
[i
]);
371 ds_put_cstr(&ds
, terminator
);
375 /* Breaks 's' into tokens at any character in 'delimiters', and appends each
376 * token to 'svec'. Empty tokens are not added. */
378 svec_split(struct svec
*svec
, const char *s_
, const char *delimiters
)
380 char *s
= xstrdup(s_
);
381 char *save_ptr
= NULL
;
384 for (token
= strtok_r(s
, delimiters
, &save_ptr
); token
!= NULL
;
385 token
= strtok_r(NULL
, delimiters
, &save_ptr
)) {
386 svec_add(svec
, token
);
392 svec_back(const struct svec
*svec
)
395 return svec
->names
[svec
->n
- 1];
399 svec_pop_back(struct svec
*svec
)
402 free(svec
->names
[--svec
->n
]);