hash.c revision 87aef7c3
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 2387aef7c3Smrg#include "config.h" 2487aef7c3Smrg 25ea6ae205Smrg#include <stdlib.h> 26ea6ae205Smrg#include <stdio.h> 27ea6ae205Smrg#include <string.h> 28ea6ae205Smrg#include <ctype.h> 29ea6ae205Smrg#include "hash.h" 30ea6ae205Smrg#include "list.h" 31ea6ae205Smrg 32ea6ae205Smrg#define LOG2_NUMBUCKETS 10 33ea6ae205Smrg#define NUMBUCKETS (1 << LOG2_NUMBUCKETS) 34ea6ae205Smrg 35ea6ae205Smrgstatic unsigned 36663cdc11Smrghash(const char *string) 37ea6ae205Smrg{ 38ea6ae205Smrg int i; 39ea6ae205Smrg unsigned u = 0; 40ea6ae205Smrg for(i = 0; string[i] != '\0'; i++) 41ea6ae205Smrg u = (u<<5) + (u >> (LOG2_NUMBUCKETS - 5)) + (unsigned char)string[i]; 42ea6ae205Smrg return (u & (NUMBUCKETS - 1)); 43ea6ae205Smrg} 44ea6ae205Smrg 45ea6ae205Smrgstatic void 4687aef7c3Smrgstr_tolower(char *s) 47ea6ae205Smrg{ 4887aef7c3Smrg while(*s != '\0') { 4987aef7c3Smrg *s = tolower(*s); 5087aef7c3Smrg s++; 51ea6ae205Smrg } 52ea6ae205Smrg} 53ea6ae205Smrg 54ea6ae205SmrgHashTablePtr 55ea6ae205SmrgmakeHashTable(void) 56ea6ae205Smrg{ 57ea6ae205Smrg return calloc(NUMBUCKETS, sizeof(HashBucketPtr)); 58ea6ae205Smrg} 59ea6ae205Smrg 60ea6ae205Smrgvoid 61ea6ae205SmrgdestroyHashTable(HashTablePtr table) 62ea6ae205Smrg{ 63ea6ae205Smrg int i; 64ea6ae205Smrg HashBucketPtr bp; 65ea6ae205Smrg 66ea6ae205Smrg for(i = 0; i < NUMBUCKETS; i++) { 67ea6ae205Smrg while(table[i]) { 68ea6ae205Smrg bp = table[i]; 69ea6ae205Smrg table[i] = table[i]->next; 70ea6ae205Smrg free(bp->key); 71ea6ae205Smrg free(bp->value); 72ea6ae205Smrg free(bp); 73ea6ae205Smrg } 74ea6ae205Smrg } 75ea6ae205Smrg free(table); 76ea6ae205Smrg} 77ea6ae205Smrg 78ea6ae205Smrgchar * 79663cdc11SmrggetHash(HashTablePtr table, const char *key) 80ea6ae205Smrg{ 8187aef7c3Smrg unsigned int i = hash(key); 82ea6ae205Smrg HashBucketPtr bp; 83ea6ae205Smrg for(bp = table[i]; bp; bp = bp->next) { 84ea6ae205Smrg if(strcasecmp(bp->key, key) == 0) 85ea6ae205Smrg return bp->value; 86ea6ae205Smrg } 87ea6ae205Smrg return NULL; 88ea6ae205Smrg} 89ea6ae205Smrg 90ea6ae205Smrgint 91ea6ae205SmrgputHash(HashTablePtr table, char *key, char *value, int prio) 92ea6ae205Smrg{ 9387aef7c3Smrg unsigned int i = hash(key); 94ea6ae205Smrg char *keycopy = NULL, *valuecopy = NULL; 95ea6ae205Smrg HashBucketPtr bp; 96ea6ae205Smrg for(bp = table[i]; bp; bp = bp->next) { 97ea6ae205Smrg if(strcasecmp(bp->key, key) == 0) { 98ea6ae205Smrg if(prio > bp->prio) { 9987aef7c3Smrg keycopy = strdup(key); 100ea6ae205Smrg if(keycopy == NULL) goto fail; 10187aef7c3Smrg str_tolower(keycopy); 10287aef7c3Smrg valuecopy = strdup(value); 103ea6ae205Smrg if(valuecopy == NULL) goto fail; 104ea6ae205Smrg free(bp->key); 105ea6ae205Smrg free(bp->value); 106ea6ae205Smrg bp->key = keycopy; 107ea6ae205Smrg bp->value = valuecopy; 108ea6ae205Smrg } 109ea6ae205Smrg return 1; 110ea6ae205Smrg } 111ea6ae205Smrg } 11287aef7c3Smrg keycopy = strdup(key); 113ea6ae205Smrg if(keycopy == NULL) 114ea6ae205Smrg goto fail; 11587aef7c3Smrg str_tolower(keycopy); 11687aef7c3Smrg valuecopy = strdup(value); 117ea6ae205Smrg if(valuecopy == NULL) 118ea6ae205Smrg goto fail; 119ea6ae205Smrg bp = malloc(sizeof(HashBucketRec)); 120ea6ae205Smrg if(bp == NULL) 121ea6ae205Smrg goto fail; 122ea6ae205Smrg bp->key = keycopy; 123ea6ae205Smrg bp->value = valuecopy; 124ea6ae205Smrg bp->prio = prio; 125ea6ae205Smrg bp->next = table[i]; 126ea6ae205Smrg table[i] = bp; 127ea6ae205Smrg return 1; 128ea6ae205Smrg 129ea6ae205Smrg fail: 130ea6ae205Smrg if(keycopy) free(keycopy); 131ea6ae205Smrg if(valuecopy) free(valuecopy); 132ea6ae205Smrg return -1; 133ea6ae205Smrg} 134ea6ae205Smrg 135ea6ae205Smrgint 136ea6ae205SmrghashElements(HashTablePtr table) 137ea6ae205Smrg{ 138ea6ae205Smrg int i, n; 139ea6ae205Smrg HashBucketPtr bp; 140ea6ae205Smrg 141ea6ae205Smrg n = 0; 142ea6ae205Smrg for(i = 0; i < NUMBUCKETS; i++) { 143ea6ae205Smrg for(bp = table[i]; bp; bp = bp->next) { 144ea6ae205Smrg n++; 145ea6ae205Smrg } 146ea6ae205Smrg } 147ea6ae205Smrg return n; 148ea6ae205Smrg} 149ea6ae205Smrg 150ea6ae205Smrgstatic int 151ea6ae205Smrgkey_first_cmp(const void *v1, const void *v2) 152ea6ae205Smrg{ 153ea6ae205Smrg const HashBucketPtr *b1 = v1, *b2 = v2; 154ea6ae205Smrg int c1 = strcasecmp((*b1)->key, (*b2)->key); 155ea6ae205Smrg if(c1 != 0) return c1; 156ea6ae205Smrg return strcmp((*b1)->value, (*b2)->value); 157ea6ae205Smrg} 158ea6ae205Smrg 159ea6ae205Smrgstatic int 160ea6ae205Smrgvalue_first_cmp(const void *v1, const void *v2) 161ea6ae205Smrg{ 162ea6ae205Smrg const HashBucketPtr *b1 = v1, *b2 = v2; 163ea6ae205Smrg int c1 = strcmp((*b1)->value, (*b2)->value); 164ea6ae205Smrg if(c1 != 0) return c1; 165ea6ae205Smrg return strcasecmp((*b1)->key, (*b2)->key); 166ea6ae205Smrg} 167ea6ae205Smrg 168ea6ae205SmrgHashBucketPtr * 169ea6ae205SmrghashArray(HashTablePtr table, int value_first) 170ea6ae205Smrg{ 171ea6ae205Smrg int i, j, n; 172ea6ae205Smrg HashBucketPtr *dst; 173663cdc11Smrg 174ea6ae205Smrg n = hashElements(table); 175ea6ae205Smrg dst = malloc((n + 1) * sizeof(HashBucketPtr)); 176ea6ae205Smrg if(dst == NULL) 177ea6ae205Smrg return NULL; 178ea6ae205Smrg 179ea6ae205Smrg j = 0; 180ea6ae205Smrg for(i = 0; i < NUMBUCKETS; i++) { 181ea6ae205Smrg while(table[i]) { 182ea6ae205Smrg dst[j++] = table[i]; 183ea6ae205Smrg table[i] = table[i]->next; 184ea6ae205Smrg } 185ea6ae205Smrg } 186ea6ae205Smrg qsort(dst, j, sizeof(HashBucketPtr), 187ea6ae205Smrg value_first ? value_first_cmp : key_first_cmp); 188ea6ae205Smrg dst[j++] = NULL; 189ea6ae205Smrg free(table); 190ea6ae205Smrg 191ea6ae205Smrg return dst; 192ea6ae205Smrg} 193ea6ae205Smrg 194ea6ae205Smrgvoid 195ea6ae205SmrgdestroyHashArray(HashBucketPtr *array) 196ea6ae205Smrg{ 197ea6ae205Smrg int i = 0; 198ea6ae205Smrg while(array[i]) { 199ea6ae205Smrg free(array[i]->key); 200ea6ae205Smrg free(array[i]->value); 201ea6ae205Smrg free(array[i]); 202ea6ae205Smrg i++; 203ea6ae205Smrg } 204ea6ae205Smrg free(array); 205ea6ae205Smrg} 206