]> git.proxmox.com Git - mirror_ovs.git/blob - lib/namemap.c
ovsdb-idl: Fix iteration over tracked rows with no actual data.
[mirror_ovs.git] / lib / namemap.c
1 /*
2 * Copyright (c) 2017-2018 Nicira, Inc.
3 *
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:
7 *
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.
15 */
16
17 #include <config.h>
18 #include "openvswitch/namemap.h"
19 #include <ctype.h>
20 #include "hash.h"
21 #include "openvswitch/dynamic-string.h"
22 #include "openvswitch/json.h"
23
24 void
25 namemap_init(struct namemap *map)
26 {
27 hmap_init(&map->by_name);
28 hmap_init(&map->by_number);
29 }
30
31 struct namemap_node *
32 namemap_find_by_name(const struct namemap *map, const char *name)
33 {
34 struct namemap_node *node;
35
36 HMAP_FOR_EACH_WITH_HASH (node, name_node, hash_string(name, 0),
37 &map->by_name) {
38 if (!strcmp(name, node->name)) {
39 return node;
40 }
41 }
42 return NULL;
43 }
44
45 struct namemap_node *
46 namemap_find_by_number(const struct namemap *map, uint32_t number)
47 {
48 struct namemap_node *node;
49
50 HMAP_FOR_EACH_IN_BUCKET (node, number_node, hash_int(number, 0),
51 &map->by_number) {
52 if (node->number == number) {
53 return node;
54 }
55 }
56 return NULL;
57 }
58
59 void
60 namemap_put(struct namemap *map, uint32_t number, const char *name)
61 {
62 struct namemap_node *node;
63
64 /* Look for duplicate name. */
65 node = namemap_find_by_name(map, name);
66 if (node) {
67 if (node->number != number) {
68 node->duplicate = true;
69 }
70 return;
71 }
72
73 /* Look for duplicate number. */
74 node = namemap_find_by_number(map, number);
75 if (node) {
76 node->duplicate = true;
77 return;
78 }
79
80 /* Add new node. */
81 node = xmalloc(sizeof *node);
82 hmap_insert(&map->by_number, &node->number_node, hash_int(number, 0));
83 hmap_insert(&map->by_name, &node->name_node, hash_string(name, 0));
84 node->number = number;
85 node->name = xstrdup(name);
86 node->duplicate = false;
87 }
88
89 void
90 namemap_destroy(struct namemap *map)
91 {
92 if (map) {
93 struct namemap_node *node, *next;
94
95 HMAP_FOR_EACH_SAFE (node, next, name_node, &map->by_name) {
96 hmap_remove(&map->by_name, &node->name_node);
97 hmap_remove(&map->by_number, &node->number_node);
98 free(node->name);
99 free(node);
100 }
101 hmap_destroy(&map->by_name);
102 hmap_destroy(&map->by_number);
103 }
104 }
105
106 /* A table or port name doesn't need to be quoted if it is alphanumeric and
107 * starts with a letter. */
108 static bool
109 name_needs_quotes(const char *name)
110 {
111 if (!isalpha((unsigned char) name[0])) {
112 return true;
113 }
114
115 for (const char *p = name + 1; *p; p++) {
116 if (!isalnum((unsigned char) *p)) {
117 return true;
118 }
119 }
120 return false;
121 }
122
123 /* Appends port or table 'name' to 's', quoting it if necessary. */
124 void
125 namemap_put_name(const char *name, struct ds *s)
126 {
127 if (name_needs_quotes(name)) {
128 json_string_escape(name, s);
129 } else {
130 ds_put_cstr(s, name);
131 }
132 }