dict.h revision 38bcdbe5d04749403e2197cca0d56397cb2da7c7
1/*
2 * This file is part of ltrace.
3 * Copyright (C) 2012 Petr Machata, Red Hat Inc.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 */
20
21#ifndef _DICT_H_
22#define _DICT_H_
23
24#include <stddef.h>
25#include <assert.h>
26#include "vect.h"
27
28struct dict {
29	/* The invariant is that KEYS, VALUES and STATUS are of the
30	 * same size.  */
31	struct vect keys;
32	struct vect values;
33	struct vect status;
34	size_t size;
35
36	size_t (*hash1)(const void *);
37	int (*eq)(const void *, const void *);
38	size_t (*hash2)(size_t);
39};
40
41/* Initialize a dictionary DICT.  The dictionary will hold keys of the
42 * size KEY_SIZE and values of the size VALUE_SIZE.  HASH1 and HASH2
43 * are, respectively, primary and secondary hashing functions.  The
44 * latter may be NULL, in which case a default internal hash is used.
45 * EQ is a callback for comparing two keys.  */
46void dict_init(struct dict *dict,
47	       size_t key_size, size_t value_size,
48	       size_t (*hash1)(const void *),
49	       int (*eq)(const void *, const void *),
50	       size_t (*hash2)(size_t));
51
52/* Wrapper around dict_init.  Initializes a dictionary DITCP which
53 * will hold keys of type KEY_TYPE and values of type VALUE_TYPE.
54 * Other arguments as above.  */
55#define DICT_INIT(DICTP, KEY_TYPE, VALUE_TYPE, HASH1, EQ, HASH2)	\
56	({								\
57		/* Check that callbacks are typed properly.  */		\
58		size_t (*_hash1_callback)(const KEY_TYPE *) = HASH1;	\
59		int (*_eq_callback)(const KEY_TYPE *, const KEY_TYPE *) = EQ; \
60		dict_init(DICTP, sizeof(KEY_TYPE), sizeof(VALUE_TYPE),	\
61			  (size_t (*)(const void *))_hash1_callback,	\
62			  (int (*)(const void *, const void *))_eq_callback, \
63			  HASH2);					\
64	})
65
66/* Clone SOURCE to TARGET.  For cloning slots, CLONE_KEY and
67 * CLONE_VALUE are called.  These callbacks return 0 on success or a
68 * negative value on failure.  If any of the callbacks is NULL, the
69 * default action is simple memmove.  Returns 0 on success.  If the
70 * cloning fails for any reason, already-cloned keys and values are
71 * destroyed again by DTOR_KEY and DTOR_VALUE callbacks (if non-NULL),
72 * and the function returns a negative value.  DATA is passed to all
73 * callbacks verbatim.  */
74int dict_clone(struct dict *target, const struct dict *source,
75	       int (*clone_key)(void *tgt, const void *src, void *data),
76	       void (*dtor_key)(void *tgt, void *data),
77	       int (*clone_value)(void *tgt, const void *src, void *data),
78	       void (*dtor_value)(void *tgt, void *data),
79	       void *data);
80
81/* Clone SRC_DICTP, which holds KEY_TYPE-VALUE_TYPE pairs, into
82 * TGT_DICTP.  Other arguments and return codes as above.  */
83#define DICT_CLONE(TGT_DICTP, SRC_DICTP, KEY_TYPE, VALUE_TYPE,		\
84		   CLONE_KEY, DTOR_KEY, CLONE_VALUE, DTOR_VALUE, DATA)	\
85	/* xxx GCC-ism necessary to get in the safety latches.  */	\
86	({								\
87		const struct dict *_source_d = (SRC_DICTP);		\
88		assert(_source_d->keys.elt_size == sizeof(KEY_TYPE));	\
89		assert(_source_d->values.elt_size == sizeof(VALUE_TYPE)); \
90		/* Check that callbacks are typed properly.  */		\
91		void (*_key_dtor_cb)(KEY_TYPE *, void *) = DTOR_KEY;	\
92		int (*_key_clone_cb)(KEY_TYPE *, const KEY_TYPE *,	\
93				     void *) = CLONE_KEY;		\
94		void (*_value_dtor_cb)(VALUE_TYPE *, void *) = DTOR_VALUE; \
95		int (*_value_clone_cb)(VALUE_TYPE *, const VALUE_TYPE *, \
96				       void *) = CLONE_VALUE;		\
97		dict_clone((TGT_DICTP), _source_d,			\
98			   (int (*)(void *, const void *,		\
99				    void *))_key_clone_cb,		\
100			   (void (*)(void *, void *))_key_dtor_cb,	\
101			   (int (*)(void *, const void *,		\
102				    void *))_value_clone_cb,		\
103			   (void (*)(void *, void *))_value_dtor_cb,	\
104			   (DATA));					\
105	})
106
107/* Return number of key-value pairs stored in DICT.  */
108size_t dict_size(const struct dict *dict);
109
110/* Emptiness predicate.  */
111int dict_empty(const struct dict *dict);
112
113/* Insert into DICT a pair of KEY and VALUE.  Returns 0 if insertion
114 * was successful, a negative value on error, or a positive value if
115 * this key is already present in the table.  */
116int dict_insert(struct dict *dict, void *key, void *value);
117
118/* Insert into DICT a pair of KEY and VALUE.  See dict_insert for
119 * details.  In addition, make a check whether DICTP holds elements of
120 * the right size.  */
121#define DICT_INSERT(DICTP, KEYP, VALUEP)				\
122	(assert((DICTP)->keys.elt_size == sizeof(*(KEYP))),		\
123	 assert((DICTP)->values.elt_size == sizeof(*(VALUEP))),		\
124	 dict_insert((DICTP), (KEYP), (VALUEP)))
125
126/* Find in DICT a value corresponding to KEY and return a pointer to
127 * it.  Returns NULL if the key was not found.  */
128void *dict_find(struct dict *dict, const void *key);
129
130/* Find in DICTP a value of type VALUE_TYPE corresponding to KEYP and
131 * return a pointer (VALUE_TYPE *) to it.  Returns NULL if the key was
132 * not found.  */
133#define DICT_FIND(DICTP, KEYP, VALUE_TYPE)			\
134	(assert((DICTP)->keys.elt_size == sizeof(*(KEYP))),	\
135	 (VALUE_TYPE *)dict_find((DICTP), (KEYP)))
136
137/* Erase from DICT the entry corresponding to KEY.  Returns a negative
138 * value if the key was not found, or 0 on success.  DTOR_KEY and
139 * DTOR_VALUE, if non-NULL, are called to destroy the erased
140 * value.  */
141int dict_erase(struct dict *dict, const void *key,
142	       void (*dtor_key)(void *tgt, void *data),
143	       void (*dtor_value)(void *tgt, void *data),
144	       void *data);
145
146/* Erase from DICTP a value of type VALUE_TYPE corresponding to
147 * KEYP.  */
148#define DICT_ERASE(DICTP, KEYP, VALUE_TYPE, DTOR_KEY, DTOR_VALUE, DATA) \
149	({								\
150		struct dict *_d = (DICTP);				\
151		assert(_d->keys.elt_size == sizeof(*KEYP));		\
152		assert(_d->values.elt_size == sizeof(VALUE_TYPE));	\
153		/* Check that callbacks are typed properly.  */		\
154		void (*_value_dtor_cb)(VALUE_TYPE *, void *) = DTOR_VALUE; \
155		dict_erase(_d, (KEYP), (DTOR_KEY),			\
156			   (void (*)(void *, void *))_value_dtor_cb,	\
157			   (DATA));					\
158	})
159
160/* Destroy DICT.  If KEY_DTOR is non-NULL, then it's called on each
161 * key stored in DICT.  Similarly for VALUE_DTOR.  DATA is passed to
162 * DTOR's verbatim.  The memory pointed-to by DICT is not freed.  */
163void dict_destroy(struct dict *dict,
164		  void (*dtor_key)(void *tgt, void *data),
165		  void (*dtor_value)(void *tgt, void *data),
166		  void *data);
167
168/* Destroy DICTP, which holds keys of type KEY_TYPE and values of type
169 * VALUE_TYPE, using DTOR.  */
170#define DICT_DESTROY(DICTP, KEY_TYPE, VALUE_TYPE, DTOR_KEY, DTOR_VALUE, DATA) \
171	do {								\
172		struct dict *_d = (DICTP);				\
173		assert(_d->keys.elt_size == sizeof(KEY_TYPE));		\
174		assert(_d->values.elt_size == sizeof(VALUE_TYPE));	\
175		/* Check that callbacks are typed properly.  */		\
176		void (*_key_dtor_cb)(KEY_TYPE *, void *) = DTOR_KEY;	\
177		void (*_value_dtor_cb)(VALUE_TYPE *, void *) = DTOR_VALUE; \
178		dict_destroy(_d, (void (*)(void *, void *))_key_dtor_cb, \
179			     (void (*)(void *, void *))_value_dtor_cb,	\
180			     (DATA));					\
181	} while (0)
182
183/* Iterate through DICT.  See callback.h for notes on iteration
184 * interfaces.  Callback arguments are key, value, DATA.  Note that
185 * the iteration over DICT is more expensive than in other containers:
186 * while CB is only called for items present in the table, and is
187 * therefore O(number of elements), the iterator needs to go through
188 * all the table, which is proportional to O(size of table).
189 * START_AFTER and the returned iterator are key where the iteration
190 * stopped.  */
191void *dict_each(struct dict *dict, void *start_after,
192		enum callback_status (*cb)(void *, void *, void *), void *data);
193
194#define DICT_EACH(DICTP, KEY_TYPE, VALUE_TYPE, START_AFTER, CB, DATA)	\
195	/* xxx GCC-ism necessary to get in the safety latches.  */	\
196	({								\
197		assert((DICTP)->keys.elt_size == sizeof(KEY_TYPE));	\
198		assert((DICTP)->values.elt_size == sizeof(VALUE_TYPE));	\
199		/* Check that CB is typed properly.  */			\
200		enum callback_status (*_cb)(KEY_TYPE *, VALUE_TYPE *,	\
201					    void *) = CB;		\
202		KEY_TYPE *_start_after = (START_AFTER);			\
203		(KEY_TYPE *)dict_each((DICTP), _start_after,		\
204				      (enum callback_status		\
205				       (*)(void *, void *, void *))_cb,	\
206				      (DATA));				\
207	})
208
209/* A callback for hashing integers.  */
210size_t dict_hash_int(const int *key);
211
212/* An equality predicate callback for integers.  */
213int dict_eq_int(const int *key1, const int *key2);
214
215/* A callback for hashing NULL-terminated strings.  */
216size_t dict_hash_string(const char **key);
217
218/* An equality predicate callback for strings.  */
219int dict_eq_string(const char **key1, const char **key2);
220
221/* A dtor which calls 'free' on keys in a table.  */
222void dict_dtor_string(const char **key, void *data);
223
224/* A cloner that calls 'strdup' on keys in a table.  */
225int dict_clone_string(const char **tgt, const char **src, void *data);
226
227#endif /* _DICT_H_ */
228