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