LCOV - code coverage report
Current view: top level - misc/kabi/lvm2.git/libdm/datastruct - hash.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 91 111 82.0 %
Date: 2010-04-13 Functions: 16 20 80.0 %
Branches: 31 44 70.5 %

           Branch data     Line data    Source code
       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                 :        293 : static struct dm_hash_node *_create_node(const char *str, unsigned len)
      60                 :            : {
      61                 :        293 :         struct dm_hash_node *n = dm_malloc(sizeof(*n) + len);
      62                 :            : 
      63         [ +  - ]:        293 :         if (n) {
      64                 :        293 :                 memcpy(n->key, str, len);
      65                 :        293 :                 n->keylen = len;
      66                 :            :         }
      67                 :            : 
      68                 :        293 :         return n;
      69                 :            : }
      70                 :            : 
      71                 :        421 : static unsigned long _hash(const char *str, unsigned len)
      72                 :            : {
      73                 :        421 :         unsigned long h = 0, g;
      74                 :            :         unsigned i;
      75                 :            : 
      76         [ +  + ]:      10454 :         for (i = 0; i < len; i++) {
      77                 :      10033 :                 h <<= 4;
      78                 :      10033 :                 h += _nums[(unsigned char) *str++];
      79                 :      10033 :                 g = h & ((unsigned long) 0xf << 16u);
      80         [ +  + ]:      10033 :                 if (g) {
      81                 :       7915 :                         h ^= g >> 16u;
      82                 :       7915 :                         h ^= g >> 5u;
      83                 :            :                 }
      84                 :            :         }
      85                 :            : 
      86                 :        421 :         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         [ +  + ]:         72 :         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                 :         18 :         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         [ +  + ]:       2587 :                 for (c = t->slots[i]; c; c = n) {
     128                 :        283 :                         n = c->next;
     129                 :        283 :                         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                 :        421 : static struct dm_hash_node **_find(struct dm_hash_table *t, const char *key,
     141                 :            :                                    uint32_t len)
     142                 :            : {
     143                 :        421 :         unsigned h = _hash(key, len) & (t->num_slots - 1);
     144                 :            :         struct dm_hash_node **c;
     145                 :            : 
     146         [ +  + ]:        590 :         for (c = &t->slots[h]; *c; c = &((*c)->next)) {
     147         [ +  + ]:        212 :                 if ((*c)->keylen != len)
     148                 :         87 :                         continue;
     149                 :            : 
     150         [ +  + ]:        125 :                 if (!memcmp(key, (*c)->key, len))
     151                 :         43 :                         break;
     152                 :            :         }
     153                 :            : 
     154                 :        421 :         return c;
     155                 :            : }
     156                 :            : 
     157                 :        118 : void *dm_hash_lookup_binary(struct dm_hash_table *t, const char *key,
     158                 :            :                          uint32_t len)
     159                 :            : {
     160                 :        118 :         struct dm_hash_node **c = _find(t, key, len);
     161                 :            : 
     162         [ +  + ]:        118 :         return *c ? (*c)->data : 0;
     163                 :            : }
     164                 :            : 
     165                 :        293 : int dm_hash_insert_binary(struct dm_hash_table *t, const char *key,
     166                 :            :                           uint32_t len, void *data)
     167                 :            : {
     168                 :        293 :         struct dm_hash_node **c = _find(t, key, len);
     169                 :            : 
     170         [ -  + ]:        293 :         if (*c)
     171                 :          0 :                 (*c)->data = data;
     172                 :            :         else {
     173                 :        293 :                 struct dm_hash_node *n = _create_node(key, len);
     174                 :            : 
     175         [ -  + ]:        293 :                 if (!n)
     176                 :          0 :                         return 0;
     177                 :            : 
     178                 :        293 :                 n->data = data;
     179                 :        293 :                 n->next = 0;
     180                 :        293 :                 *c = n;
     181                 :        293 :                 t->num_nodes++;
     182                 :            :         }
     183                 :            : 
     184                 :        293 :         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                 :        118 : void *dm_hash_lookup(struct dm_hash_table *t, const char *key)
     201                 :            : {
     202                 :        118 :         return dm_hash_lookup_binary(t, key, strlen(key) + 1);
     203                 :            : }
     204                 :            : 
     205                 :        293 : int dm_hash_insert(struct dm_hash_table *t, const char *key, void *data)
     206                 :            : {
     207                 :        293 :         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         [ +  + ]:       1938 :                 for (c = t->slots[i]; c; c = n) {
     227                 :        146 :                         n = c->next;
     228                 :        146 :                         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.8