1 1.1 christos /* Interface to hashtable implementations. 2 1.1.1.5 christos Copyright (C) 2006-2026 Free Software Foundation, Inc. 3 1.1 christos 4 1.1 christos This file is part of libctf. 5 1.1 christos 6 1.1 christos libctf is free software; you can redistribute it and/or modify it under 7 1.1 christos the terms of the GNU General Public License as published by the Free 8 1.1 christos Software Foundation; either version 3, or (at your option) any later 9 1.1 christos version. 10 1.1 christos 11 1.1 christos This program is distributed in the hope that it will be useful, but 12 1.1 christos WITHOUT ANY WARRANTY; without even the implied warranty of 13 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 14 1.1 christos See the GNU General Public License for more details. 15 1.1 christos 16 1.1 christos You should have received a copy of the GNU General Public License 17 1.1 christos along with this program; see the file COPYING. If not see 18 1.1 christos <http://www.gnu.org/licenses/>. */ 19 1.1 christos 20 1.1 christos #include <ctf-impl.h> 21 1.1 christos #include <string.h> 22 1.1 christos #include "libiberty.h" 23 1.1 christos #include "hashtab.h" 24 1.1 christos 25 1.1.1.4 christos /* We have two hashtable implementations: 26 1.1.1.2 christos 27 1.1.1.2 christos - ctf_dynhash_* is an interface to a dynamically-expanding hash with 28 1.1.1.4 christos unknown size that should support addition of large numbers of items, 29 1.1.1.4 christos and removal as well, and is used only at type-insertion time and during 30 1.1.1.4 christos linking. It can be constructed with an expected initial number of 31 1.1.1.4 christos elements, but need not be. 32 1.1.1.2 christos 33 1.1.1.2 christos - ctf_dynset_* is an interface to a dynamically-expanding hash that contains 34 1.1.1.2 christos only keys: no values. 35 1.1.1.2 christos 36 1.1.1.2 christos These can be implemented by the same underlying hashmap if you wish. */ 37 1.1.1.2 christos 38 1.1.1.4 christos /* The helem is used for general key/value mappings in the ctf_dynhash: the 39 1.1.1.4 christos owner may not have space allocated for it, and will be garbage (not 40 1.1.1.4 christos NULL!) in that case. */ 41 1.1 christos 42 1.1 christos typedef struct ctf_helem 43 1.1 christos { 44 1.1 christos void *key; /* Either a pointer, or a coerced ctf_id_t. */ 45 1.1 christos void *value; /* The value (possibly a coerced int). */ 46 1.1.1.2 christos ctf_dynhash_t *owner; /* The hash that owns us. */ 47 1.1 christos } ctf_helem_t; 48 1.1 christos 49 1.1.1.2 christos /* Equally, the key_free and value_free may not exist. */ 50 1.1.1.2 christos 51 1.1 christos struct ctf_dynhash 52 1.1 christos { 53 1.1 christos struct htab *htab; 54 1.1 christos ctf_hash_free_fun key_free; 55 1.1 christos ctf_hash_free_fun value_free; 56 1.1 christos }; 57 1.1 christos 58 1.1.1.2 christos /* Hash and eq functions for the dynhash and hash. */ 59 1.1 christos 60 1.1 christos unsigned int 61 1.1 christos ctf_hash_integer (const void *ptr) 62 1.1 christos { 63 1.1 christos ctf_helem_t *hep = (ctf_helem_t *) ptr; 64 1.1 christos 65 1.1 christos return htab_hash_pointer (hep->key); 66 1.1 christos } 67 1.1 christos 68 1.1 christos int 69 1.1 christos ctf_hash_eq_integer (const void *a, const void *b) 70 1.1 christos { 71 1.1 christos ctf_helem_t *hep_a = (ctf_helem_t *) a; 72 1.1 christos ctf_helem_t *hep_b = (ctf_helem_t *) b; 73 1.1 christos 74 1.1 christos return htab_eq_pointer (hep_a->key, hep_b->key); 75 1.1 christos } 76 1.1 christos 77 1.1 christos unsigned int 78 1.1 christos ctf_hash_string (const void *ptr) 79 1.1 christos { 80 1.1 christos ctf_helem_t *hep = (ctf_helem_t *) ptr; 81 1.1 christos 82 1.1 christos return htab_hash_string (hep->key); 83 1.1 christos } 84 1.1 christos 85 1.1 christos int 86 1.1 christos ctf_hash_eq_string (const void *a, const void *b) 87 1.1 christos { 88 1.1 christos ctf_helem_t *hep_a = (ctf_helem_t *) a; 89 1.1 christos ctf_helem_t *hep_b = (ctf_helem_t *) b; 90 1.1 christos 91 1.1 christos return !strcmp((const char *) hep_a->key, (const char *) hep_b->key); 92 1.1 christos } 93 1.1 christos 94 1.1.1.2 christos /* Hash a type_key. */ 95 1.1.1.2 christos unsigned int 96 1.1.1.2 christos ctf_hash_type_key (const void *ptr) 97 1.1.1.2 christos { 98 1.1.1.2 christos ctf_helem_t *hep = (ctf_helem_t *) ptr; 99 1.1.1.2 christos ctf_link_type_key_t *k = (ctf_link_type_key_t *) hep->key; 100 1.1.1.2 christos 101 1.1.1.2 christos return htab_hash_pointer (k->cltk_fp) + 59 102 1.1.1.2 christos * htab_hash_pointer ((void *) (uintptr_t) k->cltk_idx); 103 1.1.1.2 christos } 104 1.1.1.2 christos 105 1.1.1.2 christos int 106 1.1.1.2 christos ctf_hash_eq_type_key (const void *a, const void *b) 107 1.1.1.2 christos { 108 1.1.1.2 christos ctf_helem_t *hep_a = (ctf_helem_t *) a; 109 1.1.1.2 christos ctf_helem_t *hep_b = (ctf_helem_t *) b; 110 1.1.1.2 christos ctf_link_type_key_t *key_a = (ctf_link_type_key_t *) hep_a->key; 111 1.1.1.2 christos ctf_link_type_key_t *key_b = (ctf_link_type_key_t *) hep_b->key; 112 1.1.1.2 christos 113 1.1.1.2 christos return (key_a->cltk_fp == key_b->cltk_fp) 114 1.1.1.2 christos && (key_a->cltk_idx == key_b->cltk_idx); 115 1.1.1.2 christos } 116 1.1.1.2 christos 117 1.1.1.2 christos /* Hash a type_id_key. */ 118 1.1 christos unsigned int 119 1.1.1.2 christos ctf_hash_type_id_key (const void *ptr) 120 1.1 christos { 121 1.1 christos ctf_helem_t *hep = (ctf_helem_t *) ptr; 122 1.1.1.2 christos ctf_type_id_key_t *k = (ctf_type_id_key_t *) hep->key; 123 1.1 christos 124 1.1.1.2 christos return htab_hash_pointer ((void *) (uintptr_t) k->ctii_input_num) 125 1.1.1.2 christos + 59 * htab_hash_pointer ((void *) (uintptr_t) k->ctii_type); 126 1.1 christos } 127 1.1 christos 128 1.1 christos int 129 1.1.1.2 christos ctf_hash_eq_type_id_key (const void *a, const void *b) 130 1.1 christos { 131 1.1 christos ctf_helem_t *hep_a = (ctf_helem_t *) a; 132 1.1 christos ctf_helem_t *hep_b = (ctf_helem_t *) b; 133 1.1.1.2 christos ctf_type_id_key_t *key_a = (ctf_type_id_key_t *) hep_a->key; 134 1.1.1.2 christos ctf_type_id_key_t *key_b = (ctf_type_id_key_t *) hep_b->key; 135 1.1 christos 136 1.1.1.2 christos return (key_a->ctii_input_num == key_b->ctii_input_num) 137 1.1.1.2 christos && (key_a->ctii_type == key_b->ctii_type); 138 1.1 christos } 139 1.1 christos 140 1.1 christos /* The dynhash, used for hashes whose size is not known at creation time. */ 141 1.1 christos 142 1.1.1.2 christos /* Free a single ctf_helem with arbitrary key/value functions. */ 143 1.1 christos 144 1.1 christos static void 145 1.1 christos ctf_dynhash_item_free (void *item) 146 1.1 christos { 147 1.1 christos ctf_helem_t *helem = item; 148 1.1 christos 149 1.1.1.2 christos if (helem->owner->key_free && helem->key) 150 1.1.1.2 christos helem->owner->key_free (helem->key); 151 1.1.1.2 christos if (helem->owner->value_free && helem->value) 152 1.1.1.2 christos helem->owner->value_free (helem->value); 153 1.1 christos free (helem); 154 1.1 christos } 155 1.1 christos 156 1.1 christos ctf_dynhash_t * 157 1.1.1.4 christos ctf_dynhash_create_sized (unsigned long nelems, ctf_hash_fun hash_fun, 158 1.1.1.4 christos ctf_hash_eq_fun eq_fun, ctf_hash_free_fun key_free, 159 1.1.1.4 christos ctf_hash_free_fun value_free) 160 1.1 christos { 161 1.1 christos ctf_dynhash_t *dynhash; 162 1.1.1.2 christos htab_del del = ctf_dynhash_item_free; 163 1.1 christos 164 1.1.1.2 christos if (key_free || value_free) 165 1.1.1.2 christos dynhash = malloc (sizeof (ctf_dynhash_t)); 166 1.1.1.2 christos else 167 1.1.1.4 christos { 168 1.1.1.4 christos void *p = malloc (offsetof (ctf_dynhash_t, key_free)); 169 1.1.1.4 christos dynhash = p; 170 1.1.1.4 christos } 171 1.1 christos if (!dynhash) 172 1.1 christos return NULL; 173 1.1 christos 174 1.1.1.2 christos if (key_free == NULL && value_free == NULL) 175 1.1.1.2 christos del = free; 176 1.1.1.2 christos 177 1.1.1.4 christos if ((dynhash->htab = htab_create_alloc (nelems, (htab_hash) hash_fun, eq_fun, 178 1.1.1.2 christos del, xcalloc, free)) == NULL) 179 1.1 christos { 180 1.1 christos free (dynhash); 181 1.1 christos return NULL; 182 1.1 christos } 183 1.1 christos 184 1.1.1.2 christos if (key_free || value_free) 185 1.1.1.2 christos { 186 1.1.1.2 christos dynhash->key_free = key_free; 187 1.1.1.2 christos dynhash->value_free = value_free; 188 1.1.1.2 christos } 189 1.1 christos 190 1.1 christos return dynhash; 191 1.1 christos } 192 1.1 christos 193 1.1.1.4 christos ctf_dynhash_t * 194 1.1.1.4 christos ctf_dynhash_create (ctf_hash_fun hash_fun, ctf_hash_eq_fun eq_fun, 195 1.1.1.4 christos ctf_hash_free_fun key_free, ctf_hash_free_fun value_free) 196 1.1.1.4 christos { 197 1.1.1.4 christos /* 7 is arbitrary and not benchmarked yet. */ 198 1.1.1.4 christos 199 1.1.1.4 christos return ctf_dynhash_create_sized (7, hash_fun, eq_fun, key_free, value_free); 200 1.1.1.4 christos } 201 1.1.1.4 christos 202 1.1 christos static ctf_helem_t ** 203 1.1 christos ctf_hashtab_lookup (struct htab *htab, const void *key, enum insert_option insert) 204 1.1 christos { 205 1.1 christos ctf_helem_t tmp = { .key = (void *) key }; 206 1.1 christos return (ctf_helem_t **) htab_find_slot (htab, &tmp, insert); 207 1.1 christos } 208 1.1 christos 209 1.1 christos static ctf_helem_t * 210 1.1 christos ctf_hashtab_insert (struct htab *htab, void *key, void *value, 211 1.1 christos ctf_hash_free_fun key_free, 212 1.1 christos ctf_hash_free_fun value_free) 213 1.1 christos { 214 1.1 christos ctf_helem_t **slot; 215 1.1 christos 216 1.1 christos slot = ctf_hashtab_lookup (htab, key, INSERT); 217 1.1 christos 218 1.1 christos if (!slot) 219 1.1 christos { 220 1.1.1.2 christos errno = ENOMEM; 221 1.1 christos return NULL; 222 1.1 christos } 223 1.1 christos 224 1.1 christos if (!*slot) 225 1.1 christos { 226 1.1.1.2 christos /* Only spend space on the owner if we're going to use it: if there is a 227 1.1.1.2 christos key or value freeing function. */ 228 1.1.1.2 christos if (key_free || value_free) 229 1.1.1.2 christos *slot = malloc (sizeof (ctf_helem_t)); 230 1.1.1.2 christos else 231 1.1.1.4 christos { 232 1.1.1.4 christos void *p = malloc (offsetof (ctf_helem_t, owner)); 233 1.1.1.4 christos *slot = p; 234 1.1.1.4 christos } 235 1.1 christos if (!*slot) 236 1.1 christos return NULL; 237 1.1.1.2 christos (*slot)->key = key; 238 1.1 christos } 239 1.1 christos else 240 1.1 christos { 241 1.1 christos if (key_free) 242 1.1.1.2 christos key_free (key); 243 1.1 christos if (value_free) 244 1.1 christos value_free ((*slot)->value); 245 1.1 christos } 246 1.1 christos (*slot)->value = value; 247 1.1 christos return *slot; 248 1.1 christos } 249 1.1 christos 250 1.1 christos int 251 1.1 christos ctf_dynhash_insert (ctf_dynhash_t *hp, void *key, void *value) 252 1.1 christos { 253 1.1 christos ctf_helem_t *slot; 254 1.1.1.2 christos ctf_hash_free_fun key_free = NULL, value_free = NULL; 255 1.1 christos 256 1.1.1.2 christos if (hp->htab->del_f == ctf_dynhash_item_free) 257 1.1.1.2 christos { 258 1.1.1.2 christos key_free = hp->key_free; 259 1.1.1.2 christos value_free = hp->value_free; 260 1.1.1.2 christos } 261 1.1 christos slot = ctf_hashtab_insert (hp->htab, key, value, 262 1.1.1.2 christos key_free, value_free); 263 1.1 christos 264 1.1 christos if (!slot) 265 1.1.1.4 christos return -errno; 266 1.1 christos 267 1.1.1.2 christos /* Keep track of the owner, so that the del function can get at the key_free 268 1.1.1.2 christos and value_free functions. Only do this if one of those functions is set: 269 1.1.1.2 christos if not, the owner is not even present in the helem. */ 270 1.1 christos 271 1.1.1.2 christos if (key_free || value_free) 272 1.1.1.2 christos slot->owner = hp; 273 1.1 christos 274 1.1 christos return 0; 275 1.1 christos } 276 1.1 christos 277 1.1 christos void 278 1.1 christos ctf_dynhash_remove (ctf_dynhash_t *hp, const void *key) 279 1.1 christos { 280 1.1.1.2 christos ctf_helem_t hep = { (void *) key, NULL, NULL }; 281 1.1 christos htab_remove_elt (hp->htab, &hep); 282 1.1 christos } 283 1.1 christos 284 1.1 christos void 285 1.1 christos ctf_dynhash_empty (ctf_dynhash_t *hp) 286 1.1 christos { 287 1.1 christos htab_empty (hp->htab); 288 1.1 christos } 289 1.1 christos 290 1.1.1.2 christos size_t 291 1.1.1.2 christos ctf_dynhash_elements (ctf_dynhash_t *hp) 292 1.1.1.2 christos { 293 1.1.1.2 christos return htab_elements (hp->htab); 294 1.1.1.2 christos } 295 1.1.1.2 christos 296 1.1 christos void * 297 1.1 christos ctf_dynhash_lookup (ctf_dynhash_t *hp, const void *key) 298 1.1 christos { 299 1.1 christos ctf_helem_t **slot; 300 1.1 christos 301 1.1 christos slot = ctf_hashtab_lookup (hp->htab, key, NO_INSERT); 302 1.1 christos 303 1.1 christos if (slot) 304 1.1 christos return (*slot)->value; 305 1.1 christos 306 1.1 christos return NULL; 307 1.1 christos } 308 1.1 christos 309 1.1.1.2 christos /* TRUE/FALSE return. */ 310 1.1.1.2 christos int 311 1.1.1.2 christos ctf_dynhash_lookup_kv (ctf_dynhash_t *hp, const void *key, 312 1.1.1.2 christos const void **orig_key, void **value) 313 1.1.1.2 christos { 314 1.1.1.2 christos ctf_helem_t **slot; 315 1.1.1.2 christos 316 1.1.1.2 christos slot = ctf_hashtab_lookup (hp->htab, key, NO_INSERT); 317 1.1.1.2 christos 318 1.1.1.2 christos if (slot) 319 1.1.1.2 christos { 320 1.1.1.2 christos if (orig_key) 321 1.1.1.2 christos *orig_key = (*slot)->key; 322 1.1.1.2 christos if (value) 323 1.1.1.2 christos *value = (*slot)->value; 324 1.1.1.2 christos return 1; 325 1.1.1.2 christos } 326 1.1.1.2 christos return 0; 327 1.1.1.2 christos } 328 1.1.1.2 christos 329 1.1 christos typedef struct ctf_traverse_cb_arg 330 1.1 christos { 331 1.1 christos ctf_hash_iter_f fun; 332 1.1 christos void *arg; 333 1.1 christos } ctf_traverse_cb_arg_t; 334 1.1 christos 335 1.1 christos static int 336 1.1 christos ctf_hashtab_traverse (void **slot, void *arg_) 337 1.1 christos { 338 1.1 christos ctf_helem_t *helem = *((ctf_helem_t **) slot); 339 1.1 christos ctf_traverse_cb_arg_t *arg = (ctf_traverse_cb_arg_t *) arg_; 340 1.1 christos 341 1.1 christos arg->fun (helem->key, helem->value, arg->arg); 342 1.1 christos return 1; 343 1.1 christos } 344 1.1 christos 345 1.1 christos void 346 1.1 christos ctf_dynhash_iter (ctf_dynhash_t *hp, ctf_hash_iter_f fun, void *arg_) 347 1.1 christos { 348 1.1 christos ctf_traverse_cb_arg_t arg = { fun, arg_ }; 349 1.1 christos htab_traverse (hp->htab, ctf_hashtab_traverse, &arg); 350 1.1 christos } 351 1.1 christos 352 1.1.1.2 christos typedef struct ctf_traverse_find_cb_arg 353 1.1.1.2 christos { 354 1.1.1.2 christos ctf_hash_iter_find_f fun; 355 1.1.1.2 christos void *arg; 356 1.1.1.2 christos void *found_key; 357 1.1.1.2 christos } ctf_traverse_find_cb_arg_t; 358 1.1.1.2 christos 359 1.1.1.2 christos static int 360 1.1.1.2 christos ctf_hashtab_traverse_find (void **slot, void *arg_) 361 1.1.1.2 christos { 362 1.1.1.2 christos ctf_helem_t *helem = *((ctf_helem_t **) slot); 363 1.1.1.2 christos ctf_traverse_find_cb_arg_t *arg = (ctf_traverse_find_cb_arg_t *) arg_; 364 1.1.1.2 christos 365 1.1.1.2 christos if (arg->fun (helem->key, helem->value, arg->arg)) 366 1.1.1.2 christos { 367 1.1.1.2 christos arg->found_key = helem->key; 368 1.1.1.2 christos return 0; 369 1.1.1.2 christos } 370 1.1.1.2 christos return 1; 371 1.1.1.2 christos } 372 1.1.1.2 christos 373 1.1.1.2 christos void * 374 1.1.1.2 christos ctf_dynhash_iter_find (ctf_dynhash_t *hp, ctf_hash_iter_find_f fun, void *arg_) 375 1.1.1.2 christos { 376 1.1.1.2 christos ctf_traverse_find_cb_arg_t arg = { fun, arg_, NULL }; 377 1.1.1.2 christos htab_traverse (hp->htab, ctf_hashtab_traverse_find, &arg); 378 1.1.1.2 christos return arg.found_key; 379 1.1.1.2 christos } 380 1.1.1.2 christos 381 1.1 christos typedef struct ctf_traverse_remove_cb_arg 382 1.1 christos { 383 1.1 christos struct htab *htab; 384 1.1 christos ctf_hash_iter_remove_f fun; 385 1.1 christos void *arg; 386 1.1 christos } ctf_traverse_remove_cb_arg_t; 387 1.1 christos 388 1.1 christos static int 389 1.1 christos ctf_hashtab_traverse_remove (void **slot, void *arg_) 390 1.1 christos { 391 1.1 christos ctf_helem_t *helem = *((ctf_helem_t **) slot); 392 1.1 christos ctf_traverse_remove_cb_arg_t *arg = (ctf_traverse_remove_cb_arg_t *) arg_; 393 1.1 christos 394 1.1 christos if (arg->fun (helem->key, helem->value, arg->arg)) 395 1.1 christos htab_clear_slot (arg->htab, slot); 396 1.1 christos return 1; 397 1.1 christos } 398 1.1 christos 399 1.1 christos void 400 1.1 christos ctf_dynhash_iter_remove (ctf_dynhash_t *hp, ctf_hash_iter_remove_f fun, 401 1.1 christos void *arg_) 402 1.1 christos { 403 1.1 christos ctf_traverse_remove_cb_arg_t arg = { hp->htab, fun, arg_ }; 404 1.1 christos htab_traverse (hp->htab, ctf_hashtab_traverse_remove, &arg); 405 1.1 christos } 406 1.1 christos 407 1.1.1.2 christos /* Traverse a dynhash in arbitrary order, in _next iterator form. 408 1.1.1.2 christos 409 1.1.1.4 christos Adding entries to the dynhash while iterating is not supported (just as it 410 1.1.1.4 christos isn't for htab_traverse). Deleting is fine (see ctf_dynhash_next_remove, 411 1.1.1.4 christos below). 412 1.1.1.2 christos 413 1.1.1.2 christos Note: unusually, this returns zero on success and a *positive* value on 414 1.1.1.2 christos error, because it does not take an fp, taking an error pointer would be 415 1.1.1.2 christos incredibly clunky, and nearly all error-handling ends up stuffing the result 416 1.1.1.2 christos of this into some sort of errno or ctf_errno, which is invariably 417 1.1.1.2 christos positive. So doing this simplifies essentially all callers. */ 418 1.1.1.2 christos int 419 1.1.1.2 christos ctf_dynhash_next (ctf_dynhash_t *h, ctf_next_t **it, void **key, void **value) 420 1.1.1.2 christos { 421 1.1.1.2 christos ctf_next_t *i = *it; 422 1.1.1.2 christos ctf_helem_t *slot; 423 1.1.1.2 christos 424 1.1.1.2 christos if (!i) 425 1.1.1.2 christos { 426 1.1.1.2 christos size_t size = htab_size (h->htab); 427 1.1.1.2 christos 428 1.1.1.2 christos /* If the table has too many entries to fit in an ssize_t, just give up. 429 1.1.1.2 christos This might be spurious, but if any type-related hashtable has ever been 430 1.1.1.2 christos nearly as large as that then something very odd is going on. */ 431 1.1.1.2 christos if (((ssize_t) size) < 0) 432 1.1.1.2 christos return EDOM; 433 1.1.1.2 christos 434 1.1.1.2 christos if ((i = ctf_next_create ()) == NULL) 435 1.1.1.2 christos return ENOMEM; 436 1.1.1.2 christos 437 1.1.1.2 christos i->u.ctn_hash_slot = h->htab->entries; 438 1.1.1.2 christos i->cu.ctn_h = h; 439 1.1.1.2 christos i->ctn_n = 0; 440 1.1.1.2 christos i->ctn_size = (ssize_t) size; 441 1.1.1.2 christos i->ctn_iter_fun = (void (*) (void)) ctf_dynhash_next; 442 1.1.1.2 christos *it = i; 443 1.1.1.2 christos } 444 1.1.1.2 christos 445 1.1.1.2 christos if ((void (*) (void)) ctf_dynhash_next != i->ctn_iter_fun) 446 1.1.1.2 christos return ECTF_NEXT_WRONGFUN; 447 1.1.1.2 christos 448 1.1.1.2 christos if (h != i->cu.ctn_h) 449 1.1.1.2 christos return ECTF_NEXT_WRONGFP; 450 1.1.1.2 christos 451 1.1.1.2 christos if ((ssize_t) i->ctn_n == i->ctn_size) 452 1.1.1.2 christos goto hash_end; 453 1.1.1.2 christos 454 1.1.1.2 christos while ((ssize_t) i->ctn_n < i->ctn_size 455 1.1.1.2 christos && (*i->u.ctn_hash_slot == HTAB_EMPTY_ENTRY 456 1.1.1.2 christos || *i->u.ctn_hash_slot == HTAB_DELETED_ENTRY)) 457 1.1.1.2 christos { 458 1.1.1.2 christos i->u.ctn_hash_slot++; 459 1.1.1.2 christos i->ctn_n++; 460 1.1.1.2 christos } 461 1.1.1.2 christos 462 1.1.1.2 christos if ((ssize_t) i->ctn_n == i->ctn_size) 463 1.1.1.2 christos goto hash_end; 464 1.1.1.2 christos 465 1.1.1.2 christos slot = *i->u.ctn_hash_slot; 466 1.1.1.2 christos 467 1.1.1.2 christos if (key) 468 1.1.1.2 christos *key = slot->key; 469 1.1.1.2 christos if (value) 470 1.1.1.2 christos *value = slot->value; 471 1.1.1.2 christos 472 1.1.1.2 christos i->u.ctn_hash_slot++; 473 1.1.1.2 christos i->ctn_n++; 474 1.1.1.2 christos 475 1.1.1.2 christos return 0; 476 1.1.1.2 christos 477 1.1.1.2 christos hash_end: 478 1.1.1.2 christos ctf_next_destroy (i); 479 1.1.1.2 christos *it = NULL; 480 1.1.1.2 christos return ECTF_NEXT_END; 481 1.1.1.2 christos } 482 1.1.1.2 christos 483 1.1.1.4 christos /* Remove the entry most recently returned by ctf_dynhash_next. 484 1.1.1.4 christos 485 1.1.1.4 christos Returns ECTF_NEXT_END if this is impossible (already removed, iterator not 486 1.1.1.4 christos initialized, iterator off the end). */ 487 1.1.1.4 christos 488 1.1.1.4 christos int 489 1.1.1.4 christos ctf_dynhash_next_remove (ctf_next_t * const *it) 490 1.1.1.4 christos { 491 1.1.1.4 christos ctf_next_t *i = *it; 492 1.1.1.4 christos 493 1.1.1.4 christos if ((void (*) (void)) ctf_dynhash_next != i->ctn_iter_fun) 494 1.1.1.4 christos return ECTF_NEXT_WRONGFUN; 495 1.1.1.4 christos 496 1.1.1.4 christos if (!i) 497 1.1.1.4 christos return ECTF_NEXT_END; 498 1.1.1.4 christos 499 1.1.1.4 christos if (i->ctn_n == 0) 500 1.1.1.4 christos return ECTF_NEXT_END; 501 1.1.1.4 christos 502 1.1.1.4 christos htab_clear_slot (i->cu.ctn_h->htab, i->u.ctn_hash_slot - 1); 503 1.1.1.4 christos 504 1.1.1.4 christos return 0; 505 1.1.1.4 christos } 506 1.1.1.4 christos 507 1.1.1.2 christos int 508 1.1.1.2 christos ctf_dynhash_sort_by_name (const ctf_next_hkv_t *one, const ctf_next_hkv_t *two, 509 1.1.1.2 christos void *unused _libctf_unused_) 510 1.1.1.2 christos { 511 1.1.1.2 christos return strcmp ((char *) one->hkv_key, (char *) two->hkv_key); 512 1.1.1.2 christos } 513 1.1.1.2 christos 514 1.1.1.2 christos /* Traverse a sorted dynhash, in _next iterator form. 515 1.1.1.2 christos 516 1.1.1.2 christos See ctf_dynhash_next for notes on error returns, etc. 517 1.1.1.2 christos 518 1.1.1.2 christos Sort keys before iterating over them using the SORT_FUN and SORT_ARG. 519 1.1.1.2 christos 520 1.1.1.2 christos If SORT_FUN is null, thunks to ctf_dynhash_next. */ 521 1.1.1.2 christos int 522 1.1.1.2 christos ctf_dynhash_next_sorted (ctf_dynhash_t *h, ctf_next_t **it, void **key, 523 1.1.1.2 christos void **value, ctf_hash_sort_f sort_fun, void *sort_arg) 524 1.1.1.2 christos { 525 1.1.1.2 christos ctf_next_t *i = *it; 526 1.1.1.2 christos 527 1.1.1.2 christos if (sort_fun == NULL) 528 1.1.1.2 christos return ctf_dynhash_next (h, it, key, value); 529 1.1.1.2 christos 530 1.1.1.2 christos if (!i) 531 1.1.1.2 christos { 532 1.1.1.2 christos size_t els = ctf_dynhash_elements (h); 533 1.1.1.2 christos ctf_next_t *accum_i = NULL; 534 1.1.1.2 christos void *key, *value; 535 1.1.1.2 christos int err; 536 1.1.1.2 christos ctf_next_hkv_t *walk; 537 1.1.1.2 christos 538 1.1.1.2 christos if (((ssize_t) els) < 0) 539 1.1.1.2 christos return EDOM; 540 1.1.1.2 christos 541 1.1.1.2 christos if ((i = ctf_next_create ()) == NULL) 542 1.1.1.2 christos return ENOMEM; 543 1.1.1.2 christos 544 1.1.1.2 christos if ((i->u.ctn_sorted_hkv = calloc (els, sizeof (ctf_next_hkv_t))) == NULL) 545 1.1.1.2 christos { 546 1.1.1.2 christos ctf_next_destroy (i); 547 1.1.1.2 christos return ENOMEM; 548 1.1.1.2 christos } 549 1.1.1.2 christos walk = i->u.ctn_sorted_hkv; 550 1.1.1.2 christos 551 1.1.1.2 christos i->cu.ctn_h = h; 552 1.1.1.2 christos 553 1.1.1.2 christos while ((err = ctf_dynhash_next (h, &accum_i, &key, &value)) == 0) 554 1.1.1.2 christos { 555 1.1.1.2 christos walk->hkv_key = key; 556 1.1.1.2 christos walk->hkv_value = value; 557 1.1.1.2 christos walk++; 558 1.1.1.2 christos } 559 1.1.1.2 christos if (err != ECTF_NEXT_END) 560 1.1.1.2 christos { 561 1.1.1.2 christos ctf_next_destroy (i); 562 1.1.1.2 christos return err; 563 1.1.1.2 christos } 564 1.1.1.2 christos 565 1.1.1.2 christos if (sort_fun) 566 1.1.1.2 christos ctf_qsort_r (i->u.ctn_sorted_hkv, els, sizeof (ctf_next_hkv_t), 567 1.1.1.2 christos (int (*) (const void *, const void *, void *)) sort_fun, 568 1.1.1.2 christos sort_arg); 569 1.1.1.2 christos i->ctn_n = 0; 570 1.1.1.2 christos i->ctn_size = (ssize_t) els; 571 1.1.1.2 christos i->ctn_iter_fun = (void (*) (void)) ctf_dynhash_next_sorted; 572 1.1.1.2 christos *it = i; 573 1.1.1.2 christos } 574 1.1.1.2 christos 575 1.1.1.2 christos if ((void (*) (void)) ctf_dynhash_next_sorted != i->ctn_iter_fun) 576 1.1.1.2 christos return ECTF_NEXT_WRONGFUN; 577 1.1.1.2 christos 578 1.1.1.2 christos if (h != i->cu.ctn_h) 579 1.1.1.2 christos return ECTF_NEXT_WRONGFP; 580 1.1.1.2 christos 581 1.1.1.2 christos if ((ssize_t) i->ctn_n == i->ctn_size) 582 1.1.1.2 christos { 583 1.1.1.2 christos ctf_next_destroy (i); 584 1.1.1.2 christos *it = NULL; 585 1.1.1.2 christos return ECTF_NEXT_END; 586 1.1.1.2 christos } 587 1.1.1.2 christos 588 1.1.1.2 christos if (key) 589 1.1.1.2 christos *key = i->u.ctn_sorted_hkv[i->ctn_n].hkv_key; 590 1.1.1.2 christos if (value) 591 1.1.1.2 christos *value = i->u.ctn_sorted_hkv[i->ctn_n].hkv_value; 592 1.1.1.2 christos i->ctn_n++; 593 1.1.1.2 christos return 0; 594 1.1.1.2 christos } 595 1.1.1.2 christos 596 1.1 christos void 597 1.1 christos ctf_dynhash_destroy (ctf_dynhash_t *hp) 598 1.1 christos { 599 1.1 christos if (hp != NULL) 600 1.1 christos htab_delete (hp->htab); 601 1.1 christos free (hp); 602 1.1 christos } 603 1.1 christos 604 1.1.1.2 christos /* The dynset, used for sets of keys with no value. The implementation of this 605 1.1.1.2 christos can be much simpler, because without a value the slot can simply be the 606 1.1.1.2 christos stored key, which means we don't need to store the freeing functions and the 607 1.1.1.2 christos dynset itself is just a htab. */ 608 1.1.1.2 christos 609 1.1.1.2 christos ctf_dynset_t * 610 1.1.1.2 christos ctf_dynset_create (htab_hash hash_fun, htab_eq eq_fun, 611 1.1.1.2 christos ctf_hash_free_fun key_free) 612 1.1.1.2 christos { 613 1.1.1.2 christos /* 7 is arbitrary and untested for now. */ 614 1.1.1.2 christos return (ctf_dynset_t *) htab_create_alloc (7, (htab_hash) hash_fun, eq_fun, 615 1.1.1.2 christos key_free, xcalloc, free); 616 1.1.1.2 christos } 617 1.1.1.2 christos 618 1.1.1.2 christos /* The dynset has one complexity: the underlying implementation reserves two 619 1.1.1.2 christos values for internal hash table implementation details (empty versus deleted 620 1.1.1.2 christos entries). These values are otherwise very useful for pointers cast to ints, 621 1.1.1.2 christos so transform the ctf_dynset_inserted value to allow for it. (This 622 1.1.1.2 christos introduces an ambiguity in that one can no longer store these two values in 623 1.1.1.2 christos the dynset, but if we pick high enough values this is very unlikely to be a 624 1.1.1.2 christos problem.) 625 1.1.1.2 christos 626 1.1.1.2 christos We leak this implementation detail to the freeing functions on the grounds 627 1.1.1.2 christos that any use of these functions is overwhelmingly likely to be in sets using 628 1.1.1.2 christos real pointers, which will be unaffected. */ 629 1.1.1.2 christos 630 1.1.1.2 christos #define DYNSET_EMPTY_ENTRY_REPLACEMENT ((void *) (uintptr_t) -64) 631 1.1.1.2 christos #define DYNSET_DELETED_ENTRY_REPLACEMENT ((void *) (uintptr_t) -63) 632 1.1.1.2 christos 633 1.1.1.2 christos static void * 634 1.1.1.2 christos key_to_internal (const void *key) 635 1.1.1.2 christos { 636 1.1.1.2 christos if (key == HTAB_EMPTY_ENTRY) 637 1.1.1.2 christos return DYNSET_EMPTY_ENTRY_REPLACEMENT; 638 1.1.1.2 christos else if (key == HTAB_DELETED_ENTRY) 639 1.1.1.2 christos return DYNSET_DELETED_ENTRY_REPLACEMENT; 640 1.1.1.2 christos 641 1.1.1.2 christos return (void *) key; 642 1.1.1.2 christos } 643 1.1.1.2 christos 644 1.1.1.2 christos static void * 645 1.1.1.2 christos internal_to_key (const void *internal) 646 1.1.1.2 christos { 647 1.1.1.2 christos if (internal == DYNSET_EMPTY_ENTRY_REPLACEMENT) 648 1.1.1.2 christos return HTAB_EMPTY_ENTRY; 649 1.1.1.2 christos else if (internal == DYNSET_DELETED_ENTRY_REPLACEMENT) 650 1.1.1.2 christos return HTAB_DELETED_ENTRY; 651 1.1.1.2 christos return (void *) internal; 652 1.1.1.2 christos } 653 1.1.1.2 christos 654 1.1.1.2 christos int 655 1.1.1.2 christos ctf_dynset_insert (ctf_dynset_t *hp, void *key) 656 1.1.1.2 christos { 657 1.1.1.2 christos struct htab *htab = (struct htab *) hp; 658 1.1.1.2 christos void **slot; 659 1.1.1.2 christos 660 1.1.1.4 christos slot = htab_find_slot (htab, key_to_internal (key), INSERT); 661 1.1.1.2 christos 662 1.1.1.2 christos if (!slot) 663 1.1.1.2 christos { 664 1.1.1.2 christos errno = ENOMEM; 665 1.1.1.2 christos return -errno; 666 1.1.1.2 christos } 667 1.1.1.2 christos 668 1.1.1.2 christos if (*slot) 669 1.1.1.2 christos { 670 1.1.1.2 christos if (htab->del_f) 671 1.1.1.2 christos (*htab->del_f) (*slot); 672 1.1.1.2 christos } 673 1.1.1.2 christos 674 1.1.1.2 christos *slot = key_to_internal (key); 675 1.1.1.2 christos 676 1.1.1.2 christos return 0; 677 1.1.1.2 christos } 678 1.1.1.2 christos 679 1.1.1.2 christos void 680 1.1.1.2 christos ctf_dynset_remove (ctf_dynset_t *hp, const void *key) 681 1.1.1.2 christos { 682 1.1.1.2 christos htab_remove_elt ((struct htab *) hp, key_to_internal (key)); 683 1.1.1.2 christos } 684 1.1.1.2 christos 685 1.1.1.4 christos size_t 686 1.1.1.4 christos ctf_dynset_elements (ctf_dynset_t *hp) 687 1.1.1.4 christos { 688 1.1.1.4 christos return htab_elements ((struct htab *) hp); 689 1.1.1.4 christos } 690 1.1.1.4 christos 691 1.1.1.2 christos void 692 1.1.1.2 christos ctf_dynset_destroy (ctf_dynset_t *hp) 693 1.1.1.2 christos { 694 1.1.1.2 christos if (hp != NULL) 695 1.1.1.2 christos htab_delete ((struct htab *) hp); 696 1.1.1.2 christos } 697 1.1.1.2 christos 698 1.1.1.2 christos void * 699 1.1.1.2 christos ctf_dynset_lookup (ctf_dynset_t *hp, const void *key) 700 1.1.1.2 christos { 701 1.1.1.2 christos void **slot = htab_find_slot ((struct htab *) hp, 702 1.1.1.2 christos key_to_internal (key), NO_INSERT); 703 1.1.1.2 christos 704 1.1.1.2 christos if (slot) 705 1.1.1.2 christos return internal_to_key (*slot); 706 1.1.1.2 christos return NULL; 707 1.1.1.2 christos } 708 1.1.1.2 christos 709 1.1.1.2 christos /* TRUE/FALSE return. */ 710 1.1.1.2 christos int 711 1.1.1.2 christos ctf_dynset_exists (ctf_dynset_t *hp, const void *key, const void **orig_key) 712 1.1.1.2 christos { 713 1.1.1.2 christos void **slot = htab_find_slot ((struct htab *) hp, 714 1.1.1.2 christos key_to_internal (key), NO_INSERT); 715 1.1.1.2 christos 716 1.1.1.2 christos if (orig_key && slot) 717 1.1.1.2 christos *orig_key = internal_to_key (*slot); 718 1.1.1.2 christos return (slot != NULL); 719 1.1.1.2 christos } 720 1.1.1.2 christos 721 1.1.1.2 christos /* Look up a completely random value from the set, if any exist. 722 1.1.1.2 christos Keys with value zero cannot be distinguished from a nonexistent key. */ 723 1.1.1.2 christos void * 724 1.1.1.2 christos ctf_dynset_lookup_any (ctf_dynset_t *hp) 725 1.1.1.2 christos { 726 1.1.1.2 christos struct htab *htab = (struct htab *) hp; 727 1.1.1.2 christos void **slot = htab->entries; 728 1.1.1.2 christos void **limit = slot + htab_size (htab); 729 1.1.1.2 christos 730 1.1.1.2 christos while (slot < limit 731 1.1.1.2 christos && (*slot == HTAB_EMPTY_ENTRY || *slot == HTAB_DELETED_ENTRY)) 732 1.1.1.2 christos slot++; 733 1.1.1.2 christos 734 1.1.1.2 christos if (slot < limit) 735 1.1.1.2 christos return internal_to_key (*slot); 736 1.1.1.2 christos return NULL; 737 1.1.1.2 christos } 738 1.1.1.2 christos 739 1.1.1.2 christos /* Traverse a dynset in arbitrary order, in _next iterator form. 740 1.1.1.2 christos 741 1.1.1.2 christos Otherwise, just like ctf_dynhash_next. */ 742 1.1.1.2 christos int 743 1.1.1.2 christos ctf_dynset_next (ctf_dynset_t *hp, ctf_next_t **it, void **key) 744 1.1.1.2 christos { 745 1.1.1.2 christos struct htab *htab = (struct htab *) hp; 746 1.1.1.2 christos ctf_next_t *i = *it; 747 1.1.1.2 christos void *slot; 748 1.1.1.2 christos 749 1.1.1.2 christos if (!i) 750 1.1.1.2 christos { 751 1.1.1.2 christos size_t size = htab_size (htab); 752 1.1.1.2 christos 753 1.1.1.2 christos /* If the table has too many entries to fit in an ssize_t, just give up. 754 1.1.1.2 christos This might be spurious, but if any type-related hashtable has ever been 755 1.1.1.2 christos nearly as large as that then somthing very odd is going on. */ 756 1.1.1.2 christos 757 1.1.1.2 christos if (((ssize_t) size) < 0) 758 1.1.1.2 christos return EDOM; 759 1.1.1.2 christos 760 1.1.1.2 christos if ((i = ctf_next_create ()) == NULL) 761 1.1.1.2 christos return ENOMEM; 762 1.1.1.2 christos 763 1.1.1.2 christos i->u.ctn_hash_slot = htab->entries; 764 1.1.1.2 christos i->cu.ctn_s = hp; 765 1.1.1.2 christos i->ctn_n = 0; 766 1.1.1.2 christos i->ctn_size = (ssize_t) size; 767 1.1.1.2 christos i->ctn_iter_fun = (void (*) (void)) ctf_dynset_next; 768 1.1.1.2 christos *it = i; 769 1.1.1.2 christos } 770 1.1.1.2 christos 771 1.1.1.2 christos if ((void (*) (void)) ctf_dynset_next != i->ctn_iter_fun) 772 1.1.1.2 christos return ECTF_NEXT_WRONGFUN; 773 1.1.1.2 christos 774 1.1.1.2 christos if (hp != i->cu.ctn_s) 775 1.1.1.2 christos return ECTF_NEXT_WRONGFP; 776 1.1.1.2 christos 777 1.1.1.2 christos if ((ssize_t) i->ctn_n == i->ctn_size) 778 1.1.1.2 christos goto set_end; 779 1.1.1.2 christos 780 1.1.1.2 christos while ((ssize_t) i->ctn_n < i->ctn_size 781 1.1.1.2 christos && (*i->u.ctn_hash_slot == HTAB_EMPTY_ENTRY 782 1.1.1.2 christos || *i->u.ctn_hash_slot == HTAB_DELETED_ENTRY)) 783 1.1.1.2 christos { 784 1.1.1.2 christos i->u.ctn_hash_slot++; 785 1.1.1.2 christos i->ctn_n++; 786 1.1.1.2 christos } 787 1.1.1.2 christos 788 1.1.1.2 christos if ((ssize_t) i->ctn_n == i->ctn_size) 789 1.1.1.2 christos goto set_end; 790 1.1.1.2 christos 791 1.1.1.2 christos slot = *i->u.ctn_hash_slot; 792 1.1.1.2 christos 793 1.1.1.2 christos if (key) 794 1.1.1.2 christos *key = internal_to_key (slot); 795 1.1.1.2 christos 796 1.1.1.2 christos i->u.ctn_hash_slot++; 797 1.1.1.2 christos i->ctn_n++; 798 1.1.1.2 christos 799 1.1.1.2 christos return 0; 800 1.1.1.2 christos 801 1.1.1.2 christos set_end: 802 1.1.1.2 christos ctf_next_destroy (i); 803 1.1.1.2 christos *it = NULL; 804 1.1.1.2 christos return ECTF_NEXT_END; 805 1.1.1.2 christos } 806 1.1.1.2 christos 807 1.1.1.4 christos /* Helper functions for insertion/removal of types. */ 808 1.1 christos 809 1.1 christos int 810 1.1.1.4 christos ctf_dynhash_insert_type (ctf_dict_t *fp, ctf_dynhash_t *hp, uint32_t type, 811 1.1.1.4 christos uint32_t name) 812 1.1 christos { 813 1.1.1.4 christos const char *str; 814 1.1.1.4 christos int err; 815 1.1 christos 816 1.1 christos if (type == 0) 817 1.1 christos return EINVAL; 818 1.1 christos 819 1.1.1.4 christos if ((str = ctf_strptr_validate (fp, name)) == NULL) 820 1.1.1.4 christos return ctf_errno (fp) * -1; 821 1.1 christos 822 1.1 christos if (str[0] == '\0') 823 1.1 christos return 0; /* Just ignore empty strings on behalf of caller. */ 824 1.1 christos 825 1.1.1.4 christos if ((err = ctf_dynhash_insert (hp, (char *) str, 826 1.1.1.4 christos (void *) (ptrdiff_t) type)) == 0) 827 1.1 christos return 0; 828 1.1 christos 829 1.1.1.4 christos /* ctf_dynhash_insert returns a negative error value: negate it for 830 1.1.1.4 christos ctf_set_errno. */ 831 1.1.1.4 christos ctf_set_errno (fp, err * -1); 832 1.1.1.4 christos return err; 833 1.1 christos } 834 1.1 christos 835 1.1 christos ctf_id_t 836 1.1.1.4 christos ctf_dynhash_lookup_type (ctf_dynhash_t *hp, const char *key) 837 1.1 christos { 838 1.1.1.4 christos void *value; 839 1.1 christos 840 1.1.1.4 christos if (ctf_dynhash_lookup_kv (hp, key, NULL, &value)) 841 1.1.1.4 christos return (ctf_id_t) (uintptr_t) value; 842 1.1 christos 843 1.1 christos return 0; 844 1.1 christos } 845