blob: 18ad785a5ec8dd7860416a51bec641dd2d706f5e [file] [log] [blame]
Juan Cespedescac15c32003-01-31 18:58:58 +01001/*
Petr Machataa11cbed2012-05-05 00:07:38 +02002 * This file is part of ltrace.
Petr Machata98ff3092013-03-08 22:11:36 +01003 * Copyright (C) 2012, 2013 Petr Machata, Red Hat Inc.
Petr Machataa11cbed2012-05-05 00:07:38 +02004 *
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
Petr Machatad7e4ca82012-11-28 03:38:47 +010024#include <stddef.h>
25#include <assert.h>
26#include "vect.h"
Juan Cespedescac15c32003-01-31 18:58:58 +010027
Petr Machatad7e4ca82012-11-28 03:38:47 +010028struct 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;
Juan Cespedescac15c32003-01-31 18:58:58 +010035
Petr Machatad7e4ca82012-11-28 03:38:47 +010036 size_t (*hash1)(const void *);
37 int (*eq)(const void *, const void *);
38 size_t (*hash2)(size_t);
39};
Juan Cespedescac15c32003-01-31 18:58:58 +010040
Petr Machatad7e4ca82012-11-28 03:38:47 +010041/* 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));
Petr Machata345c9b52012-02-10 13:10:03 +010051
Petr Machatad7e4ca82012-11-28 03:38:47 +010052/* 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 })
Petr Machata345c9b52012-02-10 13:10:03 +010065
Petr Machatad7e4ca82012-11-28 03:38:47 +010066/* 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
Petr Machata3d532ac2013-03-08 23:57:30 +0100130/* Look into DICTP for a key *KEYP. Return a boolean indicating
131 * whether the key was found. */
Petr Machata98ff3092013-03-08 22:11:36 +0100132#define DICT_HAS_KEY(DICTP, KEYP) \
133 (assert((DICTP)->keys.elt_size == sizeof(*(KEYP))), \
134 dict_find((DICTP), (KEYP)) != NULL)
135
Petr Machatad7e4ca82012-11-28 03:38:47 +0100136/* Find in DICTP a value of type VALUE_TYPE corresponding to KEYP and
137 * return a pointer (VALUE_TYPE *) to it. Returns NULL if the key was
138 * not found. */
Petr Machata98ff3092013-03-08 22:11:36 +0100139#define DICT_FIND_REF(DICTP, KEYP, VALUE_TYPE) \
Petr Machatad7e4ca82012-11-28 03:38:47 +0100140 (assert((DICTP)->keys.elt_size == sizeof(*(KEYP))), \
141 (VALUE_TYPE *)dict_find((DICTP), (KEYP)))
142
Petr Machata98ff3092013-03-08 22:11:36 +0100143/* Find in DICTP a value of type VALUE_TYPE corresponding to KEYP and
144 * copy it to the memory pointed-to by VAR. Returns 0 on success, or
145 * a negative value if the key was not found. */
146#define DICT_FIND_VAL(DICTP, KEYP, VAR) \
147 ({ \
148 assert((DICTP)->keys.elt_size == sizeof(*(KEYP))); \
149 assert((DICTP)->values.elt_size == sizeof((VAR))); \
150 void *_ptr = dict_find((DICTP), (KEYP)); \
151 if (_ptr != NULL) \
152 memcpy((VAR), _ptr, (DICTP)->values.elt_size); \
153 _ptr != NULL ? 0 : -1; \
154 })
155
Petr Machatad7e4ca82012-11-28 03:38:47 +0100156/* Erase from DICT the entry corresponding to KEY. Returns a negative
157 * value if the key was not found, or 0 on success. DTOR_KEY and
158 * DTOR_VALUE, if non-NULL, are called to destroy the erased
159 * value. */
160int dict_erase(struct dict *dict, const void *key,
161 void (*dtor_key)(void *tgt, void *data),
162 void (*dtor_value)(void *tgt, void *data),
163 void *data);
164
165/* Erase from DICTP a value of type VALUE_TYPE corresponding to
166 * KEYP. */
167#define DICT_ERASE(DICTP, KEYP, VALUE_TYPE, DTOR_KEY, DTOR_VALUE, DATA) \
168 ({ \
169 struct dict *_d = (DICTP); \
170 assert(_d->keys.elt_size == sizeof(*KEYP)); \
171 assert(_d->values.elt_size == sizeof(VALUE_TYPE)); \
172 /* Check that callbacks are typed properly. */ \
173 void (*_value_dtor_cb)(VALUE_TYPE *, void *) = DTOR_VALUE; \
174 dict_erase(_d, (KEYP), (DTOR_KEY), \
175 (void (*)(void *, void *))_value_dtor_cb, \
176 (DATA)); \
177 })
178
179/* Destroy DICT. If KEY_DTOR is non-NULL, then it's called on each
180 * key stored in DICT. Similarly for VALUE_DTOR. DATA is passed to
181 * DTOR's verbatim. The memory pointed-to by DICT is not freed. */
182void dict_destroy(struct dict *dict,
183 void (*dtor_key)(void *tgt, void *data),
184 void (*dtor_value)(void *tgt, void *data),
185 void *data);
186
187/* Destroy DICTP, which holds keys of type KEY_TYPE and values of type
188 * VALUE_TYPE, using DTOR. */
189#define DICT_DESTROY(DICTP, KEY_TYPE, VALUE_TYPE, DTOR_KEY, DTOR_VALUE, DATA) \
190 do { \
191 struct dict *_d = (DICTP); \
192 assert(_d->keys.elt_size == sizeof(KEY_TYPE)); \
193 assert(_d->values.elt_size == sizeof(VALUE_TYPE)); \
194 /* Check that callbacks are typed properly. */ \
195 void (*_key_dtor_cb)(KEY_TYPE *, void *) = DTOR_KEY; \
196 void (*_value_dtor_cb)(VALUE_TYPE *, void *) = DTOR_VALUE; \
197 dict_destroy(_d, (void (*)(void *, void *))_key_dtor_cb, \
198 (void (*)(void *, void *))_value_dtor_cb, \
199 (DATA)); \
200 } while (0)
201
202/* Iterate through DICT. See callback.h for notes on iteration
203 * interfaces. Callback arguments are key, value, DATA. Note that
204 * the iteration over DICT is more expensive than in other containers:
205 * while CB is only called for items present in the table, and is
206 * therefore O(number of elements), the iterator needs to go through
207 * all the table, which is proportional to O(size of table).
208 * START_AFTER and the returned iterator are key where the iteration
209 * stopped. */
210void *dict_each(struct dict *dict, void *start_after,
211 enum callback_status (*cb)(void *, void *, void *), void *data);
212
213#define DICT_EACH(DICTP, KEY_TYPE, VALUE_TYPE, START_AFTER, CB, DATA) \
214 /* xxx GCC-ism necessary to get in the safety latches. */ \
215 ({ \
216 assert((DICTP)->keys.elt_size == sizeof(KEY_TYPE)); \
217 assert((DICTP)->values.elt_size == sizeof(VALUE_TYPE)); \
218 /* Check that CB is typed properly. */ \
219 enum callback_status (*_cb)(KEY_TYPE *, VALUE_TYPE *, \
220 void *) = CB; \
Petr Machata38bcdbe2012-12-04 17:56:10 +0100221 KEY_TYPE *_start_after = (START_AFTER); \
222 (KEY_TYPE *)dict_each((DICTP), _start_after, \
Petr Machatad7e4ca82012-11-28 03:38:47 +0100223 (enum callback_status \
224 (*)(void *, void *, void *))_cb, \
225 (DATA)); \
226 })
227
228/* A callback for hashing integers. */
229size_t dict_hash_int(const int *key);
230
231/* An equality predicate callback for integers. */
232int dict_eq_int(const int *key1, const int *key2);
233
234/* A callback for hashing NULL-terminated strings. */
235size_t dict_hash_string(const char **key);
236
237/* An equality predicate callback for strings. */
238int dict_eq_string(const char **key1, const char **key2);
Petr Machataa11cbed2012-05-05 00:07:38 +0200239
Petr Machata3e865762012-11-28 22:06:17 +0100240/* A dtor which calls 'free' on keys in a table. */
241void dict_dtor_string(const char **key, void *data);
242
243/* A cloner that calls 'strdup' on keys in a table. */
244int dict_clone_string(const char **tgt, const char **src, void *data);
245
Petr Machataa11cbed2012-05-05 00:07:38 +0200246#endif /* _DICT_H_ */