Main Page | Class Hierarchy | Data Structures | Directories | File List | Data Fields | Related Pages

mm_hash.c

00001 /*-
00002  * Copyright (c) 2004-2005
00003  *      Sleepycat Software.  All rights reserved.
00004  *
00005  * http://www.apache.org/licenses/LICENSE-2.0.txt
00006  * 
00007  * authors: Thies C. Arntzen <[email protected]>
00008  *          Sterling Hughes <[email protected]>
00009  *          George Schlossnagle <[email protected]>
00010  */
00011 extern "C"
00012 {
00013 #include <stdlib.h>
00014 #include <string.h>
00015 #include "mm_hash.h"
00016 }
00017 
00018 MM_Hash *mm_hash_new(MM *mm, MM_HashDtor dtor)
00019 {
00020         MM_Hash *table;
00021 
00022         table = (MM_Hash *) mm_calloc(mm, 1, sizeof(MM_Hash));
00023         table->mm = mm;
00024         table->dtor = dtor;
00025 
00026         return table;
00027 }
00028 
00029 void mm_hash_free(MM_Hash *table) 
00030 {
00031         MM_Bucket *cur;
00032         MM_Bucket *next;
00033         int     i;
00034 
00035         for (i = 0; i < MM_HASH_SIZE; i++) {
00036                 cur = table->buckets[i];
00037                 while (cur) {
00038                         next = cur->next;
00039 
00040                         if (table->dtor) table->dtor(cur->data);
00041                         mm_free(table->mm, cur->key);
00042                         mm_free(table->mm, cur);
00043 
00044                         cur = next;
00045                 }
00046         }
00047         mm_free(table->mm, table);
00048 }
00049 
00050 static unsigned int hash_hash(const char *key, int length)
00051 {
00052     unsigned int hash = 0;
00053 
00054     while (--length)
00055         hash = hash * 65599 + *key++;
00056 
00057     return hash;
00058 }
00059 
00060 void *mm_hash_find(MM_Hash *table, const void *key, int length)
00061 {
00062         MM_Bucket       *b;
00063         unsigned int  hash = hash_hash((const char *)key, length) % MM_HASH_SIZE;
00064 
00065     for (b = table->buckets[ hash ]; b; b = b->next) {
00066                 if (hash != b->hash) continue;
00067                 if (length != b->length) continue;
00068                 if (memcmp(key, b->key, length)) continue;
00069 
00070                 return b->data;
00071     }
00072 
00073     return NULL;
00074 }
00075 
00076 void mm_hash_update(MM_Hash *table, char *key, int length, void *data)
00077 {
00078         MM_Bucket *b, p;
00079         unsigned int  hash;
00080         
00081         hash = hash_hash(key, length) % MM_HASH_SIZE;
00082 
00083         for(b = table->buckets[ hash ]; b; b = b->next) {
00084                 if (hash != b->hash) continue;
00085                 if (length != b->length) continue;
00086                 if (memcmp(key, b->key, length)) continue;
00087                 if (table->dtor) table->dtor(b->data);
00088                 b->data = data;
00089         }
00090         if(!b) {
00091         b = (MM_Bucket *) mm_malloc(table->mm, sizeof(MM_Bucket));
00092         b->key = (char *) mm_malloc(table->mm, length + 1);
00093         memcpy(b->key, key, length);
00094         b->key[length] = 0;
00095         b->length = length;
00096         b->hash = hash;
00097         b->data = data;
00098                 b->next = table->buckets[ hash ];
00099                 table->buckets[ hash ] = b;
00100         }       
00101         table->nElements++;
00102 }
00103 
00104 void mm_hash_delete(MM_Hash *table, char *key, int length)
00105 {
00106         MM_Bucket       *b; 
00107         MM_Bucket       *prev = NULL;
00108         unsigned int  hash;
00109 
00110         hash = hash_hash(key, length) % MM_HASH_SIZE;
00111     for (b = table->buckets[ hash ]; b; b = b->next) {
00112                 if (hash != b->hash || length != b->length || memcmp(key, b->key, length)) {
00113                         prev = b;
00114                         continue;
00115                 }
00116 
00117                 /* unlink */
00118                 if (prev) {
00119                         prev->next = b->next;
00120                 } else {
00121                         table->buckets[hash] = b->next;
00122                 }
00123                 
00124                 if (table->dtor) table->dtor(b->data);
00125                 mm_free(table->mm, b->key);
00126                 mm_free(table->mm, b);
00127 
00128                 break;
00129     }
00130 }
00131 
00132 /*
00133 Local variables:
00134 tab-width: 4
00135 c-basic-offset: 4
00136 End:
00137 vim600: noet sw=4 ts=4 fdm=marker
00138 vim<600: noet sw=4 ts=4
00139 */

Generated on Sun Dec 25 12:14:41 2005 for Berkeley DB 4.4.16 by  doxygen 1.4.2