github.com/Jeffail/benthos/v3@v3.65.0/lib/util/hash/murmur2/murmur2.go (about)

     1  package murmur2
     2  
     3  import "hash"
     4  
     5  type murmur2 struct {
     6  	data   []byte
     7  	cached *uint32
     8  }
     9  
    10  // New32 creates a murmur 2 based hash.Hash32 implementation.
    11  func New32() hash.Hash32 {
    12  	return &murmur2{
    13  		data: make([]byte, 0),
    14  	}
    15  }
    16  
    17  // Write a slice of data to the hasher.
    18  func (mur *murmur2) Write(p []byte) (n int, err error) {
    19  	mur.data = append(mur.data, p...)
    20  	mur.cached = nil
    21  	return len(p), nil
    22  }
    23  
    24  // Sum appends the current hash to b and returns the resulting slice.
    25  // It does not change the underlying hash state.
    26  func (mur *murmur2) Sum(b []byte) []byte {
    27  	v := mur.Sum32()
    28  	return append(b, byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
    29  }
    30  
    31  // Reset resets the Hash to its initial state.
    32  func (mur *murmur2) Reset() {
    33  	mur.data = mur.data[0:0]
    34  	mur.cached = nil
    35  }
    36  
    37  // Size returns the number of bytes Sum will return.
    38  func (mur *murmur2) Size() int {
    39  	return 4
    40  }
    41  
    42  // BlockSize returns the hash's underlying block size.
    43  // The Write method must be able to accept any amount
    44  // of data, but it may operate more efficiently if all writes
    45  // are a multiple of the block size.
    46  func (mur *murmur2) BlockSize() int {
    47  	return 4
    48  }
    49  
    50  const (
    51  	seed uint32 = uint32(0x9747b28c)
    52  	m    int32  = int32(0x5bd1e995)
    53  	r    uint32 = uint32(24)
    54  )
    55  
    56  func (mur *murmur2) Sum32() uint32 {
    57  	if mur.cached != nil {
    58  		return *mur.cached
    59  	}
    60  
    61  	length := int32(len(mur.data))
    62  
    63  	h := int32(seed ^ uint32(length))
    64  	length4 := length / 4
    65  
    66  	for i := int32(0); i < length4; i++ {
    67  		i4 := i * 4
    68  		k := int32(mur.data[i4+0]&0xff) +
    69  			(int32(mur.data[i4+1]&0xff) << 8) +
    70  			(int32(mur.data[i4+2]&0xff) << 16) +
    71  			(int32(mur.data[i4+3]&0xff) << 24)
    72  		k *= m
    73  		k ^= int32(uint32(k) >> r)
    74  		k *= m
    75  		h *= m
    76  		h ^= k
    77  	}
    78  
    79  	switch length % 4 {
    80  	case 3:
    81  		h ^= int32(mur.data[(length & ^3)+2]&0xff) << 16
    82  		fallthrough
    83  	case 2:
    84  		h ^= int32(mur.data[(length & ^3)+1]&0xff) << 8
    85  		fallthrough
    86  	case 1:
    87  		h ^= int32(mur.data[length & ^3] & 0xff)
    88  		h *= m
    89  	}
    90  
    91  	h ^= int32(uint32(h) >> 13)
    92  	h *= m
    93  	h ^= int32(uint32(h) >> 15)
    94  
    95  	cached := uint32(h)
    96  	mur.cached = &cached
    97  	return cached
    98  }