]> git.ozlabs.org Git - ccan/blob - ccan/htable/htable_type.h
htable: first implementation
[ccan] / ccan / htable / htable_type.h
1 #ifndef CCAN_HTABLE_TYPE_H
2 #define CCAN_HTABLE_TYPE_H
3 #include <ccan/htable/htable.h>
4 #include "config.h"
5
6 /**
7  * HTABLE_DEFINE_TYPE - create a set of htable ops for a type
8  * @type: a type whose pointers will be values in the hash.
9  * @keyof: a function/macro to extract a key from a @type element.
10  * @hashfn: a hash function for a @key
11  * @cmpfn: a comparison function for two keyof()s.
12  * @name: a name for all the functions to define (of form htable_<name>_*)
13  *
14  * NULL values may not be placed into the hash table.
15  *
16  * The following wrapper functions are defined; each one is a
17  * simplified version of the htable.h equivalent:
18  *
19  *      // Creating and freeing.
20  *      struct htable_@name *htable_@name_new(void);
21  *      void htable_@name_free(const struct htable_@name *ht);
22  *
23  *      // Add, delete and find.
24  *      bool htable_@name_add(struct htable_@name *ht, const type *e);
25  *      bool htable_@name_del(struct htable_@name *ht, const type *e);
26  *      bool htable_@name_delkey(struct htable_@name *ht, const ktype *k);
27  *      type *htable_@name_get(const struct htable_@name *ht, const ktype *k);
28  *
29  *      // Iteration.
30  *      struct htable_@name_iter;
31  *      type *htable_@name_first(const struct htable_@name *ht,
32  *                               struct htable_@name_iter *i);
33  *      type *htable_@name_next(const struct htable_@name *ht,
34  *                              struct htable_@name_iter *i);
35  */
36 #define HTABLE_DEFINE_TYPE(type, keyof, hashfn, cmpfn, name)            \
37 struct htable_##name;                                                   \
38 struct htable_##name##_iter { struct htable_iter i; };                  \
39 static inline size_t htable_##name##_hash(const void *elem, void *priv) \
40 {                                                                       \
41         return hashfn(keyof((const type *)elem));                       \
42 }                                                                       \
43 static inline struct htable_##name *htable_##name##_new(void)           \
44 {                                                                       \
45         return (struct htable_##name *)htable_new(htable_##name##_hash, \
46                                                   NULL);                \
47 }                                                                       \
48 static inline void htable_##name##_free(const struct htable_##name *ht) \
49 {                                                                       \
50         htable_free((const struct htable *)ht);                         \
51 }                                                                       \
52 static inline bool htable_##name##_add(struct htable_##name *ht,        \
53                                        const type *elem)                \
54 {                                                                       \
55         return htable_add((struct htable *)ht, hashfn(keyof(elem)), elem); \
56 }                                                                       \
57 static inline bool htable_##name##_del(const struct htable_##name *ht,  \
58                                        const type *elem)                \
59 {                                                                       \
60         return htable_del((struct htable *)ht, hashfn(keyof(elem)), elem); \
61 }                                                                       \
62 static inline type *htable_##name##_get(const struct htable_##name *ht, \
63                                         const HTABLE_KTYPE(keyof) k)    \
64 {                                                                       \
65         /* Typecheck for cmpfn */                                       \
66         (void)sizeof(cmpfn(keyof((const type *)NULL),                   \
67                            keyof((const type *)NULL)));                 \
68         return (type *)htable_get((const struct htable *)ht,            \
69                                   hashfn(k),                            \
70                                   (bool (*)(const void *, void *))(cmpfn), \
71                                   k);                                   \
72 }                                                                       \
73 static inline bool htable_##name##_delkey(struct htable_##name *ht,     \
74                                           const HTABLE_KTYPE(keyof) k) \
75 {                                                                       \
76         type *elem = htable_##name##_get(ht, k);                        \
77         if (elem)                                                       \
78                 return htable_##name##_del(ht, elem);                   \
79         return false;                                                   \
80 }                                                                       \
81 static inline type *htable_##name##_first(const struct htable_##name *ht, \
82                                           struct htable_##name##_iter *iter) \
83 {                                                                       \
84         return htable_first((const struct htable *)ht, &iter->i);       \
85 }                                                                       \
86 static inline type *htable_##name##_next(const struct htable_##name *ht, \
87                                          struct htable_##name##_iter *iter) \
88 {                                                                       \
89         return htable_next((const struct htable *)ht, &iter->i);        \
90 }
91
92 #if HAVE_TYPEOF
93 #define HTABLE_KTYPE(keyof) typeof(keyof(NULL))
94 #else
95 #define HTABLE_KTYPE(keyof) void *
96 #endif
97 #endif /* CCAN_HTABLE_TYPE_H */