3abc4ecc65cb2e7c5d374af4f2cc316918b4d9c3
[pspp] / src / libpspp / string-map.h
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2009, 2011 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #ifndef LIBPSPP_STRING_MAP_H
18 #define LIBPSPP_STRING_MAP_H
19
20 /* Map from a unique string key to a string value.
21
22    This is a convenient wrapper around a "struct hmap" for storing string
23    key-value pairs. */
24
25 #include <stdbool.h>
26 #include "libpspp/hmap.h"
27
28 struct string_set;
29
30 /* A node within a string map. */
31 struct string_map_node
32   {
33     struct hmap_node hmap_node;
34     char *key;
35     char *value;
36   };
37
38 /* Returns the string key within NODE.  The caller must not modify or free the
39    returned string. */
40 static inline const char *
41 string_map_node_get_key (const struct string_map_node *node)
42 {
43   return node->key;
44 }
45
46 /* Returns the string key within NODE.  The caller must not free the returned
47    string. */
48 static inline const char *
49 string_map_node_get_value (const struct string_map_node *node)
50 {
51   return node->value;
52 }
53
54 /* Returns the string key within NODE.  The caller must not free the returned
55    string. */
56 static inline char *
57 string_map_node_get_value_rw (struct string_map_node *node)
58 {
59   return node->value;
60 }
61
62 char *string_map_node_swap_value (struct string_map_node *,
63                                   const char *new_value);
64 char *string_map_node_swap_value_nocopy (struct string_map_node *,
65                                          char *new_value);
66 void string_map_node_set_value (struct string_map_node *, const char *value);
67 void string_map_node_set_value_nocopy (struct string_map_node *, char *value);
68 void string_map_node_destroy (struct string_map_node *);
69 \f
70 /* Unordered map from unique string keys to string values. */
71 struct string_map
72   {
73     struct hmap hmap;
74   };
75
76 /* Suitable for use as the initializer for a string_map named MAP.  Typical
77    usage:
78        struct string_map map = STRING_MAP_INITIALIZER (map);
79    STRING_MAP_INITIALIZER is an alternative to calling string_map_init. */
80 #define STRING_MAP_INITIALIZER(MAP) { HMAP_INITIALIZER ((MAP).hmap) }
81
82 void string_map_init (struct string_map *);
83 void string_map_clone (struct string_map *, const struct string_map *);
84 void string_map_swap (struct string_map *, struct string_map *);
85 void string_map_destroy (struct string_map *);
86
87 static inline size_t string_map_count (const struct string_map *);
88 static inline bool string_map_is_empty (const struct string_map *);
89
90 bool string_map_contains (const struct string_map *, const char *);
91 const char *string_map_find (const struct string_map *, const char *);
92 const char *string_map_find__ (const struct string_map *, const char *,
93                                size_t length);
94 struct string_map_node *string_map_find_node (const struct string_map *,
95                                               const char *);
96 struct string_map_node *string_map_find_node__ (const struct string_map *,
97                                                 const char *, size_t length);
98 char *string_map_find_and_delete (struct string_map *, const char *key);
99
100 struct string_map_node *string_map_insert (struct string_map *,
101                                            const char *key, const char *value);
102 struct string_map_node *string_map_insert_nocopy (struct string_map *,
103                                                   char *key, char *value);
104 struct string_map_node *string_map_replace (struct string_map *,
105                                            const char *key, const char *value);
106 struct string_map_node *string_map_replace_nocopy (struct string_map *,
107                                                    char *key, char *value);
108 bool string_map_delete (struct string_map *, const char *);
109 void string_map_delete_node (struct string_map *, struct string_map_node *);
110 void string_map_delete_nofree (struct string_map *, struct string_map_node *);
111
112 void string_map_clear (struct string_map *);
113 void string_map_insert_map (struct string_map *, const struct string_map *);
114 void string_map_replace_map (struct string_map *, const struct string_map *);
115
116 void string_map_get_keys (const struct string_map *, struct string_set *);
117 void string_map_get_values (const struct string_map *, struct string_set *);
118
119 static inline struct string_map_node *string_map_first (
120   const struct string_map *);
121 static inline struct string_map_node *string_map_next (
122   const struct string_map *, const struct string_map_node *);
123
124 /* Macros for conveniently iterating through a string_map, e.g. to print all of
125    the key-value pairs in "my_map":
126
127    struct string_map_node *node;
128    const char *key, *value;
129
130    STRING_MAP_FOR_EACH_KEY_VALUE (key, value, node, &my_map)
131      printf ("%s=%s\n", key, value);
132    */
133 #define STRING_MAP_FOR_EACH_NODE(NODE, MAP)                     \
134         for ((NODE) = string_map_first (MAP); (NODE) != NULL;   \
135              (NODE) = string_map_next (MAP, NODE))
136 #define STRING_MAP_FOR_EACH_NODE_SAFE(NODE, NEXT, MAP)          \
137         for ((NODE) = string_map_first (MAP);                   \
138              ((NODE) != NULL                                    \
139               && ((NEXT) = string_map_next (MAP, NODE), 1));    \
140              (NODE) = (NEXT))
141 #define STRING_MAP_FOR_EACH_KEY(KEY, NODE, MAP)                 \
142         for ((NODE) = string_map_first (MAP);                   \
143              ((NODE) != NULL                                    \
144               && ((KEY) = string_map_node_get_key (NODE), 1));  \
145              (NODE) = string_map_next (MAP, NODE))
146 #define STRING_MAP_FOR_EACH_KEY_SAFE(KEY, NODE, NEXT, MAP)      \
147         for ((NODE) = string_map_first (MAP);                   \
148              ((NODE) != NULL                                    \
149               && ((KEY) = string_map_node_get_key (NODE), 1)    \
150               && ((NEXT) = string_map_next (MAP, NODE), 1));    \
151              (NODE) = (NEXT))
152 #define STRING_MAP_FOR_EACH_VALUE(VALUE, NODE, MAP)     \
153         for ((NODE) = string_map_first (MAP);           \
154              ((NODE) != NULL                            \
155               && ((VALUE) = (NODE)->value, 1));         \
156              (NODE) = string_map_next (MAP, NODE))
157 #define STRING_MAP_FOR_EACH_VALUE_SAFE(VALUE, NODE, NEXT, MAP)  \
158         for ((NODE) = string_map_first (MAP);                   \
159              ((NODE) != NULL                                    \
160               && ((VALUE) = (NODE)->value, 1)                   \
161               && ((NEXT) = string_map_next (MAP, NODE), 1));    \
162              (NODE) = (NEXT))
163 #define STRING_MAP_FOR_EACH_KEY_VALUE(KEY, VALUE, NODE, MAP)    \
164         for ((NODE) = string_map_first (MAP);                   \
165              ((NODE) != NULL                                    \
166               && ((KEY) = string_map_node_get_key (NODE), 1)    \
167               && ((VALUE) = (NODE)->value, 1));                 \
168              (NODE) = string_map_next (MAP, NODE))
169 #define STRING_MAP_FOR_EACH_KEY_VALUE_SAFE(KEY, VALUE, NODE, NEXT, MAP) \
170         for ((NODE) = string_map_first (MAP);                           \
171              ((NODE) != NULL                                            \
172               && ((KEY) = string_map_node_get_key (NODE), 1)            \
173               && ((VALUE) = (NODE)->value, 1)                           \
174               && ((NEXT) = string_map_next (MAP, NODE), 1));            \
175              (NODE) = (NEXT))
176 \f
177 /* Returns the number of key-value pairs currently in MAP. */
178 static inline size_t
179 string_map_count (const struct string_map *map)
180 {
181   return hmap_count (&map->hmap);
182 }
183
184 /* Returns true if MAP currently contains no key-value pairs, false
185    otherwise. */
186 static inline bool
187 string_map_is_empty (const struct string_map *map)
188 {
189   return hmap_is_empty (&map->hmap);
190 }
191
192 /* Returns the first node in MAP, or a null pointer if MAP is empty.  See the
193    hmap_first function for information about complexity (O(1) amortized) and
194    ordering (arbitrary).
195
196    The STRING_MAP_FOR_EACH family of macros provide convenient ways to iterate
197    over all the nodes in a string map. */
198 static inline struct string_map_node *
199 string_map_first (const struct string_map *map)
200 {
201   return HMAP_FIRST (struct string_map_node, hmap_node, &map->hmap);
202 }
203
204 /* Returns the next node in MAP following NODE, or a null pointer if NODE is
205    the last node in MAP.  See the hmap_next function for information about
206    complexity (O(1) amortized) and ordering (arbitrary).
207
208    The STRING_MAP_FOR_EACH family of macros provide convenient ways to iterate
209    over all the nodes in a string map. */
210 static inline struct string_map_node *
211 string_map_next (const struct string_map *map,
212                  const struct string_map_node *node)
213 {
214   return HMAP_NEXT (node, struct string_map_node, hmap_node, &map->hmap);
215 }
216
217 #endif /* libpspp/string-map.h */