LCOV - code coverage report
Current view: top level - util - murmurhash3.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 35 35 100.0 %
Date: 2012-11-29 Functions: 1 1 100.0 %
Branches: 5 6 83.3 %

           Branch data     Line data    Source code
       1                 :            : /* This file is based on the public domain MurmurHash3 from Austin Appleby:
       2                 :            :  * http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp
       3                 :            :  *
       4                 :            :  * We use only the 32 bit variant because the 2 produce different result while
       5                 :            :  * we need to produce the same result regardless of the architecture as
       6                 :            :  * clients can be both 64 or 32 bit at the same time.
       7                 :            :  */
       8                 :            : 
       9                 :            : #include <stdlib.h>
      10                 :            : #include <stdint.h>
      11                 :            : #include <endian.h>
      12                 :            : #include <string.h>
      13                 :            : #include <byteswap.h>
      14                 :            : 
      15                 :            : /* support RHEL5 lack of definitions */
      16                 :            : #ifndef le32toh
      17                 :            : # if __BYTE_ORDER == __LITTLE_ENDIAN
      18                 :            : #  define le32toh(x) (x)
      19                 :            : # else
      20                 :            : #  define le32toh(x) bswap_32 (x)
      21                 :            : # endif
      22                 :            : #endif
      23                 :            : 
      24                 :            : 
      25                 :            : static uint32_t rotl(uint32_t x, int8_t r)
      26                 :            : {
      27                 :         57 :     return (x << r) | (x >> (32 - r));
      28                 :            : }
      29                 :            : 
      30                 :            : /* slower than original but is endian neutral and handles platforms that
      31                 :            :  * do only aligned reads */
      32                 :            : __attribute__((always_inline))
      33                 :            : static inline uint32_t getblock(const uint8_t *p, int i)
      34                 :            : {
      35                 :            :     uint32_t r;
      36                 :         24 :     size_t size = sizeof(uint32_t);
      37                 :            : 
      38                 :         24 :     memcpy(&r, &p[i * size], size);
      39                 :            : 
      40                 :            :     return le32toh(r);
      41                 :            : }
      42                 :            : 
      43                 :            : /*
      44                 :            :  * Finalization mix - force all bits of a hash block to avalanche
      45                 :            :  */
      46                 :            : 
      47                 :            : __attribute__((always_inline))
      48                 :            : static inline uint32_t fmix(uint32_t h)
      49                 :            : {
      50                 :          9 :     h ^= h >> 16;
      51                 :          9 :     h *= 0x85ebca6b;
      52                 :          9 :     h ^= h >> 13;
      53                 :          9 :     h *= 0xc2b2ae35;
      54                 :          9 :     h ^= h >> 16;
      55                 :            : 
      56                 :            :     return h;
      57                 :            : }
      58                 :            : 
      59                 :            : 
      60                 :          9 : uint32_t murmurhash3(const char *key, int len, uint32_t seed)
      61                 :            : {
      62                 :            :     const uint8_t *blocks;
      63                 :            :     const uint8_t *tail;
      64                 :            :     int nblocks;
      65                 :            :     uint32_t h1;
      66                 :            :     uint32_t k1;
      67                 :            :     uint32_t c1;
      68                 :            :     uint32_t c2;
      69                 :            :     int i;
      70                 :            : 
      71                 :          9 :     blocks = (const uint8_t *)key;
      72                 :          9 :     nblocks = len / 4;
      73                 :          9 :     h1 = seed;
      74                 :          9 :     c1 = 0xcc9e2d51;
      75                 :          9 :     c2 = 0x1b873593;
      76                 :            : 
      77                 :            :     /* body */
      78                 :            : 
      79         [ +  + ]:         33 :     for (i = 0; i < nblocks; i++) {
      80                 :            : 
      81                 :         24 :         k1 = getblock(blocks, i);
      82                 :            : 
      83                 :         24 :         k1 *= c1;
      84                 :         24 :         k1 = rotl(k1, 15);
      85                 :         24 :         k1 *= c2;
      86                 :            : 
      87                 :         24 :         h1 ^= k1;
      88                 :         24 :         h1 = rotl(h1, 13);
      89                 :         24 :         h1 = h1 * 5 + 0xe6546b64;
      90                 :            :     }
      91                 :            : 
      92                 :            :     /* tail */
      93                 :            : 
      94                 :          9 :     tail = (const uint8_t *)key + nblocks * 4;
      95                 :            : 
      96                 :          9 :     k1 = 0;
      97                 :            : 
      98   [ +  +  +  - ]:          9 :     switch (len & 3) {
      99                 :            :     case 3:
     100                 :          5 :         k1 ^= tail[2] << 16;
     101                 :            :     case 2:
     102                 :          8 :         k1 ^= tail[1] << 8;
     103                 :            :     case 1:
     104                 :          9 :         k1 ^= tail[0];
     105                 :          9 :         k1 *= c1;
     106                 :          9 :         k1 = rotl(k1, 15);
     107                 :          9 :         k1 *= c2;
     108                 :          9 :         h1 ^= k1;
     109                 :            :     default:
     110                 :            :         break;
     111                 :            :     }
     112                 :            : 
     113                 :            :     /* finalization */
     114                 :            : 
     115                 :          9 :     h1 ^= len;
     116                 :          9 :     h1 = fmix(h1);
     117                 :            : 
     118                 :          9 :     return h1;
     119                 :            : }
     120                 :            : 
     121                 :            : 

Generated by: LCOV version 1.9