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.
28 #pragma ident "%Z%%M% %I% %E% SMI"
32 static const ushort_t _CTF_EMPTY
[1] = { 0 };
35 ctf_hash_create(ctf_hash_t
*hp
, ulong_t nelems
)
37 if (nelems
> USHRT_MAX
)
41 * If the hash table is going to be empty, don't bother allocating any
42 * memory and make the only bucket point to a zero so lookups fail.
45 bzero(hp
, sizeof (ctf_hash_t
));
46 hp
->h_buckets
= (ushort_t
*)_CTF_EMPTY
;
51 hp
->h_nbuckets
= 211; /* use a prime number of hash buckets */
52 hp
->h_nelems
= nelems
+ 1; /* we use index zero as a sentinel */
53 hp
->h_free
= 1; /* first free element is index 1 */
55 hp
->h_buckets
= ctf_alloc(sizeof (ushort_t
) * hp
->h_nbuckets
);
56 hp
->h_chains
= ctf_alloc(sizeof (ctf_helem_t
) * hp
->h_nelems
);
58 if (hp
->h_buckets
== NULL
|| hp
->h_chains
== NULL
) {
63 bzero(hp
->h_buckets
, sizeof (ushort_t
) * hp
->h_nbuckets
);
64 bzero(hp
->h_chains
, sizeof (ctf_helem_t
) * hp
->h_nelems
);
70 ctf_hash_size(const ctf_hash_t
*hp
)
72 return (hp
->h_nelems
? hp
->h_nelems
- 1 : 0);
76 ctf_hash_compute(const char *key
, size_t len
)
79 const char *p
, *q
= key
+ len
;
82 for (p
= key
; p
< q
; p
++, n
++) {
85 if ((g
= (h
& 0xf0000000)) != 0) {
95 ctf_hash_insert(ctf_hash_t
*hp
, ctf_file_t
*fp
, ushort_t type
, uint_t name
)
97 ctf_strs_t
*ctsp
= &fp
->ctf_str
[CTF_NAME_STID(name
)];
98 const char *str
= ctsp
->cts_strs
+ CTF_NAME_OFFSET(name
);
99 ctf_helem_t
*hep
= &hp
->h_chains
[hp
->h_free
];
105 if (hp
->h_free
>= hp
->h_nelems
)
108 if (ctsp
->cts_strs
== NULL
)
109 return (ECTF_STRTAB
);
111 if (ctsp
->cts_len
<= CTF_NAME_OFFSET(name
))
112 return (ECTF_BADNAME
);
115 return (0); /* just ignore empty strings on behalf of caller */
119 h
= ctf_hash_compute(str
, strlen(str
)) % hp
->h_nbuckets
;
120 hep
->h_next
= hp
->h_buckets
[h
];
121 hp
->h_buckets
[h
] = hp
->h_free
++;
127 * Wrapper for ctf_hash_lookup/ctf_hash_insert: if the key is already in the
128 * hash, override the previous definition with this new official definition.
129 * If the key is not present, then call ctf_hash_insert() and hash it in.
132 ctf_hash_define(ctf_hash_t
*hp
, ctf_file_t
*fp
, ushort_t type
, uint_t name
)
134 const char *str
= ctf_strptr(fp
, name
);
135 ctf_helem_t
*hep
= ctf_hash_lookup(hp
, fp
, str
, strlen(str
));
138 return (ctf_hash_insert(hp
, fp
, type
, name
));
145 ctf_hash_lookup(ctf_hash_t
*hp
, ctf_file_t
*fp
, const char *key
, size_t len
)
152 ulong_t h
= ctf_hash_compute(key
, len
) % hp
->h_nbuckets
;
154 for (i
= hp
->h_buckets
[h
]; i
!= 0; i
= hep
->h_next
) {
155 hep
= &hp
->h_chains
[i
];
156 ctsp
= &fp
->ctf_str
[CTF_NAME_STID(hep
->h_name
)];
157 str
= ctsp
->cts_strs
+ CTF_NAME_OFFSET(hep
->h_name
);
159 if (strncmp(key
, str
, len
) == 0 && str
[len
] == '\0')
167 ctf_hash_destroy(ctf_hash_t
*hp
)
169 if (hp
->h_buckets
!= NULL
&& hp
->h_nbuckets
!= 1) {
170 ctf_free(hp
->h_buckets
, sizeof (ushort_t
) * hp
->h_nbuckets
);
171 hp
->h_buckets
= NULL
;
174 if (hp
->h_chains
!= NULL
) {
175 ctf_free(hp
->h_chains
, sizeof (ctf_helem_t
) * hp
->h_nelems
);