summaryrefslogtreecommitdiffstats
path: root/lib/ccan/htable/htable_type.h
blob: 0d9e3fbb2dcce3ec7b183627d81fc577a3a82f24 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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 */