LCOV - code coverage report
Current view: directory - libdm/datastruct - hash.c (source / functions) Found Hit Coverage
Test: unnamed Lines: 111 91 82.0 %
Date: 2010-04-13 Functions: 20 16 80.0 %

       1                 : /*
       2                 :  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
       3                 :  * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
       4                 :  *
       5                 :  * This file is part of the device-mapper userspace tools.
       6                 :  *
       7                 :  * This copyrighted material is made available to anyone wishing to use,
       8                 :  * modify, copy, or redistribute it subject to the terms and conditions
       9                 :  * of the GNU Lesser General Public License v.2.1.
      10                 :  *
      11                 :  * You should have received a copy of the GNU Lesser General Public License
      12                 :  * along with this program; if not, write to the Free Software Foundation,
      13                 :  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      14                 :  */
      15                 : 
      16                 : #include "dmlib.h"
      17                 : 
      18                 : struct dm_hash_node {
      19                 :         struct dm_hash_node *next;
      20                 :         void *data;
      21                 :         unsigned keylen;
      22                 :         char key[0];
      23                 : };
      24                 : 
      25                 : struct dm_hash_table {
      26                 :         unsigned num_nodes;
      27                 :         unsigned num_slots;
      28                 :         struct dm_hash_node **slots;
      29                 : };
      30                 : 
      31                 : /* Permutation of the Integers 0 through 255 */
      32                 : static unsigned char _nums[] = {
      33                 :         1, 14, 110, 25, 97, 174, 132, 119, 138, 170, 125, 118, 27, 233, 140, 51,
      34                 :         87, 197, 177, 107, 234, 169, 56, 68, 30, 7, 173, 73, 188, 40, 36, 65,
      35                 :         49, 213, 104, 190, 57, 211, 148, 223, 48, 115, 15, 2, 67, 186, 210, 28,
      36                 :         12, 181, 103, 70, 22, 58, 75, 78, 183, 167, 238, 157, 124, 147, 172,
      37                 :         144,
      38                 :         176, 161, 141, 86, 60, 66, 128, 83, 156, 241, 79, 46, 168, 198, 41, 254,
      39                 :         178, 85, 253, 237, 250, 154, 133, 88, 35, 206, 95, 116, 252, 192, 54,
      40                 :         221,
      41                 :         102, 218, 255, 240, 82, 106, 158, 201, 61, 3, 89, 9, 42, 155, 159, 93,
      42                 :         166, 80, 50, 34, 175, 195, 100, 99, 26, 150, 16, 145, 4, 33, 8, 189,
      43                 :         121, 64, 77, 72, 208, 245, 130, 122, 143, 55, 105, 134, 29, 164, 185,
      44                 :         194,
      45                 :         193, 239, 101, 242, 5, 171, 126, 11, 74, 59, 137, 228, 108, 191, 232,
      46                 :         139,
      47                 :         6, 24, 81, 20, 127, 17, 91, 92, 251, 151, 225, 207, 21, 98, 113, 112,
      48                 :         84, 226, 18, 214, 199, 187, 13, 32, 94, 220, 224, 212, 247, 204, 196,
      49                 :         43,
      50                 :         249, 236, 45, 244, 111, 182, 153, 136, 129, 90, 217, 202, 19, 165, 231,
      51                 :         71,
      52                 :         230, 142, 96, 227, 62, 179, 246, 114, 162, 53, 160, 215, 205, 180, 47,
      53                 :         109,
      54                 :         44, 38, 31, 149, 135, 0, 216, 52, 63, 23, 37, 69, 39, 117, 146, 184,
      55                 :         163, 200, 222, 235, 248, 243, 219, 10, 152, 131, 123, 229, 203, 76, 120,
      56                 :         209
      57                 : };
      58                 : 
      59            1700 : static struct dm_hash_node *_create_node(const char *str, unsigned len)
      60                 : {
      61            1700 :         struct dm_hash_node *n = dm_malloc(sizeof(*n) + len);
      62                 : 
      63            1700 :         if (n) {
      64            1700 :                 memcpy(n->key, str, len);
      65            1700 :                 n->keylen = len;
      66                 :         }
      67                 : 
      68            1700 :         return n;
      69                 : }
      70                 : 
      71            3931 : static unsigned long _hash(const char *str, unsigned len)
      72                 : {
      73            3931 :         unsigned long h = 0, g;
      74                 :         unsigned i;
      75                 : 
      76           63037 :         for (i = 0; i < len; i++) {
      77           59106 :                 h <<= 4;
      78           59106 :                 h += _nums[(unsigned char) *str++];
      79           59106 :                 g = h & ((unsigned long) 0xf << 16u);
      80           59106 :                 if (g) {
      81           45233 :                         h ^= g >> 16u;
      82           45233 :                         h ^= g >> 5u;
      83                 :                 }
      84                 :         }
      85                 : 
      86            3931 :         return h;
      87                 : }
      88                 : 
      89              18 : struct dm_hash_table *dm_hash_create(unsigned size_hint)
      90                 : {
      91                 :         size_t len;
      92              18 :         unsigned new_size = 16u;
      93              18 :         struct dm_hash_table *hc = dm_malloc(sizeof(*hc));
      94                 : 
      95              18 :         if (!hc) {
      96               0 :                 stack;
      97               0 :                 return 0;
      98                 :         }
      99                 : 
     100              18 :         memset(hc, 0, sizeof(*hc));
     101                 : 
     102                 :         /* round size hint up to a power of two */
     103              90 :         while (new_size < size_hint)
     104              54 :                 new_size = new_size << 1;
     105                 : 
     106              18 :         hc->num_slots = new_size;
     107              18 :         len = sizeof(*(hc->slots)) * new_size;
     108              18 :         if (!(hc->slots = dm_malloc(len))) {
     109               0 :                 stack;
     110               0 :                 goto bad;
     111                 :         }
     112              18 :         memset(hc->slots, 0, len);
     113              18 :         return hc;
     114                 : 
     115                 :       bad:
     116               0 :         dm_free(hc->slots);
     117               0 :         dm_free(hc);
     118               0 :         return 0;
     119                 : }
     120                 : 
     121              18 : static void _free_nodes(struct dm_hash_table *t)
     122                 : {
     123                 :         struct dm_hash_node *c, *n;
     124                 :         unsigned i;
     125                 : 
     126            2322 :         for (i = 0; i < t->num_slots; i++)
     127            3994 :                 for (c = t->slots[i]; c; c = n) {
     128            1690 :                         n = c->next;
     129            1690 :                         dm_free(c);
     130                 :                 }
     131              18 : }
     132                 : 
     133              18 : void dm_hash_destroy(struct dm_hash_table *t)
     134                 : {
     135              18 :         _free_nodes(t);
     136              18 :         dm_free(t->slots);
     137              18 :         dm_free(t);
     138              18 : }
     139                 : 
     140            3931 : static struct dm_hash_node **_find(struct dm_hash_table *t, const char *key,
     141                 :                                    uint32_t len)
     142                 : {
     143            3931 :         unsigned h = _hash(key, len) & (t->num_slots - 1);
     144                 :         struct dm_hash_node **c;
     145                 : 
     146           19368 :         for (c = &t->slots[h]; *c; c = &((*c)->next)) {
     147           15508 :                 if ((*c)->keylen != len)
     148            4337 :                         continue;
     149                 : 
     150           11171 :                 if (!memcmp(key, (*c)->key, len))
     151              71 :                         break;
     152                 :         }
     153                 : 
     154            3931 :         return c;
     155                 : }
     156                 : 
     157            2220 : void *dm_hash_lookup_binary(struct dm_hash_table *t, const char *key,
     158                 :                          uint32_t len)
     159                 : {
     160            2220 :         struct dm_hash_node **c = _find(t, key, len);
     161                 : 
     162            2220 :         return *c ? (*c)->data : 0;
     163                 : }
     164                 : 
     165            1701 : int dm_hash_insert_binary(struct dm_hash_table *t, const char *key,
     166                 :                           uint32_t len, void *data)
     167                 : {
     168            1701 :         struct dm_hash_node **c = _find(t, key, len);
     169                 : 
     170            1701 :         if (*c)
     171               1 :                 (*c)->data = data;
     172                 :         else {
     173            1700 :                 struct dm_hash_node *n = _create_node(key, len);
     174                 : 
     175            1700 :                 if (!n)
     176               0 :                         return 0;
     177                 : 
     178            1700 :                 n->data = data;
     179            1700 :                 n->next = 0;
     180            1700 :                 *c = n;
     181            1700 :                 t->num_nodes++;
     182                 :         }
     183                 : 
     184            1701 :         return 1;
     185                 : }
     186                 : 
     187              10 : void dm_hash_remove_binary(struct dm_hash_table *t, const char *key,
     188                 :                         uint32_t len)
     189                 : {
     190              10 :         struct dm_hash_node **c = _find(t, key, len);
     191                 : 
     192              10 :         if (*c) {
     193              10 :                 struct dm_hash_node *old = *c;
     194              10 :                 *c = (*c)->next;
     195              10 :                 dm_free(old);
     196              10 :                 t->num_nodes--;
     197                 :         }
     198              10 : }
     199                 : 
     200            2220 : void *dm_hash_lookup(struct dm_hash_table *t, const char *key)
     201                 : {
     202            2220 :         return dm_hash_lookup_binary(t, key, strlen(key) + 1);
     203                 : }
     204                 : 
     205            1701 : int dm_hash_insert(struct dm_hash_table *t, const char *key, void *data)
     206                 : {
     207            1701 :         return dm_hash_insert_binary(t, key, strlen(key) + 1, data);
     208                 : }
     209                 : 
     210              10 : void dm_hash_remove(struct dm_hash_table *t, const char *key)
     211                 : {
     212              10 :         dm_hash_remove_binary(t, key, strlen(key) + 1);
     213              10 : }
     214                 : 
     215               2 : unsigned dm_hash_get_num_entries(struct dm_hash_table *t)
     216                 : {
     217               2 :         return t->num_nodes;
     218                 : }
     219                 : 
     220              14 : void dm_hash_iter(struct dm_hash_table *t, dm_hash_iterate_fn f)
     221                 : {
     222                 :         struct dm_hash_node *c, *n;
     223                 :         unsigned i;
     224                 : 
     225            1806 :         for (i = 0; i < t->num_slots; i++)
     226            2841 :                 for (c = t->slots[i]; c; c = n) {
     227            1049 :                         n = c->next;
     228            1049 :                         f(c->data);
     229                 :                 }
     230              14 : }
     231                 : 
     232               0 : void dm_hash_wipe(struct dm_hash_table *t)
     233                 : {
     234               0 :         _free_nodes(t);
     235               0 :         memset(t->slots, 0, sizeof(struct dm_hash_node *) * t->num_slots);
     236               0 :         t->num_nodes = 0u;
     237               0 : }
     238                 : 
     239               0 : char *dm_hash_get_key(struct dm_hash_table *t __attribute((unused)),
     240                 :                       struct dm_hash_node *n)
     241                 : {
     242               0 :         return n->key;
     243                 : }
     244                 : 
     245               0 : void *dm_hash_get_data(struct dm_hash_table *t __attribute((unused)),
     246                 :                        struct dm_hash_node *n)
     247                 : {
     248               0 :         return n->data;
     249                 : }
     250                 : 
     251               3 : static struct dm_hash_node *_next_slot(struct dm_hash_table *t, unsigned s)
     252                 : {
     253               3 :         struct dm_hash_node *c = NULL;
     254                 :         unsigned i;
     255                 : 
     256             387 :         for (i = s; i < t->num_slots && !c; i++)
     257             384 :                 c = t->slots[i];
     258                 : 
     259               3 :         return c;
     260                 : }
     261                 : 
     262               3 : struct dm_hash_node *dm_hash_get_first(struct dm_hash_table *t)
     263                 : {
     264               3 :         return _next_slot(t, 0);
     265                 : }
     266                 : 
     267               0 : struct dm_hash_node *dm_hash_get_next(struct dm_hash_table *t, struct dm_hash_node *n)
     268                 : {
     269               0 :         unsigned h = _hash(n->key, n->keylen) & (t->num_slots - 1);
     270                 : 
     271               0 :         return n->next ? n->next : _next_slot(t, h + 1);
     272                 : }

Generated by: LCOV version 1.7