LCOV - code coverage report
Current view: top level - ccache - hashtable.c (source / functions) Hit Total Coverage
Test: ccache.lcov.info Lines: 17 106 16.0 %
Date: 2015-06-29 Functions: 1 8 12.5 %
Branches: 6 52 11.5 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :   Copyright (c) 2002, 2004, Christopher Clark
       3                 :            :   All rights reserved.
       4                 :            : 
       5                 :            :   Redistribution and use in source and binary forms, with or without
       6                 :            :   modification, are permitted provided that the following conditions are met:
       7                 :            : 
       8                 :            :     * Redistributions of source code must retain the above copyright notice,
       9                 :            :       this list of conditions and the following disclaimer.
      10                 :            : 
      11                 :            :     * Redistributions in binary form must reproduce the above copyright notice,
      12                 :            :       this list of conditions and the following disclaimer in the documentation
      13                 :            :       and/or other materials provided with the distribution.
      14                 :            : 
      15                 :            :     * Neither the name of the original author; nor the names of any
      16                 :            :       contributors may be used to endorse or promote products derived from this
      17                 :            :       software without specific prior written permission.
      18                 :            : 
      19                 :            :   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
      20                 :            :   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      21                 :            :   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      22                 :            :   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
      23                 :            :   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      24                 :            :   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      25                 :            :   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      26                 :            :   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      27                 :            :   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      28                 :            :   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      29                 :            :   POSSIBILITY OF SUCH DAMAGE.
      30                 :            : */
      31                 :            : 
      32                 :            : #include "hashtable.h"
      33                 :            : #include "hashtable_private.h"
      34                 :            : #include <stdlib.h>
      35                 :            : #include <stdio.h>
      36                 :            : #include <string.h>
      37                 :            : #include <math.h>
      38                 :            : 
      39                 :            : /*
      40                 :            : Credit for primes table: Aaron Krowne
      41                 :            :  http://br.endernet.org/~akrowne/
      42                 :            :  http://planetmath.org/encyclopedia/GoodHashTablePrimes.html
      43                 :            : */
      44                 :            : static const unsigned int primes[] = {
      45                 :            : 53, 97, 193, 389,
      46                 :            : 769, 1543, 3079, 6151,
      47                 :            : 12289, 24593, 49157, 98317,
      48                 :            : 196613, 393241, 786433, 1572869,
      49                 :            : 3145739, 6291469, 12582917, 25165843,
      50                 :            : 50331653, 100663319, 201326611, 402653189,
      51                 :            : 805306457, 1610612741
      52                 :            : };
      53                 :            : const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0]);
      54                 :            : const float max_load_factor = 0.65;
      55                 :            : 
      56                 :            : /*****************************************************************************/
      57                 :            : struct hashtable *
      58                 :          1 : create_hashtable(unsigned int minsize,
      59                 :            :                  unsigned int (*hashf) (void*),
      60                 :            :                  int (*eqf) (void*,void*))
      61                 :            : {
      62                 :            :     struct hashtable *h;
      63                 :          1 :     unsigned int pindex, size = primes[0];
      64                 :            :     /* Check requested hashtable isn't too large */
      65         [ -  + ]:          1 :     if (minsize > (1u << 30)) return NULL;
      66                 :            :     /* Enforce size as prime */
      67         [ +  - ]:          6 :     for (pindex=0; pindex < prime_table_length; pindex++) {
      68         [ +  + ]:          6 :         if (primes[pindex] > minsize) { size = primes[pindex]; break; }
      69                 :            :     }
      70                 :          1 :     h = (struct hashtable *)malloc(sizeof(struct hashtable));
      71         [ -  + ]:          1 :     if (NULL == h) return NULL; /*oom*/
      72                 :          1 :     h->table = (struct entry **)malloc(sizeof(struct entry*) * size);
      73         [ -  + ]:          1 :     if (NULL == h->table) { free(h); return NULL; } /*oom*/
      74                 :          1 :     memset(h->table, 0, size * sizeof(struct entry *));
      75                 :          1 :     h->tablelength  = size;
      76                 :          1 :     h->primeindex   = pindex;
      77                 :          1 :     h->entrycount   = 0;
      78                 :          1 :     h->hashfn       = hashf;
      79                 :          1 :     h->eqfn         = eqf;
      80                 :          1 :     h->loadlimit    = (unsigned int) ceil(size * max_load_factor);
      81                 :          1 :     return h;
      82                 :            : }
      83                 :            : 
      84                 :            : /*****************************************************************************/
      85                 :            : unsigned int
      86                 :          0 : hash(struct hashtable *h, void *k)
      87                 :            : {
      88                 :            :     /* Aim to protect against poor hash functions by adding logic here
      89                 :            :      * - logic taken from java 1.4 hashtable source */
      90                 :          0 :     unsigned int i = h->hashfn(k);
      91                 :          0 :     i += ~(i << 9);
      92                 :          0 :     i ^=  ((i >> 14) | (i << 18)); /* >>> */
      93                 :          0 :     i +=  (i << 4);
      94                 :          0 :     i ^=  ((i >> 10) | (i << 22)); /* >>> */
      95                 :          0 :     return i;
      96                 :            : }
      97                 :            : 
      98                 :            : /*****************************************************************************/
      99                 :            : static int
     100                 :          0 : hashtable_expand(struct hashtable *h)
     101                 :            : {
     102                 :            :     /* Double the size of the table to accommodate more entries */
     103                 :            :     struct entry **newtable;
     104                 :            :     struct entry *e;
     105                 :            :     struct entry **pE;
     106                 :            :     unsigned int newsize, i, index;
     107                 :            :     /* Check we're not hitting max capacity */
     108         [ #  # ]:          0 :     if (h->primeindex == (prime_table_length - 1)) return 0;
     109                 :          0 :     newsize = primes[++(h->primeindex)];
     110                 :            : 
     111                 :          0 :     newtable = (struct entry **)malloc(sizeof(struct entry*) * newsize);
     112         [ #  # ]:          0 :     if (NULL != newtable)
     113                 :            :     {
     114                 :          0 :         memset(newtable, 0, newsize * sizeof(struct entry *));
     115                 :            :         /* This algorithm is not 'stable'. ie. it reverses the list
     116                 :            :          * when it transfers entries between the tables */
     117         [ #  # ]:          0 :         for (i = 0; i < h->tablelength; i++) {
     118         [ #  # ]:          0 :             while (NULL != (e = h->table[i])) {
     119                 :          0 :                 h->table[i] = e->next;
     120                 :          0 :                 index = indexFor(newsize,e->h);
     121                 :          0 :                 e->next = newtable[index];
     122                 :          0 :                 newtable[index] = e;
     123                 :            :             }
     124                 :            :         }
     125                 :          0 :         free(h->table);
     126                 :          0 :         h->table = newtable;
     127                 :            :     }
     128                 :            :     /* Plan B: realloc instead */
     129                 :            :     else 
     130                 :            :     {
     131                 :          0 :         newtable = (struct entry **)
     132                 :          0 :                    realloc(h->table, newsize * sizeof(struct entry *));
     133         [ #  # ]:          0 :         if (NULL == newtable) { (h->primeindex)--; return 0; }
     134                 :          0 :         h->table = newtable;
     135                 :          0 :         memset(newtable[h->tablelength], 0, newsize - h->tablelength);
     136         [ #  # ]:          0 :         for (i = 0; i < h->tablelength; i++) {
     137         [ #  # ]:          0 :             for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) {
     138                 :          0 :                 index = indexFor(newsize,e->h);
     139         [ #  # ]:          0 :                 if (index == i)
     140                 :            :                 {
     141                 :          0 :                     pE = &(e->next);
     142                 :            :                 }
     143                 :            :                 else
     144                 :            :                 {
     145                 :          0 :                     *pE = e->next;
     146                 :          0 :                     e->next = newtable[index];
     147                 :          0 :                     newtable[index] = e;
     148                 :            :                 }
     149                 :            :             }
     150                 :            :         }
     151                 :            :     }
     152                 :          0 :     h->tablelength = newsize;
     153                 :          0 :     h->loadlimit   = (unsigned int) ceil(newsize * max_load_factor);
     154                 :          0 :     return -1;
     155                 :            : }
     156                 :            : 
     157                 :            : /*****************************************************************************/
     158                 :            : unsigned int
     159                 :          0 : hashtable_count(struct hashtable *h)
     160                 :            : {
     161                 :          0 :     return h->entrycount;
     162                 :            : }
     163                 :            : 
     164                 :            : /*****************************************************************************/
     165                 :            : int
     166                 :          0 : hashtable_insert(struct hashtable *h, void *k, void *v)
     167                 :            : {
     168                 :            :     /* This method allows duplicate keys - but they shouldn't be used */
     169                 :            :     unsigned int index;
     170                 :            :     struct entry *e;
     171         [ #  # ]:          0 :     if (++(h->entrycount) > h->loadlimit)
     172                 :            :     {
     173                 :            :         /* Ignore the return value. If expand fails, we should
     174                 :            :          * still try cramming just this value into the existing table
     175                 :            :          * -- we may not have memory for a larger table, but one more
     176                 :            :          * element may be ok. Next time we insert, we'll try expanding again.*/
     177                 :          0 :         hashtable_expand(h);
     178                 :            :     }
     179                 :          0 :     e = (struct entry *)malloc(sizeof(struct entry));
     180         [ #  # ]:          0 :     if (NULL == e) { --(h->entrycount); return 0; } /*oom*/
     181                 :          0 :     e->h = hash(h,k);
     182                 :          0 :     index = indexFor(h->tablelength,e->h);
     183                 :          0 :     e->k = k;
     184                 :          0 :     e->v = v;
     185                 :          0 :     e->next = h->table[index];
     186                 :          0 :     h->table[index] = e;
     187                 :          0 :     return -1;
     188                 :            : }
     189                 :            : 
     190                 :            : /*****************************************************************************/
     191                 :            : void * /* returns value associated with key */
     192                 :          0 : hashtable_search(struct hashtable *h, void *k)
     193                 :            : {
     194                 :            :     struct entry *e;
     195                 :            :     unsigned int hashvalue, index;
     196                 :          0 :     hashvalue = hash(h,k);
     197                 :          0 :     index = indexFor(h->tablelength,hashvalue);
     198                 :          0 :     e = h->table[index];
     199         [ #  # ]:          0 :     while (NULL != e)
     200                 :            :     {
     201                 :            :         /* Check hash value to short circuit heavier comparison */
     202 [ #  # ][ #  # ]:          0 :         if ((hashvalue == e->h) && (h->eqfn(k, e->k))) return e->v;
     203                 :          0 :         e = e->next;
     204                 :            :     }
     205                 :          0 :     return NULL;
     206                 :            : }
     207                 :            : 
     208                 :            : /*****************************************************************************/
     209                 :            : void * /* returns value associated with key */
     210                 :          0 : hashtable_remove(struct hashtable *h, void *k)
     211                 :            : {
     212                 :            :     /* TODO: consider compacting the table when the load factor drops enough,
     213                 :            :      *       or provide a 'compact' method. */
     214                 :            : 
     215                 :            :     struct entry *e;
     216                 :            :     struct entry **pE;
     217                 :            :     void *v;
     218                 :            :     unsigned int hashvalue, index;
     219                 :            : 
     220                 :          0 :     hashvalue = hash(h,k);
     221                 :          0 :     index = indexFor(h->tablelength,hash(h,k));
     222                 :          0 :     pE = &(h->table[index]);
     223                 :          0 :     e = *pE;
     224         [ #  # ]:          0 :     while (NULL != e)
     225                 :            :     {
     226                 :            :         /* Check hash value to short circuit heavier comparison */
     227 [ #  # ][ #  # ]:          0 :         if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
     228                 :            :         {
     229                 :          0 :             *pE = e->next;
     230                 :          0 :             h->entrycount--;
     231                 :          0 :             v = e->v;
     232                 :          0 :             freekey(e->k);
     233                 :          0 :             free(e);
     234                 :          0 :             return v;
     235                 :            :         }
     236                 :          0 :         pE = &(e->next);
     237                 :          0 :         e = e->next;
     238                 :            :     }
     239                 :          0 :     return NULL;
     240                 :            : }
     241                 :            : 
     242                 :            : /*****************************************************************************/
     243                 :            : /* destroy */
     244                 :            : void
     245                 :          0 : hashtable_destroy(struct hashtable *h, int free_values)
     246                 :            : {
     247                 :            :     unsigned int i;
     248                 :            :     struct entry *e, *f;
     249                 :          0 :     struct entry **table = h->table;
     250         [ #  # ]:          0 :     if (free_values)
     251                 :            :     {
     252         [ #  # ]:          0 :         for (i = 0; i < h->tablelength; i++)
     253                 :            :         {
     254                 :          0 :             e = table[i];
     255         [ #  # ]:          0 :             while (NULL != e)
     256                 :          0 :             { f = e; e = e->next; freekey(f->k); free(f->v); free(f); }
     257                 :            :         }
     258                 :            :     }
     259                 :            :     else
     260                 :            :     {
     261         [ #  # ]:          0 :         for (i = 0; i < h->tablelength; i++)
     262                 :            :         {
     263                 :          0 :             e = table[i];
     264         [ #  # ]:          0 :             while (NULL != e)
     265                 :          0 :             { f = e; e = e->next; freekey(f->k); free(f); }
     266                 :            :         }
     267                 :            :     }
     268                 :          0 :     free(h->table);
     269                 :          0 :     free(h);
     270                 :          0 : }
     271                 :            : 
     272                 :            : /*
     273                 :            :  * Copyright (c) 2002, Christopher Clark
     274                 :            :  * All rights reserved.
     275                 :            :  * 
     276                 :            :  * Redistribution and use in source and binary forms, with or without
     277                 :            :  * modification, are permitted provided that the following conditions
     278                 :            :  * are met:
     279                 :            :  * 
     280                 :            :  * * Redistributions of source code must retain the above copyright
     281                 :            :  * notice, this list of conditions and the following disclaimer.
     282                 :            :  * 
     283                 :            :  * * Redistributions in binary form must reproduce the above copyright
     284                 :            :  * notice, this list of conditions and the following disclaimer in the
     285                 :            :  * documentation and/or other materials provided with the distribution.
     286                 :            :  * 
     287                 :            :  * * Neither the name of the original author; nor the names of any contributors
     288                 :            :  * may be used to endorse or promote products derived from this software
     289                 :            :  * without specific prior written permission.
     290                 :            :  * 
     291                 :            :  * 
     292                 :            :  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     293                 :            :  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     294                 :            :  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     295                 :            :  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
     296                 :            :  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     297                 :            :  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     298                 :            :  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     299                 :            :  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     300                 :            :  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     301                 :            :  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     302                 :            :  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     303                 :            : */

Generated by: LCOV version 1.9