Path: blob/main/cddl/contrib/opensolaris/common/ctf/ctf_hash.c
39507 views
/*1* CDDL HEADER START2*3* The contents of this file are subject to the terms of the4* Common Development and Distribution License, Version 1.0 only5* (the "License"). You may not use this file except in compliance6* with the License.7*8* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE9* or http://www.opensolaris.org/os/licensing.10* See the License for the specific language governing permissions11* and limitations under the License.12*13* When distributing Covered Code, include this CDDL HEADER in each14* file and include the License file at usr/src/OPENSOLARIS.LICENSE.15* If applicable, add the following below this CDDL HEADER, with the16* fields enclosed by brackets "[]" replaced with your own identifying17* information: Portions Copyright [yyyy] [name of copyright owner]18*19* CDDL HEADER END20*/2122/*23* Copyright 2006 Sun Microsystems, Inc. All rights reserved.24* Use is subject to license terms.25*/2627#pragma ident "%Z%%M% %I% %E% SMI"2829#include <ctf_impl.h>3031static const uint_t _CTF_EMPTY[1] = { 0 };3233int34ctf_hash_create(ctf_hash_t *hp, ulong_t nelems)35{36if (nelems > USHRT_MAX)37return (EOVERFLOW);3839/*40* If the hash table is going to be empty, don't bother allocating any41* memory and make the only bucket point to a zero so lookups fail.42*/43if (nelems == 0) {44bzero(hp, sizeof (ctf_hash_t));45hp->h_buckets = (uint_t *)_CTF_EMPTY;46hp->h_nbuckets = 1;47return (0);48}4950hp->h_nbuckets = 211; /* use a prime number of hash buckets */51hp->h_nelems = nelems + 1; /* we use index zero as a sentinel */52hp->h_free = 1; /* first free element is index 1 */5354hp->h_buckets = ctf_alloc(sizeof (uint_t) * hp->h_nbuckets);55hp->h_chains = ctf_alloc(sizeof (ctf_helem_t) * hp->h_nelems);5657if (hp->h_buckets == NULL || hp->h_chains == NULL) {58ctf_hash_destroy(hp);59return (EAGAIN);60}6162bzero(hp->h_buckets, sizeof (uint_t) * hp->h_nbuckets);63bzero(hp->h_chains, sizeof (ctf_helem_t) * hp->h_nelems);6465return (0);66}6768uint_t69ctf_hash_size(const ctf_hash_t *hp)70{71return (hp->h_nelems ? hp->h_nelems - 1 : 0);72}7374static ulong_t75ctf_hash_compute(const char *key, size_t len)76{77ulong_t g, h = 0;78const char *p, *q = key + len;79size_t n = 0;8081for (p = key; p < q; p++, n++) {82h = (h << 4) + *p;8384if ((g = (h & 0xf0000000)) != 0) {85h ^= (g >> 24);86h ^= g;87}88}8990return (h);91}9293int94ctf_hash_insert(ctf_hash_t *hp, ctf_file_t *fp, uint_t type, uint_t name)95{96ctf_strs_t *ctsp = &fp->ctf_str[CTF_NAME_STID(name)];97const char *str = ctsp->cts_strs + CTF_NAME_OFFSET(name);98ctf_helem_t *hep = &hp->h_chains[hp->h_free];99ulong_t h;100101if (type == 0)102return (EINVAL);103104if (hp->h_free >= hp->h_nelems)105return (EOVERFLOW);106107if (ctsp->cts_strs == NULL)108return (ECTF_STRTAB);109110if (ctsp->cts_len <= CTF_NAME_OFFSET(name))111return (ECTF_BADNAME);112113if (str[0] == '\0')114return (0); /* just ignore empty strings on behalf of caller */115116hep->h_name = name;117hep->h_type = type;118h = ctf_hash_compute(str, strlen(str)) % hp->h_nbuckets;119hep->h_next = hp->h_buckets[h];120hp->h_buckets[h] = hp->h_free++;121122return (0);123}124125/*126* Wrapper for ctf_hash_lookup/ctf_hash_insert: if the key is already in the127* 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.129*/130int131ctf_hash_define(ctf_hash_t *hp, ctf_file_t *fp, uint_t type, uint_t name)132{133const char *str = ctf_strptr(fp, name);134ctf_helem_t *hep = ctf_hash_lookup(hp, fp, str, strlen(str));135136if (hep == NULL)137return (ctf_hash_insert(hp, fp, type, name));138139hep->h_type = type;140return (0);141}142143ctf_helem_t *144ctf_hash_lookup(ctf_hash_t *hp, ctf_file_t *fp, const char *key, size_t len)145{146ctf_helem_t *hep;147ctf_strs_t *ctsp;148const char *str;149uint_t i;150151ulong_t h = ctf_hash_compute(key, len) % hp->h_nbuckets;152153for (i = hp->h_buckets[h]; i != 0; i = hep->h_next) {154hep = &hp->h_chains[i];155ctsp = &fp->ctf_str[CTF_NAME_STID(hep->h_name)];156str = ctsp->cts_strs + CTF_NAME_OFFSET(hep->h_name);157158if (strncmp(key, str, len) == 0 && str[len] == '\0')159return (hep);160}161162return (NULL);163}164165void166ctf_hash_destroy(ctf_hash_t *hp)167{168if (hp->h_buckets != NULL && hp->h_nbuckets != 1) {169ctf_free(hp->h_buckets, sizeof (uint_t) * hp->h_nbuckets);170hp->h_buckets = NULL;171}172173if (hp->h_chains != NULL) {174ctf_free(hp->h_chains, sizeof (ctf_helem_t) * hp->h_nelems);175hp->h_chains = NULL;176}177}178179180