1178481Sjb/* 2178481Sjb * CDDL HEADER START 3178481Sjb * 4178481Sjb * The contents of this file are subject to the terms of the 5178481Sjb * Common Development and Distribution License, Version 1.0 only 6178481Sjb * (the "License"). You may not use this file except in compliance 7178481Sjb * with the License. 8178481Sjb * 9178481Sjb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10178481Sjb * or http://www.opensolaris.org/os/licensing. 11178481Sjb * See the License for the specific language governing permissions 12178481Sjb * and limitations under the License. 13178481Sjb * 14178481Sjb * When distributing Covered Code, include this CDDL HEADER in each 15178481Sjb * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16178481Sjb * If applicable, add the following below this CDDL HEADER, with the 17178481Sjb * fields enclosed by brackets "[]" replaced with your own identifying 18178481Sjb * information: Portions Copyright [yyyy] [name of copyright owner] 19178481Sjb * 20178481Sjb * CDDL HEADER END 21178481Sjb */ 22178481Sjb/* 23178481Sjb * Copyright 2001-2003 Sun Microsystems, Inc. All rights reserved. 24178481Sjb * Use is subject to license terms. 25178481Sjb */ 26178481Sjb 27178481Sjb#pragma ident "%Z%%M% %I% %E% SMI" 28178481Sjb 29178481Sjb/* 30178481Sjb * Create, manage, and destroy association lists. alists are arrays with 31178481Sjb * arbitrary index types, and are also commonly known as associative arrays. 32178481Sjb */ 33178481Sjb 34178481Sjb#include <stdio.h> 35178481Sjb#include <stdlib.h> 36178481Sjb 37178481Sjb#include "alist.h" 38178481Sjb#include "memory.h" 39178481Sjb#include "hash.h" 40178481Sjb 41178481Sjb#define ALIST_HASH_SIZE 997 42178481Sjb 43178481Sjbstruct alist { 44178481Sjb hash_t *al_elements; 45178481Sjb void (*al_namefree)(void *); 46178481Sjb void (*al_valfree)(void *); 47178481Sjb}; 48178481Sjb 49178481Sjbtypedef struct alist_el { 50178481Sjb void *ale_name; 51178481Sjb void *ale_value; 52178481Sjb} alist_el_t; 53178481Sjb 54178481Sjbstatic int 55178546Sjbalist_hash(int nbuckets, void *arg) 56178481Sjb{ 57178546Sjb alist_el_t *el = arg; 58178481Sjb uintptr_t num = (uintptr_t)el->ale_name; 59178481Sjb 60178481Sjb return (num % nbuckets); 61178481Sjb} 62178481Sjb 63178481Sjbstatic int 64178546Sjbalist_cmp(void *arg1, void *arg2) 65178481Sjb{ 66178546Sjb alist_el_t *el1 = arg1; 67178546Sjb alist_el_t *el2 = arg2; 68178481Sjb return ((uintptr_t)el1->ale_name != (uintptr_t)el2->ale_name); 69178481Sjb} 70178481Sjb 71178481Sjbalist_t * 72178481Sjbalist_xnew(int nbuckets, void (*namefree)(void *), 73178481Sjb void (*valfree)(void *), int (*hashfn)(int, void *), 74178481Sjb int (*cmpfn)(void *, void *)) 75178481Sjb{ 76178481Sjb alist_t *alist; 77178481Sjb 78178481Sjb alist = xcalloc(sizeof (alist_t)); 79178481Sjb alist->al_elements = hash_new(nbuckets, hashfn, cmpfn); 80178481Sjb alist->al_namefree = namefree; 81178481Sjb alist->al_valfree = valfree; 82178481Sjb 83178481Sjb return (alist); 84178481Sjb} 85178481Sjb 86178481Sjbalist_t * 87178481Sjbalist_new(void (*namefree)(void *), void (*valfree)(void *)) 88178481Sjb{ 89178481Sjb return (alist_xnew(ALIST_HASH_SIZE, namefree, valfree, 90178546Sjb alist_hash, alist_cmp)); 91178481Sjb} 92178481Sjb 93178481Sjbstatic void 94178546Sjbalist_free_cb(void *arg1, void *arg2) 95178481Sjb{ 96178546Sjb alist_el_t *el = arg1; 97178546Sjb alist_t *alist = arg2; 98178481Sjb if (alist->al_namefree) 99178481Sjb alist->al_namefree(el->ale_name); 100178481Sjb if (alist->al_valfree) 101178481Sjb alist->al_valfree(el->ale_name); 102178481Sjb free(el); 103178481Sjb} 104178481Sjb 105178481Sjbvoid 106178481Sjbalist_free(alist_t *alist) 107178481Sjb{ 108178546Sjb hash_free(alist->al_elements, alist_free_cb, alist); 109178481Sjb free(alist); 110178481Sjb} 111178481Sjb 112178481Sjbvoid 113178481Sjbalist_add(alist_t *alist, void *name, void *value) 114178481Sjb{ 115178481Sjb alist_el_t *el; 116178481Sjb 117178481Sjb el = xmalloc(sizeof (alist_el_t)); 118178481Sjb el->ale_name = name; 119178481Sjb el->ale_value = value; 120178481Sjb hash_add(alist->al_elements, el); 121178481Sjb} 122178481Sjb 123178481Sjbint 124178481Sjbalist_find(alist_t *alist, void *name, void **value) 125178481Sjb{ 126178546Sjb alist_el_t template, *retx; 127178546Sjb void *ret; 128178481Sjb 129178481Sjb template.ale_name = name; 130178546Sjb if (!hash_find(alist->al_elements, &template, &ret)) 131178481Sjb return (0); 132178481Sjb 133178546Sjb if (value) { 134178546Sjb retx = ret; 135178546Sjb *value = retx->ale_value; 136178546Sjb } 137178481Sjb 138178481Sjb return (1); 139178481Sjb} 140178481Sjb 141178481Sjbtypedef struct alist_iter_data { 142178481Sjb int (*aid_func)(void *, void *, void *); 143178481Sjb void *aid_priv; 144178481Sjb} alist_iter_data_t; 145178481Sjb 146178481Sjbstatic int 147178546Sjbalist_iter_cb(void *arg1, void *arg2) 148178481Sjb{ 149178546Sjb alist_el_t *el = arg1; 150178546Sjb alist_iter_data_t *aid = arg2; 151178481Sjb return (aid->aid_func(el->ale_name, el->ale_value, aid->aid_priv)); 152178481Sjb} 153178481Sjb 154178481Sjbint 155178481Sjbalist_iter(alist_t *alist, int (*func)(void *, void *, void *), void *private) 156178481Sjb{ 157178481Sjb alist_iter_data_t aid; 158178481Sjb 159178481Sjb aid.aid_func = func; 160178481Sjb aid.aid_priv = private; 161178481Sjb 162178546Sjb return (hash_iter(alist->al_elements, alist_iter_cb, &aid)); 163178481Sjb} 164178481Sjb 165178481Sjb/* 166178481Sjb * Debugging support. Used to print the contents of an alist. 167178481Sjb */ 168178481Sjb 169178481Sjbvoid 170178481Sjbalist_stats(alist_t *alist, int verbose) 171178481Sjb{ 172178481Sjb printf("Alist statistics\n"); 173178481Sjb hash_stats(alist->al_elements, verbose); 174178481Sjb} 175178481Sjb 176178481Sjbstatic int alist_def_print_cb_key_int = 1; 177178481Sjbstatic int alist_def_print_cb_value_int = 1; 178178481Sjb 179178481Sjbstatic int 180178481Sjbalist_def_print_cb(void *key, void *value) 181178481Sjb{ 182178481Sjb printf("Key: "); 183178481Sjb if (alist_def_print_cb_key_int == 1) 184178546Sjb printf("%5lu ", (ulong_t)key); 185178481Sjb else 186178481Sjb printf("%s\n", (char *)key); 187178481Sjb 188178481Sjb printf("Value: "); 189178481Sjb if (alist_def_print_cb_value_int == 1) 190178546Sjb printf("%5lu\n", (ulong_t)value); 191178481Sjb else 192178481Sjb printf("%s\n", (char *)key); 193178481Sjb 194178481Sjb return (1); 195178481Sjb} 196178481Sjb 197178481Sjbstatic int 198178481Sjbalist_dump_cb(void *node, void *private) 199178481Sjb{ 200178546Sjb int (*printer)(void *, void *) = private; 201178481Sjb alist_el_t *el = node; 202178481Sjb 203178481Sjb printer(el->ale_name, el->ale_value); 204178481Sjb 205178481Sjb return (1); 206178481Sjb} 207178481Sjb 208178481Sjbint 209178481Sjbalist_dump(alist_t *alist, int (*printer)(void *, void *)) 210178481Sjb{ 211178481Sjb if (!printer) 212178481Sjb printer = alist_def_print_cb; 213178481Sjb 214178481Sjb return (hash_iter(alist->al_elements, alist_dump_cb, (void *)printer)); 215178481Sjb} 216