github.com/kelleygo/clashcore@v1.0.2/common/murmur3/murmur32.go (about)

     1  package murmur3
     2  
     3  // https://github.com/spaolacci/murmur3/blob/master/murmur32.go
     4  
     5  import (
     6  	"hash"
     7  	"math/bits"
     8  	"unsafe"
     9  )
    10  
    11  // Make sure interfaces are correctly implemented.
    12  var (
    13  	_ hash.Hash32 = new(digest32)
    14  	_ bmixer      = new(digest32)
    15  )
    16  
    17  const (
    18  	c1_32 uint32 = 0xcc9e2d51
    19  	c2_32 uint32 = 0x1b873593
    20  )
    21  
    22  // digest32 represents a partial evaluation of a 32 bites hash.
    23  type digest32 struct {
    24  	digest
    25  	h1 uint32 // Unfinalized running hash.
    26  }
    27  
    28  // New32 returns new 32-bit hasher
    29  func New32() hash.Hash32 { return New32WithSeed(0) }
    30  
    31  // New32WithSeed returns new 32-bit hasher set with explicit seed value
    32  func New32WithSeed(seed uint32) hash.Hash32 {
    33  	d := new(digest32)
    34  	d.seed = seed
    35  	d.bmixer = d
    36  	d.Reset()
    37  	return d
    38  }
    39  
    40  func (d *digest32) Size() int { return 4 }
    41  
    42  func (d *digest32) reset() { d.h1 = d.seed }
    43  
    44  func (d *digest32) Sum(b []byte) []byte {
    45  	h := d.Sum32()
    46  	return append(b, byte(h>>24), byte(h>>16), byte(h>>8), byte(h))
    47  }
    48  
    49  // Digest as many blocks as possible.
    50  func (d *digest32) bmix(p []byte) (tail []byte) {
    51  	h1 := d.h1
    52  
    53  	nblocks := len(p) / 4
    54  	for i := 0; i < nblocks; i++ {
    55  		k1 := *(*uint32)(unsafe.Pointer(&p[i*4]))
    56  
    57  		k1 *= c1_32
    58  		k1 = bits.RotateLeft32(k1, 15)
    59  		k1 *= c2_32
    60  
    61  		h1 ^= k1
    62  		h1 = bits.RotateLeft32(h1, 13)
    63  		h1 = h1*4 + h1 + 0xe6546b64
    64  	}
    65  	d.h1 = h1
    66  	return p[nblocks*d.Size():]
    67  }
    68  
    69  func (d *digest32) Sum32() (h1 uint32) {
    70  	h1 = d.h1
    71  
    72  	var k1 uint32
    73  	switch len(d.tail) & 3 {
    74  	case 3:
    75  		k1 ^= uint32(d.tail[2]) << 16
    76  		fallthrough
    77  	case 2:
    78  		k1 ^= uint32(d.tail[1]) << 8
    79  		fallthrough
    80  	case 1:
    81  		k1 ^= uint32(d.tail[0])
    82  		k1 *= c1_32
    83  		k1 = bits.RotateLeft32(k1, 15)
    84  		k1 *= c2_32
    85  		h1 ^= k1
    86  	}
    87  
    88  	h1 ^= uint32(d.clen)
    89  
    90  	h1 ^= h1 >> 16
    91  	h1 *= 0x85ebca6b
    92  	h1 ^= h1 >> 13
    93  	h1 *= 0xc2b2ae35
    94  	h1 ^= h1 >> 16
    95  
    96  	return h1
    97  }
    98  
    99  func Sum32(data []byte) uint32 { return Sum32WithSeed(data, 0) }
   100  
   101  func Sum32WithSeed(data []byte, seed uint32) uint32 {
   102  	h1 := seed
   103  
   104  	nblocks := len(data) / 4
   105  	for i := 0; i < nblocks; i++ {
   106  		k1 := *(*uint32)(unsafe.Pointer(&data[i*4]))
   107  
   108  		k1 *= c1_32
   109  		k1 = bits.RotateLeft32(k1, 15)
   110  		k1 *= c2_32
   111  
   112  		h1 ^= k1
   113  		h1 = bits.RotateLeft32(h1, 13)
   114  		h1 = h1*4 + h1 + 0xe6546b64
   115  	}
   116  
   117  	tail := data[nblocks*4:]
   118  
   119  	var k1 uint32
   120  	switch len(tail) & 3 {
   121  	case 3:
   122  		k1 ^= uint32(tail[2]) << 16
   123  		fallthrough
   124  	case 2:
   125  		k1 ^= uint32(tail[1]) << 8
   126  		fallthrough
   127  	case 1:
   128  		k1 ^= uint32(tail[0])
   129  		k1 *= c1_32
   130  		k1 = bits.RotateLeft32(k1, 15)
   131  		k1 *= c2_32
   132  		h1 ^= k1
   133  	}
   134  
   135  	h1 ^= uint32(len(data))
   136  
   137  	h1 ^= h1 >> 16
   138  	h1 *= 0x85ebca6b
   139  	h1 ^= h1 >> 13
   140  	h1 *= 0xc2b2ae35
   141  	h1 ^= h1 >> 16
   142  
   143  	return h1
   144  }