File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / lib / hash.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:26:12 2012 UTC (12 years, 4 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_22p0, v0_99_22, v0_99_21, v0_99_20_1, v0_99_20, HEAD
quagga

    1: /* Hash routine.
    2:  * Copyright (C) 1998 Kunihiro Ishiguro
    3:  *
    4:  * This file is part of GNU Zebra.
    5:  *
    6:  * GNU Zebra is free software; you can redistribute it and/or modify
    7:  * it under the terms of the GNU General Public License as published
    8:  * by the Free Software Foundation; either version 2, or (at your
    9:  * option) any later version.
   10:  *
   11:  * GNU Zebra is distributed in the hope that it will be useful, but
   12:  * WITHOUT ANY WARRANTY; without even the implied warranty of
   13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14:  * General Public License for more details.
   15:  *
   16:  * You should have received a copy of the GNU General Public License
   17:  * along with GNU Zebra; see the file COPYING.  If not, write to the
   18:  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   19:  * Boston, MA 02111-1307, USA.
   20:  */
   21: 
   22: #include <zebra.h>
   23: 
   24: #include "hash.h"
   25: #include "memory.h"
   26: 
   27: /* Allocate a new hash.  */
   28: struct hash *
   29: hash_create_size (unsigned int size, unsigned int (*hash_key) (void *),
   30:                                      int (*hash_cmp) (const void *, const void *))
   31: {
   32:   struct hash *hash;
   33: 
   34:   hash = XMALLOC (MTYPE_HASH, sizeof (struct hash));
   35:   hash->index = XCALLOC (MTYPE_HASH_INDEX,
   36: 			 sizeof (struct hash_backet *) * size);
   37:   hash->size = size;
   38:   hash->hash_key = hash_key;
   39:   hash->hash_cmp = hash_cmp;
   40:   hash->count = 0;
   41: 
   42:   return hash;
   43: }
   44: 
   45: /* Allocate a new hash with default hash size.  */
   46: struct hash *
   47: hash_create (unsigned int (*hash_key) (void *), 
   48:              int (*hash_cmp) (const void *, const void *))
   49: {
   50:   return hash_create_size (HASHTABSIZE, hash_key, hash_cmp);
   51: }
   52: 
   53: /* Utility function for hash_get().  When this function is specified
   54:    as alloc_func, return arugment as it is.  This function is used for
   55:    intern already allocated value.  */
   56: void *
   57: hash_alloc_intern (void *arg)
   58: {
   59:   return arg;
   60: }
   61: 
   62: /* Lookup and return hash backet in hash.  If there is no
   63:    corresponding hash backet and alloc_func is specified, create new
   64:    hash backet.  */
   65: void *
   66: hash_get (struct hash *hash, void *data, void * (*alloc_func) (void *))
   67: {
   68:   unsigned int key;
   69:   unsigned int index;
   70:   void *newdata;
   71:   struct hash_backet *backet;
   72: 
   73:   key = (*hash->hash_key) (data);
   74:   index = key % hash->size;
   75: 
   76:   for (backet = hash->index[index]; backet != NULL; backet = backet->next) 
   77:     if (backet->key == key && (*hash->hash_cmp) (backet->data, data))
   78:       return backet->data;
   79: 
   80:   if (alloc_func)
   81:     {
   82:       newdata = (*alloc_func) (data);
   83:       if (newdata == NULL)
   84: 	return NULL;
   85: 
   86:       backet = XMALLOC (MTYPE_HASH_BACKET, sizeof (struct hash_backet));
   87:       backet->data = newdata;
   88:       backet->key = key;
   89:       backet->next = hash->index[index];
   90:       hash->index[index] = backet;
   91:       hash->count++;
   92:       return backet->data;
   93:     }
   94:   return NULL;
   95: }
   96: 
   97: /* Hash lookup.  */
   98: void *
   99: hash_lookup (struct hash *hash, void *data)
  100: {
  101:   return hash_get (hash, data, NULL);
  102: }
  103: 
  104: /* Simple Bernstein hash which is simple and fast for common case */
  105: unsigned int string_hash_make (const char *str)
  106: {
  107:   unsigned int hash = 0;
  108: 
  109:   while (*str)
  110:     hash = (hash * 33) ^ (unsigned int) *str++;
  111: 
  112:   return hash;
  113: }
  114: 
  115: /* This function release registered value from specified hash.  When
  116:    release is successfully finished, return the data pointer in the
  117:    hash backet.  */
  118: void *
  119: hash_release (struct hash *hash, void *data)
  120: {
  121:   void *ret;
  122:   unsigned int key;
  123:   unsigned int index;
  124:   struct hash_backet *backet;
  125:   struct hash_backet *pp;
  126: 
  127:   key = (*hash->hash_key) (data);
  128:   index = key % hash->size;
  129: 
  130:   for (backet = pp = hash->index[index]; backet; backet = backet->next)
  131:     {
  132:       if (backet->key == key && (*hash->hash_cmp) (backet->data, data)) 
  133: 	{
  134: 	  if (backet == pp) 
  135: 	    hash->index[index] = backet->next;
  136: 	  else 
  137: 	    pp->next = backet->next;
  138: 
  139: 	  ret = backet->data;
  140: 	  XFREE (MTYPE_HASH_BACKET, backet);
  141: 	  hash->count--;
  142: 	  return ret;
  143: 	}
  144:       pp = backet;
  145:     }
  146:   return NULL;
  147: }
  148: 
  149: /* Iterator function for hash.  */
  150: void
  151: hash_iterate (struct hash *hash, 
  152: 	      void (*func) (struct hash_backet *, void *), void *arg)
  153: {
  154:   unsigned int i;
  155:   struct hash_backet *hb;
  156:   struct hash_backet *hbnext;
  157: 
  158:   for (i = 0; i < hash->size; i++)
  159:     for (hb = hash->index[i]; hb; hb = hbnext)
  160:       {
  161: 	/* get pointer to next hash backet here, in case (*func)
  162: 	 * decides to delete hb by calling hash_release
  163: 	 */
  164: 	hbnext = hb->next;
  165: 	(*func) (hb, arg);
  166:       }
  167: }
  168: 
  169: /* Clean up hash.  */
  170: void
  171: hash_clean (struct hash *hash, void (*free_func) (void *))
  172: {
  173:   unsigned int i;
  174:   struct hash_backet *hb;
  175:   struct hash_backet *next;
  176: 
  177:   for (i = 0; i < hash->size; i++)
  178:     {
  179:       for (hb = hash->index[i]; hb; hb = next)
  180: 	{
  181: 	  next = hb->next;
  182: 	      
  183: 	  if (free_func)
  184: 	    (*free_func) (hb->data);
  185: 
  186: 	  XFREE (MTYPE_HASH_BACKET, hb);
  187: 	  hash->count--;
  188: 	}
  189:       hash->index[i] = NULL;
  190:     }
  191: }
  192: 
  193: /* Free hash memory.  You may call hash_clean before call this
  194:    function.  */
  195: void
  196: hash_free (struct hash *hash)
  197: {
  198:   XFREE (MTYPE_HASH_INDEX, hash->index);
  199:   XFREE (MTYPE_HASH, hash);
  200: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>