LCOV - code coverage report
Current view: top level - util - murmurhash3.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 39 39 100.0 %
Date: 2016-06-29 Functions: 2 2 100.0 %

          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 <string.h>
      12             : 
      13             : #include "config.h"
      14             : #include "util/murmurhash3.h"
      15             : #include "util/sss_endian.h"
      16             : 
      17         998 : static uint32_t rotl(uint32_t x, int8_t r)
      18             : {
      19        1040 :     return (x << r) | (x >> (32 - r));
      20             : }
      21             : 
      22             : /* slower than original but is endian neutral and handles platforms that
      23             :  * do only aligned reads */
      24             : __attribute__((always_inline))
      25             : static inline uint32_t getblock(const uint8_t *p, int i)
      26             : {
      27             :     uint32_t r;
      28         482 :     size_t size = sizeof(uint32_t);
      29             : 
      30         482 :     memcpy(&r, &p[i * size], size);
      31             : 
      32         462 :     return le32toh(r);
      33             : }
      34             : 
      35             : /*
      36             :  * Finalization mix - force all bits of a hash block to avalanche
      37             :  */
      38             : 
      39             : __attribute__((always_inline))
      40             : static inline uint32_t fmix(uint32_t h)
      41             : {
      42          94 :     h ^= h >> 16;
      43          94 :     h *= 0x85ebca6b;
      44          94 :     h ^= h >> 13;
      45          94 :     h *= 0xc2b2ae35;
      46          94 :     h ^= h >> 16;
      47             : 
      48          92 :     return h;
      49             : }
      50             : 
      51             : 
      52          94 : uint32_t murmurhash3(const char *key, int len, uint32_t seed)
      53             : {
      54             :     const uint8_t *blocks;
      55             :     const uint8_t *tail;
      56             :     int nblocks;
      57             :     uint32_t h1;
      58             :     uint32_t k1;
      59             :     uint32_t c1;
      60             :     uint32_t c2;
      61             :     int i;
      62             : 
      63          94 :     blocks = (const uint8_t *)key;
      64          94 :     nblocks = len / 4;
      65          94 :     h1 = seed;
      66          94 :     c1 = 0xcc9e2d51;
      67          94 :     c2 = 0x1b873593;
      68             : 
      69             :     /* body */
      70             : 
      71         576 :     for (i = 0; i < nblocks; i++) {
      72             : 
      73         482 :         k1 = getblock(blocks, i);
      74             : 
      75         482 :         k1 *= c1;
      76         482 :         k1 = rotl(k1, 15);
      77         482 :         k1 *= c2;
      78             : 
      79         482 :         h1 ^= k1;
      80         482 :         h1 = rotl(h1, 13);
      81         482 :         h1 = h1 * 5 + 0xe6546b64;
      82             :     }
      83             : 
      84             :     /* tail */
      85             : 
      86          94 :     tail = (const uint8_t *)key + nblocks * 4;
      87             : 
      88          94 :     k1 = 0;
      89             : 
      90          94 :     switch (len & 3) {
      91             :     case 3:
      92           7 :         k1 ^= tail[2] << 16;
      93             :     case 2:
      94          46 :         k1 ^= tail[1] << 8;
      95             :     case 1:
      96          76 :         k1 ^= tail[0];
      97          76 :         k1 *= c1;
      98          76 :         k1 = rotl(k1, 15);
      99          76 :         k1 *= c2;
     100          76 :         h1 ^= k1;
     101             :     default:
     102          92 :         break;
     103             :     }
     104             : 
     105             :     /* finalization */
     106             : 
     107          94 :     h1 ^= len;
     108          94 :     h1 = fmix(h1);
     109             : 
     110          94 :     return h1;
     111             : }
     112             : 
     113             : 

Generated by: LCOV version 1.10