Coverage Report

Created: 2025-06-24 06:45

/src/binutils-gdb/libctf/ctf-hash.c
Line
Count
Source (jump to first uncovered line)
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
0
{
63
0
  ctf_helem_t *hep = (ctf_helem_t *) ptr;
64
65
0
  return htab_hash_pointer (hep->key);
66
0
}
67
68
int
69
ctf_hash_eq_integer (const void *a, const void *b)
70
0
{
71
0
  ctf_helem_t *hep_a = (ctf_helem_t *) a;
72
0
  ctf_helem_t *hep_b = (ctf_helem_t *) b;
73
74
0
  return htab_eq_pointer (hep_a->key, hep_b->key);
75
0
}
76
77
unsigned int
78
ctf_hash_string (const void *ptr)
79
0
{
80
0
  ctf_helem_t *hep = (ctf_helem_t *) ptr;
81
82
0
  return htab_hash_string (hep->key);
83
0
}
84
85
int
86
ctf_hash_eq_string (const void *a, const void *b)
87
0
{
88
0
  ctf_helem_t *hep_a = (ctf_helem_t *) a;
89
0
  ctf_helem_t *hep_b = (ctf_helem_t *) b;
90
91
0
  return !strcmp((const char *) hep_a->key, (const char *) hep_b->key);
92
0
}
93
94
/* Hash a type_key.  */
95
unsigned int
96
ctf_hash_type_key (const void *ptr)
97
0
{
98
0
  ctf_helem_t *hep = (ctf_helem_t *) ptr;
99
0
  ctf_link_type_key_t *k = (ctf_link_type_key_t *) hep->key;
100
101
0
  return htab_hash_pointer (k->cltk_fp) + 59
102
0
    * htab_hash_pointer ((void *) (uintptr_t) k->cltk_idx);
103
0
}
104
105
int
106
ctf_hash_eq_type_key (const void *a, const void *b)
107
0
{
108
0
  ctf_helem_t *hep_a = (ctf_helem_t *) a;
109
0
  ctf_helem_t *hep_b = (ctf_helem_t *) b;
110
0
  ctf_link_type_key_t *key_a = (ctf_link_type_key_t *) hep_a->key;
111
0
  ctf_link_type_key_t *key_b = (ctf_link_type_key_t *) hep_b->key;
112
113
0
  return (key_a->cltk_fp == key_b->cltk_fp)
114
0
    && (key_a->cltk_idx == key_b->cltk_idx);
115
0
}
116
117
/* Hash a type_id_key.  */
118
unsigned int
119
ctf_hash_type_id_key (const void *ptr)
120
0
{
121
0
  ctf_helem_t *hep = (ctf_helem_t *) ptr;
122
0
  ctf_type_id_key_t *k = (ctf_type_id_key_t *) hep->key;
123
124
0
  return htab_hash_pointer ((void *) (uintptr_t) k->ctii_input_num)
125
0
    + 59 * htab_hash_pointer ((void *) (uintptr_t) k->ctii_type);
126
0
}
127
128
int
129
ctf_hash_eq_type_id_key (const void *a, const void *b)
130
0
{
131
0
  ctf_helem_t *hep_a = (ctf_helem_t *) a;
132
0
  ctf_helem_t *hep_b = (ctf_helem_t *) b;
133
0
  ctf_type_id_key_t *key_a = (ctf_type_id_key_t *) hep_a->key;
134
0
  ctf_type_id_key_t *key_b = (ctf_type_id_key_t *) hep_b->key;
135
136
0
  return (key_a->ctii_input_num == key_b->ctii_input_num)
137
0
    && (key_a->ctii_type == key_b->ctii_type);
138
0
}
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
0
{
147
0
  ctf_helem_t *helem = item;
148
149
0
  if (helem->owner->key_free && helem->key)
150
0
    helem->owner->key_free (helem->key);
151
0
  if (helem->owner->value_free && helem->value)
152
0
    helem->owner->value_free (helem->value);
153
0
  free (helem);
154
0
}
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
0
{
161
0
  ctf_dynhash_t *dynhash;
162
0
  htab_del del = ctf_dynhash_item_free;
163
164
0
  if (key_free || value_free)
165
0
    dynhash = malloc (sizeof (ctf_dynhash_t));
166
0
  else
167
0
    {
168
0
      void *p = malloc (offsetof (ctf_dynhash_t, key_free));
169
0
      dynhash = p;
170
0
    }
171
0
  if (!dynhash)
172
0
    return NULL;
173
174
0
  if (key_free == NULL && value_free == NULL)
175
0
    del = free;
176
177
0
  if ((dynhash->htab = htab_create_alloc (nelems, (htab_hash) hash_fun, eq_fun,
178
0
            del, xcalloc, free)) == NULL)
179
0
    {
180
0
      free (dynhash);
181
0
      return NULL;
182
0
    }
183
184
0
  if (key_free || value_free)
185
0
    {
186
0
      dynhash->key_free = key_free;
187
0
      dynhash->value_free = value_free;
188
0
    }
189
190
0
  return dynhash;
191
0
}
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
0
{
197
  /* 7 is arbitrary and not benchmarked yet.  */
198
199
0
  return ctf_dynhash_create_sized (7, hash_fun, eq_fun, key_free, value_free);
200
0
}
201
202
static ctf_helem_t **
203
ctf_hashtab_lookup (struct htab *htab, const void *key, enum insert_option insert)
204
0
{
205
0
  ctf_helem_t tmp = { .key = (void *) key };
206
0
  return (ctf_helem_t **) htab_find_slot (htab, &tmp, insert);
207
0
}
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
0
{
214
0
  ctf_helem_t **slot;
215
216
0
  slot = ctf_hashtab_lookup (htab, key, INSERT);
217
218
0
  if (!slot)
219
0
    {
220
0
      errno = ENOMEM;
221
0
      return NULL;
222
0
    }
223
224
0
  if (!*slot)
225
0
    {
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
0
      if (key_free || value_free)
229
0
  *slot = malloc (sizeof (ctf_helem_t));
230
0
      else
231
0
  {
232
0
    void *p = malloc (offsetof (ctf_helem_t, owner));
233
0
    *slot = p;
234
0
  }
235
0
      if (!*slot)
236
0
  return NULL;
237
0
      (*slot)->key = key;
238
0
    }
239
0
  else
240
0
    {
241
0
      if (key_free)
242
0
    key_free (key);
243
0
      if (value_free)
244
0
    value_free ((*slot)->value);
245
0
    }
246
0
  (*slot)->value = value;
247
0
  return *slot;
248
0
}
249
250
int
251
ctf_dynhash_insert (ctf_dynhash_t *hp, void *key, void *value)
252
0
{
253
0
  ctf_helem_t *slot;
254
0
  ctf_hash_free_fun key_free = NULL, value_free = NULL;
255
256
0
  if (hp->htab->del_f == ctf_dynhash_item_free)
257
0
    {
258
0
      key_free = hp->key_free;
259
0
      value_free = hp->value_free;
260
0
    }
261
0
  slot = ctf_hashtab_insert (hp->htab, key, value,
262
0
           key_free, value_free);
263
264
0
  if (!slot)
265
0
    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
0
  if (key_free || value_free)
272
0
    slot->owner = hp;
273
274
0
  return 0;
275
0
}
276
277
void
278
ctf_dynhash_remove (ctf_dynhash_t *hp, const void *key)
279
0
{
280
0
  ctf_helem_t hep = { (void *) key, NULL, NULL };
281
0
  htab_remove_elt (hp->htab, &hep);
282
0
}
283
284
void
285
ctf_dynhash_empty (ctf_dynhash_t *hp)
286
0
{
287
0
  htab_empty (hp->htab);
288
0
}
289
290
size_t
291
ctf_dynhash_elements (ctf_dynhash_t *hp)
292
0
{
293
0
  return htab_elements (hp->htab);
294
0
}
295
296
void *
297
ctf_dynhash_lookup (ctf_dynhash_t *hp, const void *key)
298
0
{
299
0
  ctf_helem_t **slot;
300
301
0
  slot = ctf_hashtab_lookup (hp->htab, key, NO_INSERT);
302
303
0
  if (slot)
304
0
    return (*slot)->value;
305
306
0
  return NULL;
307
0
}
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
0
{
314
0
  ctf_helem_t **slot;
315
316
0
  slot = ctf_hashtab_lookup (hp->htab, key, NO_INSERT);
317
318
0
  if (slot)
319
0
    {
320
0
      if (orig_key)
321
0
  *orig_key = (*slot)->key;
322
0
      if (value)
323
0
  *value = (*slot)->value;
324
0
      return 1;
325
0
    }
326
0
  return 0;
327
0
}
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
0
{
338
0
  ctf_helem_t *helem = *((ctf_helem_t **) slot);
339
0
  ctf_traverse_cb_arg_t *arg = (ctf_traverse_cb_arg_t *) arg_;
340
341
0
  arg->fun (helem->key, helem->value, arg->arg);
342
0
  return 1;
343
0
}
344
345
void
346
ctf_dynhash_iter (ctf_dynhash_t *hp, ctf_hash_iter_f fun, void *arg_)
347
0
{
348
0
  ctf_traverse_cb_arg_t arg = { fun, arg_ };
349
0
  htab_traverse (hp->htab, ctf_hashtab_traverse, &arg);
350
0
}
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
0
{
362
0
  ctf_helem_t *helem = *((ctf_helem_t **) slot);
363
0
  ctf_traverse_find_cb_arg_t *arg = (ctf_traverse_find_cb_arg_t *) arg_;
364
365
0
  if (arg->fun (helem->key, helem->value, arg->arg))
366
0
    {
367
0
      arg->found_key = helem->key;
368
0
      return 0;
369
0
    }
370
0
  return 1;
371
0
}
372
373
void *
374
ctf_dynhash_iter_find (ctf_dynhash_t *hp, ctf_hash_iter_find_f fun, void *arg_)
375
0
{
376
0
  ctf_traverse_find_cb_arg_t arg = { fun, arg_, NULL };
377
0
  htab_traverse (hp->htab, ctf_hashtab_traverse_find, &arg);
378
0
  return arg.found_key;
379
0
}
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
0
{
391
0
  ctf_helem_t *helem = *((ctf_helem_t **) slot);
392
0
  ctf_traverse_remove_cb_arg_t *arg = (ctf_traverse_remove_cb_arg_t *) arg_;
393
394
0
  if (arg->fun (helem->key, helem->value, arg->arg))
395
0
    htab_clear_slot (arg->htab, slot);
396
0
  return 1;
397
0
}
398
399
void
400
ctf_dynhash_iter_remove (ctf_dynhash_t *hp, ctf_hash_iter_remove_f fun,
401
                         void *arg_)
402
0
{
403
0
  ctf_traverse_remove_cb_arg_t arg = { hp->htab, fun, arg_ };
404
0
  htab_traverse (hp->htab, ctf_hashtab_traverse_remove, &arg);
405
0
}
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
0
{
421
0
  ctf_next_t *i = *it;
422
0
  ctf_helem_t *slot;
423
424
0
  if (!i)
425
0
    {
426
0
      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
0
      if (((ssize_t) size) < 0)
432
0
  return EDOM;
433
434
0
      if ((i = ctf_next_create ()) == NULL)
435
0
  return ENOMEM;
436
437
0
      i->u.ctn_hash_slot = h->htab->entries;
438
0
      i->cu.ctn_h = h;
439
0
      i->ctn_n = 0;
440
0
      i->ctn_size = (ssize_t) size;
441
0
      i->ctn_iter_fun = (void (*) (void)) ctf_dynhash_next;
442
0
      *it = i;
443
0
    }
444
445
0
  if ((void (*) (void)) ctf_dynhash_next != i->ctn_iter_fun)
446
0
    return ECTF_NEXT_WRONGFUN;
447
448
0
  if (h != i->cu.ctn_h)
449
0
    return ECTF_NEXT_WRONGFP;
450
451
0
  if ((ssize_t) i->ctn_n == i->ctn_size)
452
0
    goto hash_end;
453
454
0
  while ((ssize_t) i->ctn_n < i->ctn_size
455
0
   && (*i->u.ctn_hash_slot == HTAB_EMPTY_ENTRY
456
0
       || *i->u.ctn_hash_slot == HTAB_DELETED_ENTRY))
457
0
    {
458
0
      i->u.ctn_hash_slot++;
459
0
      i->ctn_n++;
460
0
    }
461
462
0
  if ((ssize_t) i->ctn_n == i->ctn_size)
463
0
    goto hash_end;
464
465
0
  slot = *i->u.ctn_hash_slot;
466
467
0
  if (key)
468
0
    *key = slot->key;
469
0
  if (value)
470
0
    *value = slot->value;
471
472
0
  i->u.ctn_hash_slot++;
473
0
  i->ctn_n++;
474
475
0
  return 0;
476
477
0
 hash_end:
478
0
  ctf_next_destroy (i);
479
0
  *it = NULL;
480
0
  return ECTF_NEXT_END;
481
0
}
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
0
{
491
0
  ctf_next_t *i = *it;
492
493
0
  if ((void (*) (void)) ctf_dynhash_next != i->ctn_iter_fun)
494
0
    return ECTF_NEXT_WRONGFUN;
495
496
0
  if (!i)
497
0
    return ECTF_NEXT_END;
498
499
0
  if (i->ctn_n == 0)
500
0
    return ECTF_NEXT_END;
501
502
0
  htab_clear_slot (i->cu.ctn_h->htab, i->u.ctn_hash_slot - 1);
503
504
0
  return 0;
505
0
}
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
0
{
511
0
  return strcmp ((char *) one->hkv_key, (char *) two->hkv_key);
512
0
}
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
0
{
525
0
  ctf_next_t *i = *it;
526
527
0
  if (sort_fun == NULL)
528
0
    return ctf_dynhash_next (h, it, key, value);
529
530
0
  if (!i)
531
0
    {
532
0
      size_t els = ctf_dynhash_elements (h);
533
0
      ctf_next_t *accum_i = NULL;
534
0
      void *key, *value;
535
0
      int err;
536
0
      ctf_next_hkv_t *walk;
537
538
0
      if (((ssize_t) els) < 0)
539
0
  return EDOM;
540
541
0
      if ((i = ctf_next_create ()) == NULL)
542
0
  return ENOMEM;
543
544
0
      if ((i->u.ctn_sorted_hkv = calloc (els, sizeof (ctf_next_hkv_t))) == NULL)
545
0
  {
546
0
    ctf_next_destroy (i);
547
0
    return ENOMEM;
548
0
  }
549
0
      walk = i->u.ctn_sorted_hkv;
550
551
0
      i->cu.ctn_h = h;
552
553
0
      while ((err = ctf_dynhash_next (h, &accum_i, &key, &value)) == 0)
554
0
  {
555
0
    walk->hkv_key = key;
556
0
    walk->hkv_value = value;
557
0
    walk++;
558
0
  }
559
0
      if (err != ECTF_NEXT_END)
560
0
  {
561
0
    ctf_next_destroy (i);
562
0
    return err;
563
0
  }
564
565
0
      if (sort_fun)
566
0
    ctf_qsort_r (i->u.ctn_sorted_hkv, els, sizeof (ctf_next_hkv_t),
567
0
           (int (*) (const void *, const void *, void *)) sort_fun,
568
0
           sort_arg);
569
0
      i->ctn_n = 0;
570
0
      i->ctn_size = (ssize_t) els;
571
0
      i->ctn_iter_fun = (void (*) (void)) ctf_dynhash_next_sorted;
572
0
      *it = i;
573
0
    }
574
575
0
  if ((void (*) (void)) ctf_dynhash_next_sorted != i->ctn_iter_fun)
576
0
    return ECTF_NEXT_WRONGFUN;
577
578
0
  if (h != i->cu.ctn_h)
579
0
    return ECTF_NEXT_WRONGFP;
580
581
0
  if ((ssize_t) i->ctn_n == i->ctn_size)
582
0
    {
583
0
      ctf_next_destroy (i);
584
0
      *it = NULL;
585
0
      return ECTF_NEXT_END;
586
0
    }
587
588
0
  if (key)
589
0
    *key = i->u.ctn_sorted_hkv[i->ctn_n].hkv_key;
590
0
  if (value)
591
0
    *value = i->u.ctn_sorted_hkv[i->ctn_n].hkv_value;
592
0
  i->ctn_n++;
593
0
  return 0;
594
0
}
595
596
void
597
ctf_dynhash_destroy (ctf_dynhash_t *hp)
598
0
{
599
0
  if (hp != NULL)
600
0
    htab_delete (hp->htab);
601
0
  free (hp);
602
0
}
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
0
{
613
  /* 7 is arbitrary and untested for now.  */
614
0
  return (ctf_dynset_t *) htab_create_alloc (7, (htab_hash) hash_fun, eq_fun,
615
0
               key_free, xcalloc, free);
616
0
}
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
0
#define DYNSET_EMPTY_ENTRY_REPLACEMENT ((void *) (uintptr_t) -64)
631
0
#define DYNSET_DELETED_ENTRY_REPLACEMENT ((void *) (uintptr_t) -63)
632
633
static void *
634
key_to_internal (const void *key)
635
0
{
636
0
  if (key == HTAB_EMPTY_ENTRY)
637
0
    return DYNSET_EMPTY_ENTRY_REPLACEMENT;
638
0
  else if (key == HTAB_DELETED_ENTRY)
639
0
    return DYNSET_DELETED_ENTRY_REPLACEMENT;
640
641
0
  return (void *) key;
642
0
}
643
644
static void *
645
internal_to_key (const void *internal)
646
0
{
647
0
  if (internal == DYNSET_EMPTY_ENTRY_REPLACEMENT)
648
0
    return HTAB_EMPTY_ENTRY;
649
0
  else if (internal == DYNSET_DELETED_ENTRY_REPLACEMENT)
650
0
    return HTAB_DELETED_ENTRY;
651
0
  return (void *) internal;
652
0
}
653
654
int
655
ctf_dynset_insert (ctf_dynset_t *hp, void *key)
656
0
{
657
0
  struct htab *htab = (struct htab *) hp;
658
0
  void **slot;
659
660
0
  slot = htab_find_slot (htab, key_to_internal (key), INSERT);
661
662
0
  if (!slot)
663
0
    {
664
0
      errno = ENOMEM;
665
0
      return -errno;
666
0
    }
667
668
0
  if (*slot)
669
0
    {
670
0
      if (htab->del_f)
671
0
  (*htab->del_f) (*slot);
672
0
    }
673
674
0
  *slot = key_to_internal (key);
675
676
0
  return 0;
677
0
}
678
679
void
680
ctf_dynset_remove (ctf_dynset_t *hp, const void *key)
681
0
{
682
0
  htab_remove_elt ((struct htab *) hp, key_to_internal (key));
683
0
}
684
685
size_t
686
ctf_dynset_elements (ctf_dynset_t *hp)
687
0
{
688
0
  return htab_elements ((struct htab *) hp);
689
0
}
690
691
void
692
ctf_dynset_destroy (ctf_dynset_t *hp)
693
0
{
694
0
  if (hp != NULL)
695
0
    htab_delete ((struct htab *) hp);
696
0
}
697
698
void *
699
ctf_dynset_lookup (ctf_dynset_t *hp, const void *key)
700
0
{
701
0
  void **slot = htab_find_slot ((struct htab *) hp,
702
0
        key_to_internal (key), NO_INSERT);
703
704
0
  if (slot)
705
0
    return internal_to_key (*slot);
706
0
  return NULL;
707
0
}
708
709
/* TRUE/FALSE return.  */
710
int
711
ctf_dynset_exists (ctf_dynset_t *hp, const void *key, const void **orig_key)
712
0
{
713
0
  void **slot = htab_find_slot ((struct htab *) hp,
714
0
        key_to_internal (key), NO_INSERT);
715
716
0
  if (orig_key && slot)
717
0
    *orig_key = internal_to_key (*slot);
718
0
  return (slot != NULL);
719
0
}
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
0
{
726
0
  struct htab *htab = (struct htab *) hp;
727
0
  void **slot = htab->entries;
728
0
  void **limit = slot + htab_size (htab);
729
730
0
  while (slot < limit
731
0
   && (*slot == HTAB_EMPTY_ENTRY || *slot == HTAB_DELETED_ENTRY))
732
0
      slot++;
733
734
0
  if (slot < limit)
735
0
    return internal_to_key (*slot);
736
0
  return NULL;
737
0
}
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
0
{
745
0
  struct htab *htab = (struct htab *) hp;
746
0
  ctf_next_t *i = *it;
747
0
  void *slot;
748
749
0
  if (!i)
750
0
    {
751
0
      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
0
      if (((ssize_t) size) < 0)
758
0
  return EDOM;
759
760
0
      if ((i = ctf_next_create ()) == NULL)
761
0
  return ENOMEM;
762
763
0
      i->u.ctn_hash_slot = htab->entries;
764
0
      i->cu.ctn_s = hp;
765
0
      i->ctn_n = 0;
766
0
      i->ctn_size = (ssize_t) size;
767
0
      i->ctn_iter_fun = (void (*) (void)) ctf_dynset_next;
768
0
      *it = i;
769
0
    }
770
771
0
  if ((void (*) (void)) ctf_dynset_next != i->ctn_iter_fun)
772
0
    return ECTF_NEXT_WRONGFUN;
773
774
0
  if (hp != i->cu.ctn_s)
775
0
    return ECTF_NEXT_WRONGFP;
776
777
0
  if ((ssize_t) i->ctn_n == i->ctn_size)
778
0
    goto set_end;
779
780
0
  while ((ssize_t) i->ctn_n < i->ctn_size
781
0
   && (*i->u.ctn_hash_slot == HTAB_EMPTY_ENTRY
782
0
       || *i->u.ctn_hash_slot == HTAB_DELETED_ENTRY))
783
0
    {
784
0
      i->u.ctn_hash_slot++;
785
0
      i->ctn_n++;
786
0
    }
787
788
0
  if ((ssize_t) i->ctn_n == i->ctn_size)
789
0
    goto set_end;
790
791
0
  slot = *i->u.ctn_hash_slot;
792
793
0
  if (key)
794
0
    *key = internal_to_key (slot);
795
796
0
  i->u.ctn_hash_slot++;
797
0
  i->ctn_n++;
798
799
0
  return 0;
800
801
0
 set_end:
802
0
  ctf_next_destroy (i);
803
0
  *it = NULL;
804
0
  return ECTF_NEXT_END;
805
0
}
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
0
{
813
0
  const char *str;
814
0
  int err;
815
816
0
  if (type == 0)
817
0
    return EINVAL;
818
819
0
  if ((str = ctf_strptr_validate (fp, name)) == NULL)
820
0
    return ctf_errno (fp) * -1;
821
822
0
  if (str[0] == '\0')
823
0
    return 0;      /* Just ignore empty strings on behalf of caller.  */
824
825
0
  if ((err = ctf_dynhash_insert (hp, (char *) str,
826
0
         (void *) (ptrdiff_t) type)) == 0)
827
0
    return 0;
828
829
  /* ctf_dynhash_insert returns a negative error value: negate it for
830
     ctf_set_errno.  */
831
0
  ctf_set_errno (fp, err * -1);
832
0
  return err;
833
0
}
834
835
ctf_id_t
836
ctf_dynhash_lookup_type (ctf_dynhash_t *hp, const char *key)
837
0
{
838
0
  void *value;
839
840
0
  if (ctf_dynhash_lookup_kv (hp, key, NULL, &value))
841
0
    return (ctf_id_t) (uintptr_t) value;
842
843
0
  return 0;
844
0
}