/* * hash.c -- Hash Table Library * (C)Copyright 1999 by Hiroshi Takekawa * This file is not part of any package * * Last Modified: Mon Oct 18 21:13:13 1999. * $Id: hash.c,v 1.7 1999/10/18 12:26:03 sian Exp $ * * Enfle is free software; 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. * * Enfle is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include #include #include #include "dlist.h" #include "hash.h" Hash * hash_create(int size) { int i; Hash *h; Hash_data *d; if ((h = (Hash *)malloc(sizeof(Hash))) == NULL) return NULL; if ((h->data = (Hash_data **)malloc(sizeof(Hash_data *) * size)) == NULL) { free(h); return NULL; } if ((d = (Hash_data *)calloc(size, sizeof(Hash_data))) == NULL) { free(h->data); free(h); return NULL; } if ((h->keys = dlist_create()) == NULL) { free(h->data); free(h); free(d); return NULL; } for (i = 0; i < size; i++) h->data[i] = d++; h->size = size; return h; } Dlist * hash_get_keys(Hash *h) { return h->keys; } static int calculate_hash_function(unsigned char *k, int size, int n) { int i, index = 0; for (i = 0; i < strlen(k); i++) index = (index << 3) + (index >> 28) + k[i] * n; index = (index > 0 ? index : -index) % size; return index; } static int lookup(Hash *h, unsigned char *k) { int n = 1, index; do { index = calculate_hash_function(k, h->size, n++); } while (h->data[index]->key != NULL && (strcmp(h->data[index]->key->data, k) != 0)); return index; } int hash_register(Hash *h, unsigned char *k, void *d) { int index = lookup(h, k); if (h->data[index]->key != NULL) return -1; /* already registered */ if (dlist_stradd(h->keys, k) == NULL) return 0; h->data[index]->key = dlist_gethead(h->keys); h->data[index]->datum = d; return 1; } void * hash_lookup(Hash *h, unsigned char *k) { int index = lookup(h, k); return (h->data[index]->key == NULL) ? NULL : h->data[index]->datum; } static void destroy_datum(Hash *h, int index, int f) { Hash_data *d = h->data[index]; if (d->key != NULL) { dlist_delete(h->keys, d->key, f); d->key = NULL; } if (f && d->datum != NULL) free(d->datum); } int hash_destroy_key(Hash *h, unsigned char *k, int f) { int index = lookup(h, k); if (h->data[index]->key == NULL) return 0; destroy_datum(h, index, f); return 1; } void hash_destroy(Hash *h, int f) { int i; for (i = 0; i < h->size; i++) destroy_datum(h, i, f); free(h->data[0]); free(h->data); free(h); }