strmap.h 6.0 KB

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