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