i18n: Factor out encoding categories from GUI into common code.
[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 struct stringi_map_node *stringi_map_find_node (const struct stringi_map *,
94                                                 const char *);
95 char *stringi_map_find_and_delete (struct stringi_map *, const char *key);
96
97 struct stringi_map_node *stringi_map_insert (struct stringi_map *,
98                                              const char *key,
99                                              const char *value);
100 struct stringi_map_node *stringi_map_insert_nocopy (struct stringi_map *,
101                                                     char *key, char *value);
102 struct stringi_map_node *stringi_map_replace (struct stringi_map *,
103                                               const char *key,
104                                               const char *value);
105 struct stringi_map_node *stringi_map_replace_nocopy (struct stringi_map *,
106                                                      char *key, char *value);
107 bool stringi_map_delete (struct stringi_map *, const char *);
108 void stringi_map_delete_node (struct stringi_map *, struct stringi_map_node *);
109 void stringi_map_delete_nofree (struct stringi_map *,
110                                 struct stringi_map_node *);
111
112 void stringi_map_clear (struct stringi_map *);
113 void stringi_map_insert_map (struct stringi_map *, const struct stringi_map *);
114 void stringi_map_replace_map (struct stringi_map *,
115                               const struct stringi_map *);
116
117 void stringi_map_get_keys (const struct stringi_map *, struct stringi_set *);
118 void stringi_map_get_values (const struct stringi_map *, struct string_set *);
119
120 static inline struct stringi_map_node *stringi_map_first (
121   const struct stringi_map *);
122 static inline struct stringi_map_node *stringi_map_next (
123   const struct stringi_map *, const struct stringi_map_node *);
124
125 /* Macros for conveniently iterating through a stringi_map, e.g. to print all
126    of the key-value pairs in "my_map":
127
128    struct stringi_map_node *node;
129    const char *key, *value;
130
131    STRINGI_MAP_FOR_EACH_KEY_VALUE (key, value, node, &my_map)
132    printf ("%s=%s\n", key, value);
133 */
134 #define STRINGI_MAP_FOR_EACH_NODE(NODE, MAP)                    \
135   for ((NODE) = stringi_map_first (MAP); (NODE) != NULL;        \
136        (NODE) = stringi_map_next (MAP, NODE))
137 #define STRINGI_MAP_FOR_EACH_NODE_SAFE(NODE, NEXT, MAP) \
138   for ((NODE) = stringi_map_first (MAP);                \
139        ((NODE) != NULL                                  \
140         && ((NEXT) = stringi_map_next (MAP, NODE), 1)); \
141        (NODE) = (NEXT))
142 #define STRINGI_MAP_FOR_EACH_KEY(KEY, NODE, MAP)                \
143   for ((NODE) = stringi_map_first (MAP);                        \
144        ((NODE) != NULL                                          \
145         && ((KEY) = stringi_map_node_get_key (NODE), 1));       \
146        (NODE) = stringi_map_next (MAP, NODE))
147 #define STRINGI_MAP_FOR_EACH_KEY_SAFE(KEY, NODE, NEXT, MAP)     \
148   for ((NODE) = stringi_map_first (MAP);                        \
149        ((NODE) != NULL                                          \
150         && ((KEY) = stringi_map_node_get_key (NODE), 1)         \
151         && ((NEXT) = stringi_map_next (MAP, NODE), 1));         \
152        (NODE) = (NEXT))
153 #define STRINGI_MAP_FOR_EACH_VALUE(VALUE, NODE, MAP)    \
154   for ((NODE) = stringi_map_first (MAP);                \
155        ((NODE) != NULL                                  \
156         && ((VALUE) = (NODE)->value, 1));               \
157        (NODE) = stringi_map_next (MAP, NODE))
158 #define STRINGI_MAP_FOR_EACH_VALUE_SAFE(VALUE, NODE, NEXT, MAP) \
159   for ((NODE) = stringi_map_first (MAP);                        \
160        ((NODE) != NULL                                          \
161         && ((VALUE) = (NODE)->value, 1)                         \
162         && ((NEXT) = stringi_map_next (MAP, NODE), 1));         \
163        (NODE) = (NEXT))
164 #define STRINGI_MAP_FOR_EACH_KEY_VALUE(KEY, VALUE, NODE, MAP)   \
165   for ((NODE) = stringi_map_first (MAP);                        \
166        ((NODE) != NULL                                          \
167         && ((KEY) = stringi_map_node_get_key (NODE), 1)         \
168         && ((VALUE) = (NODE)->value, 1));                       \
169        (NODE) = stringi_map_next (MAP, NODE))
170 #define STRINGI_MAP_FOR_EACH_KEY_VALUE_SAFE(KEY, VALUE, NODE, NEXT, MAP) \
171   for ((NODE) = stringi_map_first (MAP);                                \
172        ((NODE) != NULL                                                  \
173         && ((KEY) = stringi_map_node_get_key (NODE), 1)                 \
174         && ((VALUE) = (NODE)->value, 1)                                 \
175         && ((NEXT) = stringi_map_next (MAP, NODE), 1));                 \
176        (NODE) = (NEXT))
177 \f
178 /* Returns the number of key-value pairs currently in MAP. */
179 static inline size_t
180 stringi_map_count (const struct stringi_map *map)
181 {
182   return hmap_count (&map->hmap);
183 }
184
185 /* Returns true if MAP currently contains no key-value pairs, false
186    otherwise. */
187 static inline bool
188 stringi_map_is_empty (const struct stringi_map *map)
189 {
190   return hmap_is_empty (&map->hmap);
191 }
192
193 /* Returns the first node in MAP, or a null pointer if MAP is empty.  See the
194    hmap_first function for information about complexity (O(1) amortized) and
195    ordering (arbitrary).
196
197    The STRINGI_MAP_FOR_EACH family of macros provide convenient ways to iterate
198    over all the nodes in a string map. */
199 static inline struct stringi_map_node *
200 stringi_map_first (const struct stringi_map *map)
201 {
202   return HMAP_FIRST (struct stringi_map_node, hmap_node, &map->hmap);
203 }
204
205 /* Returns the next node in MAP following NODE, or a null pointer if NODE is
206    the last node in MAP.  See the hmap_next function for information about
207    complexity (O(1) amortized) and ordering (arbitrary).
208
209    The STRINGI_MAP_FOR_EACH family of macros provide convenient ways to iterate
210    over all the nodes in a string map. */
211 static inline struct stringi_map_node *
212 stringi_map_next (const struct stringi_map *map,
213                   const struct stringi_map_node *node)
214 {
215   return HMAP_NEXT (node, struct stringi_map_node, hmap_node, &map->hmap);
216 }
217
218 #endif /* libpspp/string-map.h */