]> git.ozlabs.org Git - ccan/blob - ccan/strmap/strmap.h
strmap: Convert to using TCON_WRAP() instead of plain TCON()
[ccan] / ccan / strmap / strmap.h
1 #ifndef CCAN_STRMAP_H
2 #define CCAN_STRMAP_H
3 #include "config.h"
4 #include <ccan/tcon/tcon.h>
5 #include <ccan/typesafe_cb/typesafe_cb.h>
6 #include <stdlib.h>
7 #include <stdbool.h>
8
9 /**
10  * struct strmap - representation of a string map
11  *
12  * It's exposed here to allow you to embed it and so we can inline the
13  * trivial functions.
14  */
15 struct strmap {
16         union {
17                 struct node *n;
18                 const char *s;
19         } u;
20         void *v;
21 };
22
23 /**
24  * STRMAP - declare a type-specific strmap
25  * @type: type for this map's values, or void * for any pointer.
26  *
27  * You use this to create your own typed strmap for a particular type.
28  * You can use an integer type, *but* remember you can't use "0" as a
29  * value!
30  *
31  * Example:
32  *      STRMAP(int *) int_strmap;
33  *      strmap_init(&int_strmap);
34  */
35 #define STRMAP(type)                            \
36         TCON_WRAP(struct strmap, type canary)
37
38 /**
39  * strmap_init - initialize a string map (empty)
40  * @map: the typed strmap to initialize.
41  *
42  * For completeness; if you've arranged for it to be NULL already you don't
43  * need this.
44  *
45  * Example:
46  *      STRMAP(int *) map;
47  *
48  *      strmap_init(&map);
49  */
50 #define strmap_init(map) strmap_init_(tcon_unwrap(map))
51
52 static inline void strmap_init_(struct strmap *map)
53 {
54         map->u.n = NULL;
55 }
56
57 /**
58  * strmap_empty - is this string map empty?
59  * @map: the typed strmap to check.
60  *
61  * Example:
62  *      if (!strmap_empty(&map))
63  *              abort();
64  */
65 #define strmap_empty(map) strmap_empty_(tcon_unwrap(map))
66
67 static inline bool strmap_empty_(const struct strmap *map)
68 {
69         return map->u.n == NULL;
70 }
71
72 /**
73  * strmap_get - get a value from a string map
74  * @map: the typed strmap to search.
75  * @member: the string to search for.
76  *
77  * Returns the value, or NULL if it isn't in the map (and sets errno = ENOENT).
78  *
79  * Example:
80  *      int *val = strmap_get(&map, "hello");
81  *      if (val)
82  *              printf("hello => %i\n", *val);
83  */
84 #define strmap_get(map, member) \
85         tcon_cast((map), canary, strmap_get_(tcon_unwrap(map), (member)))
86 void *strmap_get_(const struct strmap *map, const char *member);
87
88 /**
89  * strmap_add - place a member in the string map.
90  * @map: the typed strmap to add to.
91  * @member: the string to place in the map.
92  * @v: the (non-NULL) value.
93  *
94  * This returns false if we run out of memory (errno = ENOMEM), or
95  * (more normally) if that string already appears in the map (EEXIST).
96  *
97  * Note that the pointer is placed in the map, the string is not copied.  If
98  * you want a copy in the map, use strdup().  Similarly for the value.
99  *
100  * Example:
101  *      val = malloc(sizeof *val);
102  *      *val = 17;
103  *      if (!strmap_add(&map, "goodbye", val))
104  *              printf("goodbye was already in the map\n");
105  */
106 #define strmap_add(map, member, value)                                  \
107         strmap_add_(tcon_unwrap(tcon_check((map), canary, (value))),    \
108                     (member), (void *)(value))
109
110 bool strmap_add_(struct strmap *map, const char *member, const void *value);
111
112 /**
113  * strmap_del - remove a member from the string map.
114  * @map: the typed strmap to delete from.
115  * @member: the string to remove from the map.
116  * @valuep: the value (if non-NULL)
117  *
118  * This returns the string which was passed to strmap_map(), or NULL if
119  * it was not in the map (and sets errno = ENOENT).
120  *
121  * This means that if you allocated a string (eg. using strdup()), you
122  * can free it here.  Similarly, the value is returned in @valuep if
123  * @valuep is not NULL.
124  *
125  * Example:
126  *      if (!strmap_del(&map, "goodbye", NULL))
127  *              printf("goodbye was not in the map?\n");
128  */
129 #define strmap_del(map, member, valuep)                                 \
130         strmap_del_(tcon_unwrap(tcon_check_ptr((map), canary, valuep)), \
131                     (member), (void **)valuep)
132 char *strmap_del_(struct strmap *map, const char *member, void **valuep);
133
134 /**
135  * strmap_clear - remove every member from the map.
136  * @map: the typed strmap to clear.
137  *
138  * The map will be empty after this.
139  *
140  * Example:
141  *      strmap_clear(&map);
142  */
143 #define strmap_clear(map) strmap_clear_(tcon_unwrap(map))
144
145 void strmap_clear_(struct strmap *map);
146
147 /**
148  * strmap_iterate - ordered iteration over a map
149  * @map: the typed strmap to iterate through.
150  * @handle: the function to call.
151  * @arg: the argument for the function (types should match).
152  *
153  * @handle's prototype should be:
154  *      bool @handle(const char *member, type value, typeof(arg) arg)
155  *
156  * If @handle returns false, the iteration will stop.
157  * You should not alter the map within the @handle function!
158  *
159  * Example:
160  *      typedef STRMAP(int *) strmap_intp;
161  *      static bool dump_some(const char *member, int *value, int *num)
162  *      {
163  *              // Only dump out num nodes.
164  *              if (*(num--) == 0)
165  *                      return false;
166  *              printf("%s=>%i\n", member, *value);
167  *              return true;
168  *      }
169  *
170  *      static void dump_map(const strmap_intp *map)
171  *      {
172  *              int max = 100;
173  *              strmap_iterate(map, dump_some, &max);
174  *              if (max < 0)
175  *                      printf("... (truncated to 100 entries)\n");
176  *      }
177  */
178 #define strmap_iterate(map, handle, arg)                                \
179         strmap_iterate_(tcon_unwrap(map),                               \
180                         typesafe_cb_cast(bool (*)(const char *,         \
181                                                   void *, void *),      \
182                                          bool (*)(const char *,         \
183                                                   tcon_type((map), canary), \
184                                                   __typeof__(arg)), (handle)), \
185                         (arg))
186 void strmap_iterate_(const struct strmap *map,
187                      bool (*handle)(const char *, void *, void *),
188                      const void *data);
189
190 /**
191  * strmap_prefix - return a submap matching a prefix
192  * @map: the map.
193  * @prefix: the prefix.
194  *
195  * This returns a pointer into @map, so don't alter @map while using
196  * the return value.  You can use strmap_iterate(), strmap_get() or
197  * strmap_empty() on the returned pointer.
198  *
199  * Example:
200  *      static void dump_prefix(const strmap_intp *map,
201  *                              const char *prefix)
202  *      {
203  *              int max = 100;
204  *              printf("Nodes with prefix %s:\n", prefix);
205  *              strmap_iterate(strmap_prefix(map, prefix), dump_some, &max);
206  *              if (max < 0)
207  *                      printf("... (truncated to 100 entries)\n");
208  *      }
209  */
210 #if HAVE_TYPEOF
211 #define strmap_prefix(map, prefix) \
212         ((const __typeof__(map))strmap_prefix_(tcon_unwrap(map), (prefix)))
213 #else
214 #define strmap_prefix(map, prefix) \
215         ((const void *)strmap_prefix_(tcon_unwrap(map), (prefix)))
216 #endif
217
218 const struct strmap *strmap_prefix_(const struct strmap *map,
219                                     const char *prefix);
220
221 #endif /* CCAN_STRMAP_H */