]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - libctf/ctf-hash.c
Automatic date update in version.in
[thirdparty/binutils-gdb.git] / libctf / ctf-hash.c
1 /* Interface to hashtable implementations.
2 Copyright (C) 2006-2019 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: one, ctf_dynhash_*(), is an interface to
26 a dynamically-expanding hash with unknown size that should support addition
27 of large numbers of items, and removal as well, and is used only at
28 type-insertion time; the other, ctf_dynhash_*(), is an interface to a
29 fixed-size hash from const char * -> ctf_id_t with number of elements
30 specified at creation time, that should support addition of items but need
31 not support removal. These can be implemented by the same underlying hashmap
32 if you wish. */
33
34 typedef struct ctf_helem
35 {
36 void *key; /* Either a pointer, or a coerced ctf_id_t. */
37 void *value; /* The value (possibly a coerced int). */
38 ctf_hash_free_fun key_free;
39 ctf_hash_free_fun value_free;
40 } ctf_helem_t;
41
42 struct ctf_dynhash
43 {
44 struct htab *htab;
45 ctf_hash_free_fun key_free;
46 ctf_hash_free_fun value_free;
47 };
48
49 /* Hash functions. */
50
51 unsigned int
52 ctf_hash_integer (const void *ptr)
53 {
54 ctf_helem_t *hep = (ctf_helem_t *) ptr;
55
56 return htab_hash_pointer (hep->key);
57 }
58
59 int
60 ctf_hash_eq_integer (const void *a, const void *b)
61 {
62 ctf_helem_t *hep_a = (ctf_helem_t *) a;
63 ctf_helem_t *hep_b = (ctf_helem_t *) b;
64
65 return htab_eq_pointer (hep_a->key, hep_b->key);
66 }
67
68 unsigned int
69 ctf_hash_string (const void *ptr)
70 {
71 ctf_helem_t *hep = (ctf_helem_t *) ptr;
72
73 return htab_hash_string (hep->key);
74 }
75
76 int
77 ctf_hash_eq_string (const void *a, const void *b)
78 {
79 ctf_helem_t *hep_a = (ctf_helem_t *) a;
80 ctf_helem_t *hep_b = (ctf_helem_t *) b;
81
82 return !strcmp((const char *) hep_a->key, (const char *) hep_b->key);
83 }
84
85 /* The dynhash, used for hashes whose size is not known at creation time. */
86
87 /* Free a single ctf_helem. */
88
89 static void
90 ctf_dynhash_item_free (void *item)
91 {
92 ctf_helem_t *helem = item;
93
94 if (helem->key_free && helem->key)
95 helem->key_free (helem->key);
96 if (helem->value_free && helem->value)
97 helem->value_free (helem->value);
98 free (helem);
99 }
100
101 ctf_dynhash_t *
102 ctf_dynhash_create (ctf_hash_fun hash_fun, ctf_hash_eq_fun eq_fun,
103 ctf_hash_free_fun key_free, ctf_hash_free_fun value_free)
104 {
105 ctf_dynhash_t *dynhash;
106
107 dynhash = malloc (sizeof (ctf_dynhash_t));
108 if (!dynhash)
109 return NULL;
110
111 /* 7 is arbitrary and untested for now.. */
112 if ((dynhash->htab = htab_create_alloc (7, (htab_hash) hash_fun, eq_fun,
113 ctf_dynhash_item_free, xcalloc, free)) == NULL)
114 {
115 free (dynhash);
116 return NULL;
117 }
118
119 dynhash->key_free = key_free;
120 dynhash->value_free = value_free;
121
122 return dynhash;
123 }
124
125 static ctf_helem_t **
126 ctf_hashtab_lookup (struct htab *htab, const void *key, enum insert_option insert)
127 {
128 ctf_helem_t tmp = { .key = (void *) key };
129 return (ctf_helem_t **) htab_find_slot (htab, &tmp, insert);
130 }
131
132 static ctf_helem_t *
133 ctf_hashtab_insert (struct htab *htab, void *key, void *value)
134 {
135 ctf_helem_t **slot;
136
137 slot = ctf_hashtab_lookup (htab, key, INSERT);
138
139 if (!slot)
140 {
141 errno = -ENOMEM;
142 return NULL;
143 }
144
145 if (!*slot)
146 {
147 *slot = malloc (sizeof (ctf_helem_t));
148 if (!*slot)
149 return NULL;
150 (*slot)->key = key;
151 }
152 (*slot)->value = value;
153 return *slot;
154 }
155
156 int
157 ctf_dynhash_insert (ctf_dynhash_t *hp, void *key, void *value)
158 {
159 ctf_helem_t *slot;
160
161 slot = ctf_hashtab_insert (hp->htab, key, value);
162
163 if (!slot)
164 return errno;
165
166 /* We need to keep the key_free and value_free around in each item because the
167 del function has no visiblity into the hash as a whole, only into the
168 individual items. */
169
170 slot->key_free = hp->key_free;
171 slot->value_free = hp->value_free;
172
173 return 0;
174 }
175
176 void
177 ctf_dynhash_remove (ctf_dynhash_t *hp, const void *key)
178 {
179 htab_remove_elt (hp->htab, (void *) key);
180 }
181
182 void *
183 ctf_dynhash_lookup (ctf_dynhash_t *hp, const void *key)
184 {
185 ctf_helem_t **slot;
186
187 slot = ctf_hashtab_lookup (hp->htab, key, NO_INSERT);
188
189 if (slot)
190 return (*slot)->value;
191
192 return NULL;
193 }
194
195 void
196 ctf_dynhash_destroy (ctf_dynhash_t *hp)
197 {
198 if (hp != NULL)
199 htab_delete (hp->htab);
200 free (hp);
201 }
202
203 /* ctf_hash, used for fixed-size maps from const char * -> ctf_id_t without
204 removal. This is a straight cast of a hashtab. */
205
206 ctf_hash_t *
207 ctf_hash_create (unsigned long nelems, ctf_hash_fun hash_fun,
208 ctf_hash_eq_fun eq_fun)
209 {
210 return (ctf_hash_t *) htab_create_alloc (nelems, (htab_hash) hash_fun,
211 eq_fun, free, xcalloc, free);
212 }
213
214 uint32_t
215 ctf_hash_size (const ctf_hash_t *hp)
216 {
217 return htab_elements ((struct htab *) hp);
218 }
219
220 int
221 ctf_hash_insert_type (ctf_hash_t *hp, ctf_file_t *fp, uint32_t type,
222 uint32_t name)
223 {
224 ctf_strs_t *ctsp = &fp->ctf_str[CTF_NAME_STID (name)];
225 const char *str = ctsp->cts_strs + CTF_NAME_OFFSET (name);
226
227 if (type == 0)
228 return EINVAL;
229
230 if (ctsp->cts_strs == NULL)
231 return ECTF_STRTAB;
232
233 if (ctsp->cts_len <= CTF_NAME_OFFSET (name))
234 return ECTF_BADNAME;
235
236 if (str[0] == '\0')
237 return 0; /* Just ignore empty strings on behalf of caller. */
238
239 if (ctf_hashtab_insert ((struct htab *) hp, (char *) str,
240 (void *) (ptrdiff_t) type) != NULL)
241 return 0;
242 return errno;
243 }
244
245 /* if the key is already in the hash, override the previous definition with
246 this new official definition. If the key is not present, then call
247 ctf_hash_insert_type() and hash it in. */
248 int
249 ctf_hash_define_type (ctf_hash_t *hp, ctf_file_t *fp, uint32_t type,
250 uint32_t name)
251 {
252 /* This matches the semantics of ctf_hash_insert_type() in this
253 implementation anyway. */
254
255 return ctf_hash_insert_type (hp, fp, type, name);
256 }
257
258 ctf_id_t
259 ctf_hash_lookup_type (ctf_hash_t *hp, ctf_file_t *fp __attribute__ ((__unused__)),
260 const char *key)
261 {
262 ctf_helem_t **slot;
263
264 slot = ctf_hashtab_lookup ((struct htab *) hp, key, NO_INSERT);
265
266 if (slot)
267 return (ctf_id_t) ((*slot)->value);
268
269 return 0;
270 }
271
272 void
273 ctf_hash_destroy (ctf_hash_t *hp)
274 {
275 if (hp != NULL)
276 htab_delete ((struct htab *) hp);
277 }