LCOV - code coverage report
Current view: top level - lib - hash.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 69 102 67.6 %
Date: 2015-11-19 Functions: 9 11 81.8 %

          Line data    Source code
       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          89 : 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          89 :   assert ((size & (size-1)) == 0);
      35          89 :   hash = XMALLOC (MTYPE_HASH, sizeof (struct hash));
      36          89 :   hash->index = XCALLOC (MTYPE_HASH_INDEX,
      37             :                          sizeof (struct hash_backet *) * size);
      38          89 :   hash->size = size;
      39          89 :   hash->no_expand = 0;
      40          89 :   hash->hash_key = hash_key;
      41          89 :   hash->hash_cmp = hash_cmp;
      42          89 :   hash->count = 0;
      43             : 
      44          89 :   return hash;
      45             : }
      46             : 
      47             : /* Allocate a new hash with default hash size.  */
      48             : struct hash *
      49          88 : hash_create (unsigned int (*hash_key) (void *), 
      50             :              int (*hash_cmp) (const void *, const void *))
      51             : {
      52          88 :   return hash_create_size (HASH_INITIAL_SIZE, hash_key, hash_cmp);
      53             : }
      54             : 
      55             : /* Utility function for hash_get().  When this function is specified
      56             :    as alloc_func, return arugment as it is.  This function is used for
      57             :    intern already allocated value.  */
      58             : void *
      59           5 : hash_alloc_intern (void *arg)
      60             : {
      61           5 :   return arg;
      62             : }
      63             : 
      64             : /* Expand hash if the chain length exceeds the threshold. */
      65           0 : static void hash_expand (struct hash *hash)
      66             : {
      67             :   unsigned int i, new_size, losers;
      68             :   struct hash_backet *hb, *hbnext, **new_index;
      69             : 
      70           0 :   new_size = hash->size * 2;
      71           0 :   new_index = XCALLOC(MTYPE_HASH_INDEX, sizeof(struct hash_backet *) * new_size);
      72           0 :   if (new_index == NULL)
      73           0 :     return;
      74             : 
      75           0 :   for (i = 0; i < hash->size; i++)
      76           0 :     for (hb = hash->index[i]; hb; hb = hbnext)
      77             :       {
      78           0 :         unsigned int h = hb->key & (new_size - 1);
      79             : 
      80           0 :         hbnext = hb->next;
      81           0 :         hb->next = new_index[h];
      82           0 :         new_index[h] = hb;
      83             :       }
      84             : 
      85             :   /* Switch to new table */
      86           0 :   XFREE(MTYPE_HASH_INDEX, hash->index);
      87           0 :   hash->size = new_size;
      88           0 :   hash->index = new_index;
      89             : 
      90             :   /* Ideally, new index should have chains half as long as the original.
      91             :      If expansion didn't help, then not worth expanding again,
      92             :      the problem is the hash function. */
      93           0 :   losers = 0;
      94           0 :   for (i = 0; i < hash->size; i++)
      95             :     {
      96           0 :       unsigned int len = 0;
      97           0 :       for (hb = hash->index[i]; hb; hb = hb->next)
      98             :         {
      99           0 :           if (++len > HASH_THRESHOLD/2)
     100           0 :             ++losers;
     101           0 :           if (len >= HASH_THRESHOLD)
     102           0 :             hash->no_expand = 1;
     103             :         }
     104             :     }
     105             : 
     106           0 :   if (losers > hash->count / 2)
     107           0 :     hash->no_expand = 1;
     108             : }
     109             : 
     110             : /* Lookup and return hash backet in hash.  If there is no
     111             :    corresponding hash backet and alloc_func is specified, create new
     112             :    hash backet.  */
     113             : void *
     114      149078 : hash_get (struct hash *hash, void *data, void * (*alloc_func) (void *))
     115             : {
     116             :   unsigned int key;
     117             :   unsigned int index;
     118             :   void *newdata;
     119             :   unsigned int len;
     120             :   struct hash_backet *backet;
     121             : 
     122      149078 :   key = (*hash->hash_key) (data);
     123      149078 :   index = key & (hash->size - 1);
     124      149078 :   len = 0;
     125             : 
     126      198060 :   for (backet = hash->index[index]; backet != NULL; backet = backet->next)
     127             :     {
     128      196262 :       if (backet->key == key && (*hash->hash_cmp) (backet->data, data))
     129      147280 :         return backet->data;
     130       48982 :       ++len;
     131             :     }
     132             : 
     133        1798 :   if (alloc_func)
     134             :     {
     135        1058 :       newdata = (*alloc_func) (data);
     136        1058 :       if (newdata == NULL)
     137           0 :         return NULL;
     138             : 
     139        1058 :       if (len > HASH_THRESHOLD && !hash->no_expand)
     140             :         {
     141           0 :           hash_expand (hash);
     142           0 :           index = key & (hash->size - 1);
     143             :         }
     144             : 
     145        1058 :       backet = XMALLOC (MTYPE_HASH_BACKET, sizeof (struct hash_backet));
     146        1058 :       backet->data = newdata;
     147        1058 :       backet->key = key;
     148        1058 :       backet->next = hash->index[index];
     149        1058 :       hash->index[index] = backet;
     150        1058 :       hash->count++;
     151        1058 :       return backet->data;
     152             :     }
     153         740 :   return NULL;
     154             : }
     155             : 
     156             : /* Hash lookup.  */
     157             : void *
     158      145984 : hash_lookup (struct hash *hash, void *data)
     159             : {
     160      145984 :   return hash_get (hash, data, NULL);
     161             : }
     162             : 
     163             : /* Simple Bernstein hash which is simple and fast for common case */
     164           0 : unsigned int string_hash_make (const char *str)
     165             : {
     166           0 :   unsigned int hash = 0;
     167             : 
     168           0 :   while (*str)
     169           0 :     hash = (hash * 33) ^ (unsigned int) *str++;
     170             : 
     171           0 :   return hash;
     172             : }
     173             : 
     174             : /* This function release registered value from specified hash.  When
     175             :    release is successfully finished, return the data pointer in the
     176             :    hash backet.  */
     177             : void *
     178         459 : hash_release (struct hash *hash, void *data)
     179             : {
     180             :   void *ret;
     181             :   unsigned int key;
     182             :   unsigned int index;
     183             :   struct hash_backet *backet;
     184             :   struct hash_backet *pp;
     185             : 
     186         459 :   key = (*hash->hash_key) (data);
     187         459 :   index = key & (hash->size - 1);
     188             : 
     189         530 :   for (backet = pp = hash->index[index]; backet; backet = backet->next)
     190             :     {
     191         530 :       if (backet->key == key && (*hash->hash_cmp) (backet->data, data)) 
     192             :         {
     193         459 :           if (backet == pp) 
     194         400 :             hash->index[index] = backet->next;
     195             :           else 
     196          59 :             pp->next = backet->next;
     197             : 
     198         459 :           ret = backet->data;
     199         459 :           XFREE (MTYPE_HASH_BACKET, backet);
     200         459 :           hash->count--;
     201         459 :           return ret;
     202             :         }
     203          71 :       pp = backet;
     204             :     }
     205           0 :   return NULL;
     206             : }
     207             : 
     208             : /* Iterator function for hash.  */
     209             : void
     210        1000 : hash_iterate (struct hash *hash, 
     211             :               void (*func) (struct hash_backet *, void *), void *arg)
     212             : {
     213             :   unsigned int i;
     214             :   struct hash_backet *hb;
     215             :   struct hash_backet *hbnext;
     216             : 
     217      257000 :   for (i = 0; i < hash->size; i++)
     218      401244 :     for (hb = hash->index[i]; hb; hb = hbnext)
     219             :       {
     220             :         /* get pointer to next hash backet here, in case (*func)
     221             :          * decides to delete hb by calling hash_release
     222             :          */
     223      145244 :         hbnext = hb->next;
     224      145244 :         (*func) (hb, arg);
     225             :       }
     226        1000 : }
     227             : 
     228             : /* Clean up hash.  */
     229             : void
     230           2 : hash_clean (struct hash *hash, void (*free_func) (void *))
     231             : {
     232             :   unsigned int i;
     233             :   struct hash_backet *hb;
     234             :   struct hash_backet *next;
     235             : 
     236         514 :   for (i = 0; i < hash->size; i++)
     237             :     {
     238         793 :       for (hb = hash->index[i]; hb; hb = next)
     239             :         {
     240         281 :           next = hb->next;
     241             :               
     242         281 :           if (free_func)
     243         281 :             (*free_func) (hb->data);
     244             : 
     245         281 :           XFREE (MTYPE_HASH_BACKET, hb);
     246         281 :           hash->count--;
     247             :         }
     248         512 :       hash->index[i] = NULL;
     249             :     }
     250           2 : }
     251             : 
     252             : /* Free hash memory.  You may call hash_clean before call this
     253             :    function.  */
     254             : void
     255           2 : hash_free (struct hash *hash)
     256             : {
     257           2 :   XFREE (MTYPE_HASH_INDEX, hash->index);
     258           2 :   XFREE (MTYPE_HASH, hash);
     259           2 : }

Generated by: LCOV version 1.10