]>
git.proxmox.com Git - mirror_ovs.git/blob - lib/smap.c
1 /* Copyright (c) 2012, 2014, 2015, 2016 Nicira, Inc.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License. */
21 #include "openvswitch/json.h"
26 static struct smap_node
*smap_add__(struct smap
*, char *, void *,
28 static struct smap_node
*smap_find__(const struct smap
*, const char *key
,
29 size_t key_len
, size_t hash
);
30 static int compare_nodes_by_key(const void *, const void *);
32 /* Public Functions. */
35 smap_init(struct smap
*smap
)
37 hmap_init(&smap
->map
);
41 smap_destroy(struct smap
*smap
)
45 hmap_destroy(&smap
->map
);
49 /* Adds 'key' paired with 'value' to 'smap'. It is the caller's responsibility
50 * to avoid duplicate keys if desirable. */
52 smap_add(struct smap
*smap
, const char *key
, const char *value
)
54 size_t key_len
= strlen(key
);
55 return smap_add__(smap
, xmemdup0(key
, key_len
), xstrdup(value
),
56 hash_bytes(key
, key_len
, 0));
59 /* Adds 'key' paired with 'value' to 'smap'. Takes ownership of 'key' and
60 * 'value' (which will eventually be freed with free()). It is the caller's
61 * responsibility to avoid duplicate keys if desirable. */
63 smap_add_nocopy(struct smap
*smap
, char *key
, char *value
)
65 return smap_add__(smap
, key
, value
, hash_bytes(key
, strlen(key
), 0));
68 /* Attempts to add 'key' to 'smap' associated with 'value'. If 'key' already
69 * exists in 'smap', does nothing and returns false. Otherwise, performs the
70 * addition and returns true. */
72 smap_add_once(struct smap
*smap
, const char *key
, const char *value
)
74 if (!smap_get(smap
, key
)) {
75 smap_add(smap
, key
, value
);
82 /* Adds 'key' paired with a value derived from 'format' (similar to printf).
83 * It is the caller's responsibility to avoid duplicate keys if desirable. */
85 smap_add_format(struct smap
*smap
, const char *key
, const char *format
, ...)
91 va_start(args
, format
);
92 value
= xvasprintf(format
, args
);
95 key_len
= strlen(key
);
96 smap_add__(smap
, xmemdup0(key
, key_len
), value
,
97 hash_bytes(key
, key_len
, 0));
100 /* Adds 'key' paired with a string representation of 'addr'. It is the
101 * caller's responsibility to avoid duplicate keys if desirable. */
103 smap_add_ipv6(struct smap
*smap
, const char *key
, struct in6_addr
*addr
)
105 char buf
[INET6_ADDRSTRLEN
];
106 ipv6_string_mapped(buf
, addr
);
107 smap_add(smap
, key
, buf
);
110 /* Searches for 'key' in 'smap'. If it does not already exists, adds it.
111 * Otherwise, changes its value to 'value'. The caller retains ownership of
114 smap_replace(struct smap
*smap
, const char *key
, const char *value
)
116 smap_replace_nocopy(smap
, key
, xstrdup(value
));
119 /* Searches for 'key' in 'smap'. If it does not already exists, adds it.
120 * Otherwise, changes its value to 'value'. Takes ownership of 'value'. */
122 smap_replace_nocopy(struct smap
*smap
, const char *key
, char *value
)
124 size_t key_len
= strlen(key
);
125 size_t hash
= hash_bytes(key
, key_len
, 0);
127 struct smap_node
*node
;
129 node
= smap_find__(smap
, key
, key_len
, hash
);
134 smap_add__(smap
, xmemdup0(key
, key_len
), value
, hash
);
138 /* If 'key' is in 'smap', removes it. Otherwise does nothing. */
140 smap_remove(struct smap
*smap
, const char *key
)
142 struct smap_node
*node
= smap_get_node(smap
, key
);
145 smap_remove_node(smap
, node
);
149 /* Removes 'node' from 'smap'. */
151 smap_remove_node(struct smap
*smap
, struct smap_node
*node
)
153 hmap_remove(&smap
->map
, &node
->node
);
159 /* Deletes 'node' from 'smap'.
161 * If 'keyp' is nonnull, stores the node's key in '*keyp' and transfers
162 * ownership to the caller. Otherwise, frees the node's key. Similarly for
163 * 'valuep' and the node's value. */
165 smap_steal(struct smap
*smap
, struct smap_node
*node
,
166 char **keyp
, char **valuep
)
175 *valuep
= node
->value
;
180 hmap_remove(&smap
->map
, &node
->node
);
184 /* Removes all key-value pairs from 'smap'. */
186 smap_clear(struct smap
*smap
)
188 struct smap_node
*node
, *next
;
190 SMAP_FOR_EACH_SAFE (node
, next
, smap
) {
191 smap_remove_node(smap
, node
);
195 /* Returns the value associated with 'key' in 'smap'.
196 * If 'smap' does not contain 'key', returns NULL. */
198 smap_get(const struct smap
*smap
, const char *key
)
200 return smap_get_def(smap
, key
, NULL
);
203 /* Returns the value associated with 'key' in 'smap'.
204 * If 'smap' does not contain 'key', returns 'def'. */
206 smap_get_def(const struct smap
*smap
, const char *key
, const char *def
)
208 struct smap_node
*node
= smap_get_node(smap
, key
);
209 return node
? node
->value
: def
;
212 /* Returns the node associated with 'key' in 'smap', or NULL. */
214 smap_get_node(const struct smap
*smap
, const char *key
)
216 size_t key_len
= strlen(key
);
217 return smap_find__(smap
, key
, key_len
, hash_bytes(key
, key_len
, 0));
220 /* Gets the value associated with 'key' in 'smap' and converts it to a boolean.
221 * If 'key' is not in 'smap', or its value is neither "true" nor "false",
224 smap_get_bool(const struct smap
*smap
, const char *key
, bool def
)
226 const char *value
= smap_get_def(smap
, key
, "");
228 return strcasecmp("false", value
) != 0;
230 return !strcasecmp("true", value
);
234 /* Gets the value associated with 'key' in 'smap' and converts it to an int.
235 * If 'key' is not in 'smap' or a valid integer can't be parsed from it's
236 * value, returns 'def'. */
238 smap_get_int(const struct smap
*smap
, const char *key
, int def
)
240 const char *value
= smap_get(smap
, key
);
243 if (!value
|| !str_to_int(value
, 10, &i_value
)) {
250 /* Gets the value associated with 'key' in 'smap' and converts it to an
251 * unsigned int. If 'key' is not in 'smap' or a valid unsigned integer
252 * can't be parsed from it's value, returns 'def'. */
254 smap_get_uint(const struct smap
*smap
, const char *key
, unsigned int def
)
256 const char *value
= smap_get(smap
, key
);
257 unsigned int u_value
;
259 if (!value
|| !str_to_uint(value
, 10, &u_value
)) {
266 /* Gets the value associated with 'key' in 'smap' and converts it to an
267 * unsigned long long. If 'key' is not in 'smap' or a valid number can't be
268 * parsed from it's value, returns 'def'. */
269 unsigned long long int
270 smap_get_ullong(const struct smap
*smap
, const char *key
,
271 unsigned long long def
)
273 const char *value
= smap_get(smap
, key
);
274 unsigned long long ull_value
;
276 if (!value
|| !str_to_ullong(value
, 10, &ull_value
)) {
283 /* Gets the value associated with 'key' in 'smap' and converts it to a UUID
284 * using uuid_from_string(). Returns true if successful, false if 'key' is not
285 * in 'smap' or if 'key' does not have the correct syntax for a UUID. */
287 smap_get_uuid(const struct smap
*smap
, const char *key
, struct uuid
*uuid
)
289 return uuid_from_string(uuid
, smap_get_def(smap
, key
, ""));
292 /* Returns true of there are no elements in 'smap'. */
294 smap_is_empty(const struct smap
*smap
)
296 return hmap_is_empty(&smap
->map
);
299 /* Returns the number of elements in 'smap'. */
301 smap_count(const struct smap
*smap
)
303 return hmap_count(&smap
->map
);
306 /* Initializes 'dst' as a clone of 'src. */
308 smap_clone(struct smap
*dst
, const struct smap
*src
)
310 const struct smap_node
*node
;
313 SMAP_FOR_EACH (node
, src
) {
314 smap_add__(dst
, xstrdup(node
->key
), xstrdup(node
->value
),
319 /* Returns an array of nodes sorted on key or NULL if 'smap' is empty. The
320 * caller is responsible for freeing this array. */
321 const struct smap_node
**
322 smap_sort(const struct smap
*smap
)
324 if (smap_is_empty(smap
)) {
327 const struct smap_node
**nodes
;
328 struct smap_node
*node
;
331 n
= smap_count(smap
);
332 nodes
= xmalloc(n
* sizeof *nodes
);
334 SMAP_FOR_EACH (node
, smap
) {
339 qsort(nodes
, n
, sizeof *nodes
, compare_nodes_by_key
);
345 /* Adds each of the key-value pairs from 'json' (which must be a JSON object
346 * whose values are strings) to 'smap'.
348 * The caller must have initialized 'smap'.
350 * The caller retains ownership of 'json' and everything in it. */
352 smap_from_json(struct smap
*smap
, const struct json
*json
)
354 const struct shash_node
*node
;
356 SHASH_FOR_EACH (node
, json_object(json
)) {
357 const struct json
*value
= node
->data
;
358 smap_add(smap
, node
->name
, json_string(value
));
362 /* Returns a JSON object that maps from the keys in 'smap' to their values.
364 * The caller owns the returned value and must eventually json_destroy() it.
366 * The caller retains ownership of 'smap' and everything in it. */
368 smap_to_json(const struct smap
*smap
)
370 const struct smap_node
*node
;
373 json
= json_object_create();
374 SMAP_FOR_EACH (node
, smap
) {
375 json_object_put_string(json
, node
->key
, node
->value
);
380 /* Returns true if the two maps are equal, meaning that they have the same set
381 * of key-value pairs.
384 smap_equal(const struct smap
*smap1
, const struct smap
*smap2
)
386 if (smap_count(smap1
) != smap_count(smap2
)) {
390 const struct smap_node
*node
;
391 SMAP_FOR_EACH (node
, smap1
) {
392 const char *value2
= smap_get(smap2
, node
->key
);
393 if (!value2
|| strcmp(node
->value
, value2
)) {
400 /* Private Helpers. */
402 static struct smap_node
*
403 smap_add__(struct smap
*smap
, char *key
, void *value
, size_t hash
)
405 struct smap_node
*node
= xmalloc(sizeof *node
);
408 hmap_insert(&smap
->map
, &node
->node
, hash
);
412 static struct smap_node
*
413 smap_find__(const struct smap
*smap
, const char *key
, size_t key_len
,
416 struct smap_node
*node
;
418 HMAP_FOR_EACH_WITH_HASH (node
, node
, hash
, &smap
->map
) {
419 if (!strncmp(node
->key
, key
, key_len
) && !node
->key
[key_len
]) {
428 compare_nodes_by_key(const void *a_
, const void *b_
)
430 const struct smap_node
*const *a
= a_
;
431 const struct smap_node
*const *b
= b_
;
432 return strcmp((*a
)->key
, (*b
)->key
);