3 * @brief Fast hashing symbol table lookup module
4 * @overview This symbol table uses a fast key lookup mechanism. Keys are
5 * strings and the value entries are arbitrary pointers. The keys are
6 * hashed into a series of buckets which then have a chain of hash
7 * entries using the standard doubly linked list classes (List/Link).
8 * The chain in in collating sequence so search time through the chain
9 * is on average (N/hashSize)/2.
10 * @remarks This module is not thread-safe. It is the callers responsibility
11 * to perform all thread synchronization.
13 /********************************* Copyright **********************************/
17 * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved.
19 * This software is distributed under commercial and open source licenses.
20 * You may use the GPL open source license described below or you may acquire
21 * a commercial license from Mbedthis Software. You agree to be fully bound
22 * by the terms of either license. Consult the LICENSE.TXT distributed with
23 * this software for full details.
25 * This software is open source; you can redistribute it and/or modify it
26 * under the terms of the GNU General Public License as published by the
27 * Free Software Foundation; either version 2 of the License, or (at your
28 * option) any later version. See the GNU General Public License for more
29 * details at: http: *www.mbedthis.com/downloads/gplLicense.html
31 * This program is distributed WITHOUT ANY WARRANTY; without even the
32 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
34 * This GPL license does NOT permit incorporating this software into
35 * proprietary programs. If you are unable to comply with the GPL, you must
36 * acquire a commercial license to use this software. Commercial licenses
37 * for this software and support services are available from Mbedthis
38 * Software at http: *www.mbedthis.com
42 /********************************** Includes **********************************/
46 /**************************** Forward Declarations ****************************/
48 static int hashIndex(const char *key, int size);
49 static MprSymbol *lookupInner(int *bucketIndex, MprSymbol **prevSp,
50 MprSymbolTable *table, const char *key);
52 /*********************************** Code *************************************/
54 * Create a new symbol table of a given size. Caller should provide a size
55 * that is a prime number for the greatest efficiency. Caller should use
56 * mprFree to free the symbol table.
59 MprSymbolTable *mprCreateSymbolTable(MprCtx ctx, int hashSize)
61 MprSymbolTable *table;
63 table = mprAllocTypeZeroed(ctx, MprSymbolTable);
68 if (hashSize < MPR_DEFAULT_HASH_SIZE) {
69 hashSize = MPR_DEFAULT_HASH_SIZE;
71 table->hashSize = hashSize;
74 table->hashSize = hashSize;
75 table->buckets = mprAllocZeroedBlock(MPR_LOC_ARGS(table),
76 sizeof(MprSymbol*) * hashSize);
78 if (table->buckets == 0) {
86 /******************************************************************************/
88 * Insert an entry into the symbol table. If the entry already exists, update
89 * its value. Order of insertion is not preserved.
92 MprSymbol *mprInsertSymbol(MprSymbolTable *table, const char *key, void *ptr)
94 MprSymbol *sp, *prevSp;
97 sp = lookupInner(&index, &prevSp, table, key);
101 * Already exists. Just update the data.
110 sp = mprAllocTypeZeroed(table, MprSymbol);
116 sp->key = mprStrdup(sp, key);
119 sp->next = table->buckets[index];
120 table->buckets[index] = sp;
126 /******************************************************************************/
128 * Remove an entry from the table
131 int mprRemoveSymbol(MprSymbolTable *table, const char *key)
133 MprSymbol *sp, *prevSp;
136 if ((sp = lookupInner(&index, &prevSp, table, key)) == 0) {
137 return MPR_ERR_NOT_FOUND;
141 prevSp->next = sp->next;
143 table->buckets[index] = sp->next;
151 /******************************************************************************/
153 * Lookup a key and return the hash entry
156 void *mprLookupSymbol(MprSymbolTable *table, const char *key)
162 sp = lookupInner(0, 0, table, key);
169 /******************************************************************************/
171 static MprSymbol *lookupInner(int *bucketIndex, MprSymbol **prevSp,
172 MprSymbolTable *table, const char *key)
174 MprSymbol *sp, *prev;
179 index = hashIndex(key, table->hashSize);
181 *bucketIndex = index;
184 sp = table->buckets[index];
188 rc = strcmp(sp->key, key);
196 mprAssert(sp != sp->next);
202 /******************************************************************************/
204 int mprGetSymbolCount(MprSymbolTable *table)
209 /******************************************************************************/
211 * Return the first entry in the table.
214 MprSymbol *mprGetFirstSymTab(MprSymbolTable *table)
221 for (i = 0; i < table->hashSize; i++) {
222 if ((sp = (MprSymbol*) table->buckets[i]) != 0) {
229 /******************************************************************************/
231 * Return the next entry in the table
234 MprSymbol *mprGetNextSymTab(MprSymbolTable *table, MprSymbol *last)
245 for (i = last->bucket + 1; i < table->hashSize; i++) {
246 if ((sp = (MprSymbol*) table->buckets[i]) != 0) {
253 /******************************************************************************/
255 * Hash the key to produce a hash index.
258 static int hashIndex(const char *key, int size)
264 sum += (sum * 33) + *key++;
270 /******************************************************************************/
277 * vim600: sw=4 ts=4 fdm=marker