github.com/spaolacci/murmur3@v1.1.0/murmur.go (about) 1 // Copyright 2013, Sébastien Paolacci. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 /* 6 Package murmur3 implements Austin Appleby's non-cryptographic MurmurHash3. 7 8 Reference implementation: 9 http://code.google.com/p/smhasher/wiki/MurmurHash3 10 11 History, characteristics and (legacy) perfs: 12 https://sites.google.com/site/murmurhash/ 13 https://sites.google.com/site/murmurhash/statistics 14 */ 15 package murmur3 16 17 type bmixer interface { 18 bmix(p []byte) (tail []byte) 19 Size() (n int) 20 reset() 21 } 22 23 type digest struct { 24 clen int // Digested input cumulative length. 25 tail []byte // 0 to Size()-1 bytes view of `buf'. 26 buf [16]byte // Expected (but not required) to be Size() large. 27 seed uint32 // Seed for initializing the hash. 28 bmixer 29 } 30 31 func (d *digest) BlockSize() int { return 1 } 32 33 func (d *digest) Write(p []byte) (n int, err error) { 34 n = len(p) 35 d.clen += n 36 37 if len(d.tail) > 0 { 38 // Stick back pending bytes. 39 nfree := d.Size() - len(d.tail) // nfree ∈ [1, d.Size()-1]. 40 if nfree < len(p) { 41 // One full block can be formed. 42 block := append(d.tail, p[:nfree]...) 43 p = p[nfree:] 44 _ = d.bmix(block) // No tail. 45 } else { 46 // Tail's buf is large enough to prevent reallocs. 47 p = append(d.tail, p...) 48 } 49 } 50 51 d.tail = d.bmix(p) 52 53 // Keep own copy of the 0 to Size()-1 pending bytes. 54 nn := copy(d.buf[:], d.tail) 55 d.tail = d.buf[:nn] 56 57 return n, nil 58 } 59 60 func (d *digest) Reset() { 61 d.clen = 0 62 d.tail = nil 63 d.bmixer.reset() 64 }