murmur.go 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  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. Package murmur3 implements Austin Appleby's non-cryptographic MurmurHash3.
  6. Reference implementation:
  7. http://code.google.com/p/smhasher/wiki/MurmurHash3
  8. History, characteristics and (legacy) perfs:
  9. https://sites.google.com/site/murmurhash/
  10. https://sites.google.com/site/murmurhash/statistics
  11. */
  12. package murmur3
  13. type bmixer interface {
  14. bmix(p []byte) (tail []byte)
  15. Size() (n int)
  16. reset()
  17. }
  18. type digest struct {
  19. clen int // Digested input cumulative length.
  20. tail []byte // 0 to Size()-1 bytes view of `buf'.
  21. buf [16]byte // Expected (but not required) to be Size() large.
  22. seed uint32 // Seed for initializing the hash.
  23. bmixer
  24. }
  25. func (d *digest) BlockSize() int { return 1 }
  26. func (d *digest) Write(p []byte) (n int, err error) {
  27. n = len(p)
  28. d.clen += n
  29. if len(d.tail) > 0 {
  30. // Stick back pending bytes.
  31. nfree := d.Size() - len(d.tail) // nfree ∈ [1, d.Size()-1].
  32. if nfree < len(p) {
  33. // One full block can be formed.
  34. block := append(d.tail, p[:nfree]...)
  35. p = p[nfree:]
  36. _ = d.bmix(block) // No tail.
  37. } else {
  38. // Tail's buf is large enough to prevent reallocs.
  39. p = append(d.tail, p...)
  40. }
  41. }
  42. d.tail = d.bmix(p)
  43. // Keep own copy of the 0 to Size()-1 pending bytes.
  44. nn := copy(d.buf[:], d.tail)
  45. d.tail = d.buf[:nn]
  46. return n, nil
  47. }
  48. func (d *digest) Reset() {
  49. d.clen = 0
  50. d.tail = nil
  51. d.bmixer.reset()
  52. }