1
0
mirror of https://github.com/samba-team/samba.git synced 2025-12-16 00:23:52 +03:00
Files
samba-mirror/source/lib/appweb/ejs-2.0/mpr/mprSymbol.c

280 lines
6.5 KiB
C

/*
* @file mprSym.cpp
* @brief Fast hashing symbol table lookup module
* @overview This symbol table uses a fast key lookup mechanism. Keys are
* strings and the value entries are arbitrary pointers. The keys are
* hashed into a series of buckets which then have a chain of hash
* entries using the standard doubly linked list classes (List/Link).
* The chain in in collating sequence so search time through the chain
* is on average (N/hashSize)/2.
* @remarks This module is not thread-safe. It is the callers responsibility
* to perform all thread synchronization.
*/
/********************************* Copyright **********************************/
/*
* @copy default
*
* Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved.
*
* This software is distributed under commercial and open source licenses.
* You may use the GPL open source license described below or you may acquire
* a commercial license from Mbedthis Software. You agree to be fully bound
* by the terms of either license. Consult the LICENSE.TXT distributed with
* this software for full details.
*
* This software is open source; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See the GNU General Public License for more
* details at: http: *www.mbedthis.com/downloads/gplLicense.html
*
* This program is distributed WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* This GPL license does NOT permit incorporating this software into
* proprietary programs. If you are unable to comply with the GPL, you must
* acquire a commercial license to use this software. Commercial licenses
* for this software and support services are available from Mbedthis
* Software at http: *www.mbedthis.com
*
* @end
*/
/********************************** Includes **********************************/
#include "mpr.h"
/**************************** Forward Declarations ****************************/
static int hashIndex(const char *key, int size);
static MprSymbol *lookupInner(int *bucketIndex, MprSymbol **prevSp,
MprSymbolTable *table, const char *key);
/*********************************** Code *************************************/
/*
* Create a new symbol table of a given size. Caller should provide a size
* that is a prime number for the greatest efficiency. Caller should use
* mprFree to free the symbol table.
*/
MprSymbolTable *mprCreateSymbolTable(MprCtx ctx, int hashSize)
{
MprSymbolTable *table;
table = mprAllocTypeZeroed(ctx, MprSymbolTable);
if (table == 0) {
return 0;
}
if (hashSize < MPR_DEFAULT_HASH_SIZE) {
hashSize = MPR_DEFAULT_HASH_SIZE;
}
table->hashSize = hashSize;
table->count = 0;
table->hashSize = hashSize;
table->buckets = mprAllocZeroedBlock(MPR_LOC_ARGS(table),
sizeof(MprSymbol*) * hashSize);
if (table->buckets == 0) {
mprFree(table);
return 0;
}
return table;
}
/******************************************************************************/
/*
* Insert an entry into the symbol table. If the entry already exists, update
* its value. Order of insertion is not preserved.
*/
MprSymbol *mprInsertSymbol(MprSymbolTable *table, const char *key, void *ptr)
{
MprSymbol *sp, *prevSp;
int index;
sp = lookupInner(&index, &prevSp, table, key);
if (sp != 0) {
/*
* Already exists. Just update the data.
*/
sp->data = ptr;
return sp;
}
/*
* New entry
*/
sp = mprAllocTypeZeroed(table, MprSymbol);
if (sp == 0) {
return 0;
}
sp->data = ptr;
sp->key = mprStrdup(sp, key);
sp->bucket = index;
sp->next = table->buckets[index];
table->buckets[index] = sp;
table->count++;
return sp;
}
/******************************************************************************/
/*
* Remove an entry from the table
*/
int mprRemoveSymbol(MprSymbolTable *table, const char *key)
{
MprSymbol *sp, *prevSp;
int index;
if ((sp = lookupInner(&index, &prevSp, table, key)) == 0) {
return MPR_ERR_NOT_FOUND;
}
if (prevSp) {
prevSp->next = sp->next;
} else {
table->buckets[index] = sp->next;
}
table->count--;
mprFree(sp);
return 0;
}
/******************************************************************************/
/*
* Lookup a key and return the hash entry
*/
void *mprLookupSymbol(MprSymbolTable *table, const char *key)
{
MprSymbol *sp;
mprAssert(key);
sp = lookupInner(0, 0, table, key);
if (sp == 0) {
return 0;
}
return sp->data;
}
/******************************************************************************/
static MprSymbol *lookupInner(int *bucketIndex, MprSymbol **prevSp,
MprSymbolTable *table, const char *key)
{
MprSymbol *sp, *prev;
int index, rc;
mprAssert(key);
index = hashIndex(key, table->hashSize);
if (bucketIndex) {
*bucketIndex = index;
}
sp = table->buckets[index];
prev = 0;
while (sp) {
rc = strcmp(sp->key, key);
if (rc == 0) {
if (prevSp) {
*prevSp = prev;
}
return sp;
}
prev = sp;
mprAssert(sp != sp->next);
sp = sp->next;
}
return 0;
}
/******************************************************************************/
int mprGetSymbolCount(MprSymbolTable *table)
{
return table->count;
}
/******************************************************************************/
/*
* Return the first entry in the table.
*/
MprSymbol *mprGetFirstSymTab(MprSymbolTable *table)
{
MprSymbol *sp;
int i;
mprAssert(table);
for (i = 0; i < table->hashSize; i++) {
if ((sp = (MprSymbol*) table->buckets[i]) != 0) {
return sp;
}
}
return 0;
}
/******************************************************************************/
/*
* Return the next entry in the table
*/
MprSymbol *mprGetNextSymTab(MprSymbolTable *table, MprSymbol *last)
{
MprSymbol *sp;
int i;
mprAssert(table);
if (last->next) {
return last->next;
}
for (i = last->bucket + 1; i < table->hashSize; i++) {
if ((sp = (MprSymbol*) table->buckets[i]) != 0) {
return sp;
}
}
return 0;
}
/******************************************************************************/
/*
* Hash the key to produce a hash index.
*/
static int hashIndex(const char *key, int size)
{
uint sum;
sum = 0;
while (*key) {
sum += (sum * 33) + *key++;
}
return sum % size;
}
/******************************************************************************/
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim:tw=78
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
*/