hash.c revision 663cdc11
1ea6ae205Smrg/* 2ea6ae205Smrg Copyright (c) 2003 by Juliusz Chroboczek 3ea6ae205Smrg 4ea6ae205Smrg Permission is hereby granted, free of charge, to any person obtaining a copy 5ea6ae205Smrg of this software and associated documentation files (the "Software"), to deal 6ea6ae205Smrg in the Software without restriction, including without limitation the rights 7ea6ae205Smrg to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8ea6ae205Smrg copies of the Software, and to permit persons to whom the Software is 9ea6ae205Smrg furnished to do so, subject to the following conditions: 10ea6ae205Smrg 11ea6ae205Smrg The above copyright notice and this permission notice shall be included in 12ea6ae205Smrg all copies or substantial portions of the Software. 13ea6ae205Smrg 14ea6ae205Smrg THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15ea6ae205Smrg IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16ea6ae205Smrg FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17ea6ae205Smrg AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18ea6ae205Smrg LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19ea6ae205Smrg OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20ea6ae205Smrg THE SOFTWARE. 21ea6ae205Smrg*/ 22ea6ae205Smrg 23ea6ae205Smrg#include <stdlib.h> 24ea6ae205Smrg#include <stdio.h> 25ea6ae205Smrg#include <string.h> 26ea6ae205Smrg#include <ctype.h> 27ea6ae205Smrg#include "hash.h" 28ea6ae205Smrg#include "list.h" 29ea6ae205Smrg 30ea6ae205Smrg#define LOG2_NUMBUCKETS 10 31ea6ae205Smrg#define NUMBUCKETS (1 << LOG2_NUMBUCKETS) 32ea6ae205Smrg 33ea6ae205Smrgstatic unsigned 34663cdc11Smrghash(const char *string) 35ea6ae205Smrg{ 36ea6ae205Smrg int i; 37ea6ae205Smrg unsigned u = 0; 38ea6ae205Smrg for(i = 0; string[i] != '\0'; i++) 39ea6ae205Smrg u = (u<<5) + (u >> (LOG2_NUMBUCKETS - 5)) + (unsigned char)string[i]; 40ea6ae205Smrg return (u & (NUMBUCKETS - 1)); 41ea6ae205Smrg} 42ea6ae205Smrg 43ea6ae205Smrgstatic void 44663cdc11Smrgstrcpy_lwr(char *dst, const char *src) 45ea6ae205Smrg{ 46ea6ae205Smrg while(1) { 47ea6ae205Smrg *dst = tolower(*src); 48ea6ae205Smrg if(*src == '\0') 49ea6ae205Smrg break; 50ea6ae205Smrg src++; 51ea6ae205Smrg dst++; 52ea6ae205Smrg } 53ea6ae205Smrg} 54ea6ae205Smrg 55ea6ae205SmrgHashTablePtr 56ea6ae205SmrgmakeHashTable(void) 57ea6ae205Smrg{ 58ea6ae205Smrg return calloc(NUMBUCKETS, sizeof(HashBucketPtr)); 59ea6ae205Smrg} 60ea6ae205Smrg 61ea6ae205Smrgvoid 62ea6ae205SmrgdestroyHashTable(HashTablePtr table) 63ea6ae205Smrg{ 64ea6ae205Smrg int i; 65ea6ae205Smrg HashBucketPtr bp; 66ea6ae205Smrg 67ea6ae205Smrg for(i = 0; i < NUMBUCKETS; i++) { 68ea6ae205Smrg while(table[i]) { 69ea6ae205Smrg bp = table[i]; 70ea6ae205Smrg table[i] = table[i]->next; 71ea6ae205Smrg free(bp->key); 72ea6ae205Smrg free(bp->value); 73ea6ae205Smrg free(bp); 74ea6ae205Smrg } 75ea6ae205Smrg } 76ea6ae205Smrg free(table); 77ea6ae205Smrg} 78ea6ae205Smrg 79ea6ae205Smrgchar * 80663cdc11SmrggetHash(HashTablePtr table, const char *key) 81ea6ae205Smrg{ 82ea6ae205Smrg int i = hash(key); 83ea6ae205Smrg HashBucketPtr bp; 84ea6ae205Smrg for(bp = table[i]; bp; bp = bp->next) { 85ea6ae205Smrg if(strcasecmp(bp->key, key) == 0) 86ea6ae205Smrg return bp->value; 87ea6ae205Smrg } 88ea6ae205Smrg return NULL; 89ea6ae205Smrg} 90ea6ae205Smrg 91ea6ae205Smrgint 92ea6ae205SmrgputHash(HashTablePtr table, char *key, char *value, int prio) 93ea6ae205Smrg{ 94ea6ae205Smrg int i = hash(key); 95ea6ae205Smrg char *keycopy = NULL, *valuecopy = NULL; 96ea6ae205Smrg HashBucketPtr bp; 97ea6ae205Smrg for(bp = table[i]; bp; bp = bp->next) { 98ea6ae205Smrg if(strcasecmp(bp->key, key) == 0) { 99ea6ae205Smrg if(prio > bp->prio) { 100ea6ae205Smrg keycopy = malloc(strlen(key) + 1); 101ea6ae205Smrg if(keycopy == NULL) goto fail; 102ea6ae205Smrg strcpy_lwr(keycopy, key); 103ea6ae205Smrg valuecopy = malloc(strlen(value) + 1); 104ea6ae205Smrg if(valuecopy == NULL) goto fail; 105ea6ae205Smrg strcpy(valuecopy, value); 106ea6ae205Smrg free(bp->key); 107ea6ae205Smrg free(bp->value); 108ea6ae205Smrg bp->key = keycopy; 109ea6ae205Smrg bp->value = valuecopy; 110ea6ae205Smrg } 111ea6ae205Smrg return 1; 112ea6ae205Smrg } 113ea6ae205Smrg } 114ea6ae205Smrg keycopy = malloc(strlen(key) + 1); 115ea6ae205Smrg if(keycopy == NULL) 116ea6ae205Smrg goto fail; 117ea6ae205Smrg strcpy_lwr(keycopy, key); 118ea6ae205Smrg valuecopy = malloc(strlen(value) + 1); 119ea6ae205Smrg if(valuecopy == NULL) 120ea6ae205Smrg goto fail; 121ea6ae205Smrg strcpy(valuecopy, value); 122ea6ae205Smrg bp = malloc(sizeof(HashBucketRec)); 123ea6ae205Smrg if(bp == NULL) 124ea6ae205Smrg goto fail; 125ea6ae205Smrg bp->key = keycopy; 126ea6ae205Smrg bp->value = valuecopy; 127ea6ae205Smrg bp->prio = prio; 128ea6ae205Smrg bp->next = table[i]; 129ea6ae205Smrg table[i] = bp; 130ea6ae205Smrg return 1; 131ea6ae205Smrg 132ea6ae205Smrg fail: 133ea6ae205Smrg if(keycopy) free(keycopy); 134ea6ae205Smrg if(valuecopy) free(valuecopy); 135ea6ae205Smrg return -1; 136ea6ae205Smrg} 137ea6ae205Smrg 138ea6ae205Smrgint 139ea6ae205SmrghashElements(HashTablePtr table) 140ea6ae205Smrg{ 141ea6ae205Smrg int i, n; 142ea6ae205Smrg HashBucketPtr bp; 143ea6ae205Smrg 144ea6ae205Smrg n = 0; 145ea6ae205Smrg for(i = 0; i < NUMBUCKETS; i++) { 146ea6ae205Smrg for(bp = table[i]; bp; bp = bp->next) { 147ea6ae205Smrg n++; 148ea6ae205Smrg } 149ea6ae205Smrg } 150ea6ae205Smrg return n; 151ea6ae205Smrg} 152ea6ae205Smrg 153ea6ae205Smrgstatic int 154ea6ae205Smrgkey_first_cmp(const void *v1, const void *v2) 155ea6ae205Smrg{ 156ea6ae205Smrg const HashBucketPtr *b1 = v1, *b2 = v2; 157ea6ae205Smrg int c1 = strcasecmp((*b1)->key, (*b2)->key); 158ea6ae205Smrg if(c1 != 0) return c1; 159ea6ae205Smrg return strcmp((*b1)->value, (*b2)->value); 160ea6ae205Smrg} 161ea6ae205Smrg 162ea6ae205Smrgstatic int 163ea6ae205Smrgvalue_first_cmp(const void *v1, const void *v2) 164ea6ae205Smrg{ 165ea6ae205Smrg const HashBucketPtr *b1 = v1, *b2 = v2; 166ea6ae205Smrg int c1 = strcmp((*b1)->value, (*b2)->value); 167ea6ae205Smrg if(c1 != 0) return c1; 168ea6ae205Smrg return strcasecmp((*b1)->key, (*b2)->key); 169ea6ae205Smrg} 170ea6ae205Smrg 171ea6ae205SmrgHashBucketPtr * 172ea6ae205SmrghashArray(HashTablePtr table, int value_first) 173ea6ae205Smrg{ 174ea6ae205Smrg int i, j, n; 175ea6ae205Smrg HashBucketPtr *dst; 176663cdc11Smrg 177ea6ae205Smrg n = hashElements(table); 178ea6ae205Smrg dst = malloc((n + 1) * sizeof(HashBucketPtr)); 179ea6ae205Smrg if(dst == NULL) 180ea6ae205Smrg return NULL; 181ea6ae205Smrg 182ea6ae205Smrg j = 0; 183ea6ae205Smrg for(i = 0; i < NUMBUCKETS; i++) { 184ea6ae205Smrg while(table[i]) { 185ea6ae205Smrg dst[j++] = table[i]; 186ea6ae205Smrg table[i] = table[i]->next; 187ea6ae205Smrg } 188ea6ae205Smrg } 189ea6ae205Smrg qsort(dst, j, sizeof(HashBucketPtr), 190ea6ae205Smrg value_first ? value_first_cmp : key_first_cmp); 191ea6ae205Smrg dst[j++] = NULL; 192ea6ae205Smrg free(table); 193ea6ae205Smrg 194ea6ae205Smrg return dst; 195ea6ae205Smrg} 196ea6ae205Smrg 197ea6ae205Smrgvoid 198ea6ae205SmrgdestroyHashArray(HashBucketPtr *array) 199ea6ae205Smrg{ 200ea6ae205Smrg int i = 0; 201ea6ae205Smrg while(array[i]) { 202ea6ae205Smrg free(array[i]->key); 203ea6ae205Smrg free(array[i]->value); 204ea6ae205Smrg free(array[i]); 205ea6ae205Smrg i++; 206ea6ae205Smrg } 207ea6ae205Smrg free(array); 208ea6ae205Smrg} 209