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