4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
24 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
29 #include <sys/debug.h>
31 static const ushort_t _CTF_EMPTY
[1] = { 0 };
34 ctf_hash_create(ctf_hash_t
*hp
, ulong_t nelems
)
36 if (nelems
> USHRT_MAX
)
40 * If the hash table is going to be empty, don't bother allocating any
41 * memory and make the only bucket point to a zero so lookups fail.
44 bzero(hp
, sizeof (ctf_hash_t
));
45 hp
->h_buckets
= (ushort_t
*)_CTF_EMPTY
;
50 hp
->h_nbuckets
= 211; /* use a prime number of hash buckets */
51 hp
->h_nelems
= nelems
+ 1; /* we use index zero as a sentinel */
52 hp
->h_free
= 1; /* first free element is index 1 */
54 hp
->h_buckets
= ctf_alloc(sizeof (ushort_t
) * hp
->h_nbuckets
);
55 hp
->h_chains
= ctf_alloc(sizeof (ctf_helem_t
) * hp
->h_nelems
);
57 if (hp
->h_buckets
== NULL
|| hp
->h_chains
== NULL
) {
62 bzero(hp
->h_buckets
, sizeof (ushort_t
) * hp
->h_nbuckets
);
63 bzero(hp
->h_chains
, sizeof (ctf_helem_t
) * hp
->h_nelems
);
69 ctf_hash_size(const ctf_hash_t
*hp
)
71 return (hp
->h_nelems
? hp
->h_nelems
- 1 : 0);
75 ctf_hash_compute(const char *key
, size_t len
)
78 const char *p
, *q
= key
+ len
;
81 for (p
= key
; p
< q
; p
++, n
++) {
84 if ((g
= (h
& 0xf0000000)) != 0) {
94 ctf_hash_insert(ctf_hash_t
*hp
, ctf_file_t
*fp
, ushort_t type
, uint_t name
)
96 ctf_strs_t
*ctsp
= &fp
->ctf_str
[CTF_NAME_STID(name
)];
97 const char *str
= ctsp
->cts_strs
+ CTF_NAME_OFFSET(name
);
98 ctf_helem_t
*hep
= &hp
->h_chains
[hp
->h_free
];
104 if (hp
->h_free
>= hp
->h_nelems
)
107 if (ctsp
->cts_strs
== NULL
)
108 return (ECTF_STRTAB
);
110 if (ctsp
->cts_len
<= CTF_NAME_OFFSET(name
))
111 return (ECTF_BADNAME
);
114 return (0); /* just ignore empty strings on behalf of caller */
118 h
= ctf_hash_compute(str
, strlen(str
)) % hp
->h_nbuckets
;
119 hep
->h_next
= hp
->h_buckets
[h
];
120 hp
->h_buckets
[h
] = hp
->h_free
++;
126 * Wrapper for ctf_hash_lookup/ctf_hash_insert: if the key is already in the
127 * hash, override the previous definition with this new official definition.
128 * If the key is not present, then call ctf_hash_insert() and hash it in.
131 ctf_hash_define(ctf_hash_t
*hp
, ctf_file_t
*fp
, ushort_t type
, uint_t name
)
133 const char *str
= ctf_strptr(fp
, name
);
134 ctf_helem_t
*hep
= ctf_hash_lookup(hp
, fp
, str
, strlen(str
));
137 return (ctf_hash_insert(hp
, fp
, type
, name
));
144 ctf_hash_lookup(ctf_hash_t
*hp
, ctf_file_t
*fp
, const char *key
, size_t len
)
151 ulong_t h
= ctf_hash_compute(key
, len
) % hp
->h_nbuckets
;
153 for (i
= hp
->h_buckets
[h
]; i
!= 0; i
= hep
->h_next
) {
154 hep
= &hp
->h_chains
[i
];
155 ctsp
= &fp
->ctf_str
[CTF_NAME_STID(hep
->h_name
)];
156 str
= ctsp
->cts_strs
+ CTF_NAME_OFFSET(hep
->h_name
);
158 if (strncmp(key
, str
, len
) == 0 && str
[len
] == '\0')
166 ctf_hash_destroy(ctf_hash_t
*hp
)
168 if (hp
->h_buckets
!= NULL
&& hp
->h_nbuckets
!= 1) {
169 ctf_free(hp
->h_buckets
, sizeof (ushort_t
) * hp
->h_nbuckets
);
170 hp
->h_buckets
= NULL
;
173 if (hp
->h_chains
!= NULL
) {
174 ctf_free(hp
->h_chains
, sizeof (ctf_helem_t
) * hp
->h_nelems
);