summaryrefslogtreecommitdiff
path: root/lib/ccan/htable/htable_type.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ccan/htable/htable_type.h')
-rw-r--r--lib/ccan/htable/htable_type.h97
1 files changed, 97 insertions, 0 deletions
diff --git a/lib/ccan/htable/htable_type.h b/lib/ccan/htable/htable_type.h
new file mode 100644
index 0000000000..0d9e3fbb2d
--- /dev/null
+++ b/lib/ccan/htable/htable_type.h
@@ -0,0 +1,97 @@
+#ifndef CCAN_HTABLE_TYPE_H
+#define CCAN_HTABLE_TYPE_H
+#include <ccan/htable/htable.h>
+#include "config.h"
+
+/**
+ * HTABLE_DEFINE_TYPE - create a set of htable ops for a type
+ * @type: a type whose pointers will be values in the hash.
+ * @keyof: a function/macro to extract a key from a @type element.
+ * @hashfn: a hash function for a @key
+ * @cmpfn: a comparison function for two keyof()s.
+ * @name: a name for all the functions to define (of form htable_<name>_*)
+ *
+ * NULL values may not be placed into the hash table.
+ *
+ * The following wrapper functions are defined; each one is a
+ * simplified version of the htable.h equivalent:
+ *
+ * // Creating and freeing.
+ * struct htable_@name *htable_@name_new(void);
+ * void htable_@name_free(const struct htable_@name *ht);
+ *
+ * // Add, delete and find.
+ * bool htable_@name_add(struct htable_@name *ht, const type *e);
+ * bool htable_@name_del(struct htable_@name *ht, const type *e);
+ * bool htable_@name_delkey(struct htable_@name *ht, const ktype *k);
+ * type *htable_@name_get(const struct htable_@name *ht, const ktype *k);
+ *
+ * // Iteration.
+ * struct htable_@name_iter;
+ * type *htable_@name_first(const struct htable_@name *ht,
+ * struct htable_@name_iter *i);
+ * type *htable_@name_next(const struct htable_@name *ht,
+ * struct htable_@name_iter *i);
+ */
+#define HTABLE_DEFINE_TYPE(type, keyof, hashfn, cmpfn, name) \
+struct htable_##name; \
+struct htable_##name##_iter { struct htable_iter i; }; \
+static inline size_t htable_##name##_hash(const void *elem, void *priv) \
+{ \
+ return hashfn(keyof((const type *)elem)); \
+} \
+static inline struct htable_##name *htable_##name##_new(void) \
+{ \
+ return (struct htable_##name *)htable_new(htable_##name##_hash, \
+ NULL); \
+} \
+static inline void htable_##name##_free(const struct htable_##name *ht) \
+{ \
+ htable_free((const struct htable *)ht); \
+} \
+static inline bool htable_##name##_add(struct htable_##name *ht, \
+ const type *elem) \
+{ \
+ return htable_add((struct htable *)ht, hashfn(keyof(elem)), elem); \
+} \
+static inline bool htable_##name##_del(const struct htable_##name *ht, \
+ const type *elem) \
+{ \
+ return htable_del((struct htable *)ht, hashfn(keyof(elem)), elem); \
+} \
+static inline type *htable_##name##_get(const struct htable_##name *ht, \
+ const HTABLE_KTYPE(keyof) k) \
+{ \
+ /* Typecheck for cmpfn */ \
+ (void)sizeof(cmpfn((const type *)NULL, \
+ keyof((const type *)NULL))); \
+ return (type *)htable_get((const struct htable *)ht, \
+ hashfn(k), \
+ (bool (*)(const void *, void *))(cmpfn), \
+ k); \
+} \
+static inline bool htable_##name##_delkey(struct htable_##name *ht, \
+ const HTABLE_KTYPE(keyof) k) \
+{ \
+ type *elem = htable_##name##_get(ht, k); \
+ if (elem) \
+ return htable_##name##_del(ht, elem); \
+ return false; \
+} \
+static inline type *htable_##name##_first(const struct htable_##name *ht, \
+ struct htable_##name##_iter *iter) \
+{ \
+ return htable_first((const struct htable *)ht, &iter->i); \
+} \
+static inline type *htable_##name##_next(const struct htable_##name *ht, \
+ struct htable_##name##_iter *iter) \
+{ \
+ return htable_next((const struct htable *)ht, &iter->i); \
+}
+
+#if HAVE_TYPEOF
+#define HTABLE_KTYPE(keyof) typeof(keyof(NULL))
+#else
+#define HTABLE_KTYPE(keyof) void *
+#endif
+#endif /* CCAN_HTABLE_TYPE_H */