docs
[pspp] / src / libpspp / stringi-map.h
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2009, 2010, 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_STRINGI_MAP_H
18 #define LIBPSPP_STRINGI_MAP_H
19
20 /* Map from a unique, case-insensitve 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 struct stringi_set;
30
31 /* A node within a string map. */
32 struct stringi_map_node
33   {
34     struct hmap_node hmap_node;
35     char *key;
36     char *value;
37   };
38
39 /* Returns the string key within NODE.  The caller must not modify or free the
40    returned string. */
41 static inline const char *
42 stringi_map_node_get_key (const struct stringi_map_node *node)
43 {
44   return node->key;
45 }
46
47 /* Returns the string key within NODE.  The caller must not free the returned
48    string. */
49 static inline const char *
50 stringi_map_node_get_value (const struct stringi_map_node *node)
51 {
52   return node->value;
53 }
54
55 /* Returns the string key within NODE.  The caller must not free the returned
56    string. */
57 static inline char *
58 stringi_map_node_get_value_rw (struct stringi_map_node *node)
59 {
60   return node->value;
61 }
62
63 char *stringi_map_node_swap_value (struct stringi_map_node *,
64                                    const char *new_value);
65 char *stringi_map_node_swap_value_nocopy (struct stringi_map_node *,
66                                           char *new_value);
67 void stringi_map_node_set_value (struct stringi_map_node *, const char *value);
68 void stringi_map_node_set_value_nocopy (struct stringi_map_node *, char *value);
69 void stringi_map_node_destroy (struct stringi_map_node *);
70 \f
71 /* Unordered map from unique, case-insensitive string keys to string values. */
72 struct stringi_map
73   {
74     struct hmap hmap;
75   };
76
77 /* Suitable for use as the initializer for a stringi_map named MAP.  Typical
78    usage:
79    struct stringi_map map = STRINGI_MAP_INITIALIZER (map);
80    STRINGI_MAP_INITIALIZER is an alternative to calling stringi_map_init. */
81 #define STRINGI_MAP_INITIALIZER(MAP) { HMAP_INITIALIZER ((MAP).hmap) }
82
83 void stringi_map_init (struct stringi_map *);
84 void stringi_map_clone (struct stringi_map *, const struct stringi_map *);
85 void stringi_map_swap (struct stringi_map *, struct stringi_map *);
86 void stringi_map_destroy (struct stringi_map *);
87
88 static inline size_t stringi_map_count (const struct stringi_map *);
89 static inline bool stringi_map_is_empty (const struct stringi_map *);
90
91 bool stringi_map_contains (const struct stringi_map *, const char *);
92 const char *stringi_map_find (const struct stringi_map *, const char *);
93 const char *stringi_map_find__ (const struct stringi_map *, const char *key,
94                                 size_t key_len);
95 struct stringi_map_node *stringi_map_find_node (const struct stringi_map *,
96                                                 const char *key,
97                                                 size_t key_len);
98 char *stringi_map_find_and_delete (struct stringi_map *, const char *key);
99
100 struct stringi_map_node *stringi_map_insert (struct stringi_map *,
101                                              const char *key,
102                                              const char *value);
103 struct stringi_map_node *stringi_map_insert_nocopy (struct stringi_map *,
104                                                     char *key, char *value);
105 struct stringi_map_node *stringi_map_replace (struct stringi_map *,
106                                               const char *key,
107                                               const char *value);
108 struct stringi_map_node *stringi_map_replace_nocopy (struct stringi_map *,
109                                                      char *key, char *value);
110 bool stringi_map_delete (struct stringi_map *, const char *);
111 void stringi_map_delete_node (struct stringi_map *, struct stringi_map_node *);
112 void stringi_map_delete_nofree (struct stringi_map *,
113                                 struct stringi_map_node *);
114
115 void stringi_map_clear (struct stringi_map *);
116 void stringi_map_insert_map (struct stringi_map *, const struct stringi_map *);
117 void stringi_map_replace_map (struct stringi_map *,
118                               const struct stringi_map *);
119
120 void stringi_map_get_keys (const struct stringi_map *, struct stringi_set *);
121 void stringi_map_get_values (const struct stringi_map *, struct string_set *);
122
123 static inline struct stringi_map_node *stringi_map_first (
124   const struct stringi_map *);
125 static inline struct stringi_map_node *stringi_map_next (
126   const struct stringi_map *, const struct stringi_map_node *);
127
128 /* Macros for conveniently iterating through a stringi_map, e.g. to print all
129    of the key-value pairs in "my_map":
130
131    struct stringi_map_node *node;
132    const char *key, *value;
133
134    STRINGI_MAP_FOR_EACH_KEY_VALUE (key, value, node, &my_map)
135    printf ("%s=%s\n", key, value);
136 */
137 #define STRINGI_MAP_FOR_EACH_NODE(NODE, MAP)                    \
138   for ((NODE) = stringi_map_first (MAP); (NODE) != NULL;        \
139        (NODE) = stringi_map_next (MAP, NODE))
140 #define STRINGI_MAP_FOR_EACH_NODE_SAFE(NODE, NEXT, MAP) \
141   for ((NODE) = stringi_map_first (MAP);                \
142        ((NODE) != NULL                                  \
143         && ((NEXT) = stringi_map_next (MAP, NODE), 1)); \
144        (NODE) = (NEXT))
145 #define STRINGI_MAP_FOR_EACH_KEY(KEY, NODE, MAP)                \
146   for ((NODE) = stringi_map_first (MAP);                        \
147        ((NODE) != NULL                                          \
148         && ((KEY) = stringi_map_node_get_key (NODE), 1));       \
149        (NODE) = stringi_map_next (MAP, NODE))
150 #define STRINGI_MAP_FOR_EACH_KEY_SAFE(KEY, NODE, NEXT, MAP)     \
151   for ((NODE) = stringi_map_first (MAP);                        \
152        ((NODE) != NULL                                          \
153         && ((KEY) = stringi_map_node_get_key (NODE), 1)         \
154         && ((NEXT) = stringi_map_next (MAP, NODE), 1));         \
155        (NODE) = (NEXT))
156 #define STRINGI_MAP_FOR_EACH_VALUE(VALUE, NODE, MAP)    \
157   for ((NODE) = stringi_map_first (MAP);                \
158        ((NODE) != NULL                                  \
159         && ((VALUE) = (NODE)->value, 1));               \
160        (NODE) = stringi_map_next (MAP, NODE))
161 #define STRINGI_MAP_FOR_EACH_VALUE_SAFE(VALUE, NODE, NEXT, MAP) \
162   for ((NODE) = stringi_map_first (MAP);                        \
163        ((NODE) != NULL                                          \
164         && ((VALUE) = (NODE)->value, 1)                         \
165         && ((NEXT) = stringi_map_next (MAP, NODE), 1));         \
166        (NODE) = (NEXT))
167 #define STRINGI_MAP_FOR_EACH_KEY_VALUE(KEY, VALUE, NODE, MAP)   \
168   for ((NODE) = stringi_map_first (MAP);                        \
169        ((NODE) != NULL                                          \
170         && ((KEY) = stringi_map_node_get_key (NODE), 1)         \
171         && ((VALUE) = (NODE)->value, 1));                       \
172        (NODE) = stringi_map_next (MAP, NODE))
173 #define STRINGI_MAP_FOR_EACH_KEY_VALUE_SAFE(KEY, VALUE, NODE, NEXT, MAP) \
174   for ((NODE) = stringi_map_first (MAP);                                \
175        ((NODE) != NULL                                                  \
176         && ((KEY) = stringi_map_node_get_key (NODE), 1)                 \
177         && ((VALUE) = (NODE)->value, 1)                                 \
178         && ((NEXT) = stringi_map_next (MAP, NODE), 1));                 \
179        (NODE) = (NEXT))
180 \f
181 /* Returns the number of key-value pairs currently in MAP. */
182 static inline size_t
183 stringi_map_count (const struct stringi_map *map)
184 {
185   return hmap_count (&map->hmap);
186 }
187
188 /* Returns true if MAP currently contains no key-value pairs, false
189    otherwise. */
190 static inline bool
191 stringi_map_is_empty (const struct stringi_map *map)
192 {
193   return hmap_is_empty (&map->hmap);
194 }
195
196 /* Returns the first node in MAP, or a null pointer if MAP is empty.  See the
197    hmap_first function for information about complexity (O(1) amortized) and
198    ordering (arbitrary).
199
200    The STRINGI_MAP_FOR_EACH family of macros provide convenient ways to iterate
201    over all the nodes in a string map. */
202 static inline struct stringi_map_node *
203 stringi_map_first (const struct stringi_map *map)
204 {
205   return HMAP_FIRST (struct stringi_map_node, hmap_node, &map->hmap);
206 }
207
208 /* Returns the next node in MAP following NODE, or a null pointer if NODE is
209    the last node in MAP.  See the hmap_next function for information about
210    complexity (O(1) amortized) and ordering (arbitrary).
211
212    The STRINGI_MAP_FOR_EACH family of macros provide convenient ways to iterate
213    over all the nodes in a string map. */
214 static inline struct stringi_map_node *
215 stringi_map_next (const struct stringi_map *map,
216                   const struct stringi_map_node *node)
217 {
218   return HMAP_NEXT (node, struct stringi_map_node, hmap_node, &map->hmap);
219 }
220
221 #endif /* libpspp/string-map.h */