Black Lives Matter. Support the Equal Justice Initiative.

Source file src/hash/fnv/fnv.go

Documentation: hash/fnv

     1  // Copyright 2011 The Go Authors. 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 fnv implements FNV-1 and FNV-1a, non-cryptographic hash functions
     6  // created by Glenn Fowler, Landon Curt Noll, and Phong Vo.
     7  // See
     8  // https://en.wikipedia.org/wiki/Fowler-Noll-Vo_hash_function.
     9  //
    10  // All the hash.Hash implementations returned by this package also
    11  // implement encoding.BinaryMarshaler and encoding.BinaryUnmarshaler to
    12  // marshal and unmarshal the internal state of the hash.
    13  package fnv
    14  
    15  import (
    16  	"errors"
    17  	"hash"
    18  	"math/bits"
    19  )
    20  
    21  type (
    22  	sum32   uint32
    23  	sum32a  uint32
    24  	sum64   uint64
    25  	sum64a  uint64
    26  	sum128  [2]uint64
    27  	sum128a [2]uint64
    28  )
    29  
    30  const (
    31  	offset32        = 2166136261
    32  	offset64        = 14695981039346656037
    33  	offset128Lower  = 0x62b821756295c58d
    34  	offset128Higher = 0x6c62272e07bb0142
    35  	prime32         = 16777619
    36  	prime64         = 1099511628211
    37  	prime128Lower   = 0x13b
    38  	prime128Shift   = 24
    39  )
    40  
    41  // New32 returns a new 32-bit FNV-1 hash.Hash.
    42  // Its Sum method will lay the value out in big-endian byte order.
    43  func New32() hash.Hash32 {
    44  	var s sum32 = offset32
    45  	return &s
    46  }
    47  
    48  // New32a returns a new 32-bit FNV-1a hash.Hash.
    49  // Its Sum method will lay the value out in big-endian byte order.
    50  func New32a() hash.Hash32 {
    51  	var s sum32a = offset32
    52  	return &s
    53  }
    54  
    55  // New64 returns a new 64-bit FNV-1 hash.Hash.
    56  // Its Sum method will lay the value out in big-endian byte order.
    57  func New64() hash.Hash64 {
    58  	var s sum64 = offset64
    59  	return &s
    60  }
    61  
    62  // New64a returns a new 64-bit FNV-1a hash.Hash.
    63  // Its Sum method will lay the value out in big-endian byte order.
    64  func New64a() hash.Hash64 {
    65  	var s sum64a = offset64
    66  	return &s
    67  }
    68  
    69  // New128 returns a new 128-bit FNV-1 hash.Hash.
    70  // Its Sum method will lay the value out in big-endian byte order.
    71  func New128() hash.Hash {
    72  	var s sum128
    73  	s[0] = offset128Higher
    74  	s[1] = offset128Lower
    75  	return &s
    76  }
    77  
    78  // New128a returns a new 128-bit FNV-1a hash.Hash.
    79  // Its Sum method will lay the value out in big-endian byte order.
    80  func New128a() hash.Hash {
    81  	var s sum128a
    82  	s[0] = offset128Higher
    83  	s[1] = offset128Lower
    84  	return &s
    85  }
    86  
    87  func (s *sum32) Reset()   { *s = offset32 }
    88  func (s *sum32a) Reset()  { *s = offset32 }
    89  func (s *sum64) Reset()   { *s = offset64 }
    90  func (s *sum64a) Reset()  { *s = offset64 }
    91  func (s *sum128) Reset()  { s[0] = offset128Higher; s[1] = offset128Lower }
    92  func (s *sum128a) Reset() { s[0] = offset128Higher; s[1] = offset128Lower }
    93  
    94  func (s *sum32) Sum32() uint32  { return uint32(*s) }
    95  func (s *sum32a) Sum32() uint32 { return uint32(*s) }
    96  func (s *sum64) Sum64() uint64  { return uint64(*s) }
    97  func (s *sum64a) Sum64() uint64 { return uint64(*s) }
    98  
    99  func (s *sum32) Write(data []byte) (int, error) {
   100  	hash := *s
   101  	for _, c := range data {
   102  		hash *= prime32
   103  		hash ^= sum32(c)
   104  	}
   105  	*s = hash
   106  	return len(data), nil
   107  }
   108  
   109  func (s *sum32a) Write(data []byte) (int, error) {
   110  	hash := *s
   111  	for _, c := range data {
   112  		hash ^= sum32a(c)
   113  		hash *= prime32
   114  	}
   115  	*s = hash
   116  	return len(data), nil
   117  }
   118  
   119  func (s *sum64) Write(data []byte) (int, error) {
   120  	hash := *s
   121  	for _, c := range data {
   122  		hash *= prime64
   123  		hash ^= sum64(c)
   124  	}
   125  	*s = hash
   126  	return len(data), nil
   127  }
   128  
   129  func (s *sum64a) Write(data []byte) (int, error) {
   130  	hash := *s
   131  	for _, c := range data {
   132  		hash ^= sum64a(c)
   133  		hash *= prime64
   134  	}
   135  	*s = hash
   136  	return len(data), nil
   137  }
   138  
   139  func (s *sum128) Write(data []byte) (int, error) {
   140  	for _, c := range data {
   141  		// Compute the multiplication
   142  		s0, s1 := bits.Mul64(prime128Lower, s[1])
   143  		s0 += s[1]<<prime128Shift + prime128Lower*s[0]
   144  		// Update the values
   145  		s[1] = s1
   146  		s[0] = s0
   147  		s[1] ^= uint64(c)
   148  	}
   149  	return len(data), nil
   150  }
   151  
   152  func (s *sum128a) Write(data []byte) (int, error) {
   153  	for _, c := range data {
   154  		s[1] ^= uint64(c)
   155  		// Compute the multiplication
   156  		s0, s1 := bits.Mul64(prime128Lower, s[1])
   157  		s0 += s[1]<<prime128Shift + prime128Lower*s[0]
   158  		// Update the values
   159  		s[1] = s1
   160  		s[0] = s0
   161  	}
   162  	return len(data), nil
   163  }
   164  
   165  func (s *sum32) Size() int   { return 4 }
   166  func (s *sum32a) Size() int  { return 4 }
   167  func (s *sum64) Size() int   { return 8 }
   168  func (s *sum64a) Size() int  { return 8 }
   169  func (s *sum128) Size() int  { return 16 }
   170  func (s *sum128a) Size() int { return 16 }
   171  
   172  func (s *sum32) BlockSize() int   { return 1 }
   173  func (s *sum32a) BlockSize() int  { return 1 }
   174  func (s *sum64) BlockSize() int   { return 1 }
   175  func (s *sum64a) BlockSize() int  { return 1 }
   176  func (s *sum128) BlockSize() int  { return 1 }
   177  func (s *sum128a) BlockSize() int { return 1 }
   178  
   179  func (s *sum32) Sum(in []byte) []byte {
   180  	v := uint32(*s)
   181  	return append(in, byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
   182  }
   183  
   184  func (s *sum32a) Sum(in []byte) []byte {
   185  	v := uint32(*s)
   186  	return append(in, byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
   187  }
   188  
   189  func (s *sum64) Sum(in []byte) []byte {
   190  	v := uint64(*s)
   191  	return append(in, byte(v>>56), byte(v>>48), byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
   192  }
   193  
   194  func (s *sum64a) Sum(in []byte) []byte {
   195  	v := uint64(*s)
   196  	return append(in, byte(v>>56), byte(v>>48), byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
   197  }
   198  
   199  func (s *sum128) Sum(in []byte) []byte {
   200  	return append(in,
   201  		byte(s[0]>>56), byte(s[0]>>48), byte(s[0]>>40), byte(s[0]>>32), byte(s[0]>>24), byte(s[0]>>16), byte(s[0]>>8), byte(s[0]),
   202  		byte(s[1]>>56), byte(s[1]>>48), byte(s[1]>>40), byte(s[1]>>32), byte(s[1]>>24), byte(s[1]>>16), byte(s[1]>>8), byte(s[1]),
   203  	)
   204  }
   205  
   206  func (s *sum128a) Sum(in []byte) []byte {
   207  	return append(in,
   208  		byte(s[0]>>56), byte(s[0]>>48), byte(s[0]>>40), byte(s[0]>>32), byte(s[0]>>24), byte(s[0]>>16), byte(s[0]>>8), byte(s[0]),
   209  		byte(s[1]>>56), byte(s[1]>>48), byte(s[1]>>40), byte(s[1]>>32), byte(s[1]>>24), byte(s[1]>>16), byte(s[1]>>8), byte(s[1]),
   210  	)
   211  }
   212  
   213  const (
   214  	magic32          = "fnv\x01"
   215  	magic32a         = "fnv\x02"
   216  	magic64          = "fnv\x03"
   217  	magic64a         = "fnv\x04"
   218  	magic128         = "fnv\x05"
   219  	magic128a        = "fnv\x06"
   220  	marshaledSize32  = len(magic32) + 4
   221  	marshaledSize64  = len(magic64) + 8
   222  	marshaledSize128 = len(magic128) + 8*2
   223  )
   224  
   225  func (s *sum32) MarshalBinary() ([]byte, error) {
   226  	b := make([]byte, 0, marshaledSize32)
   227  	b = append(b, magic32...)
   228  	b = appendUint32(b, uint32(*s))
   229  	return b, nil
   230  }
   231  
   232  func (s *sum32a) MarshalBinary() ([]byte, error) {
   233  	b := make([]byte, 0, marshaledSize32)
   234  	b = append(b, magic32a...)
   235  	b = appendUint32(b, uint32(*s))
   236  	return b, nil
   237  }
   238  
   239  func (s *sum64) MarshalBinary() ([]byte, error) {
   240  	b := make([]byte, 0, marshaledSize64)
   241  	b = append(b, magic64...)
   242  	b = appendUint64(b, uint64(*s))
   243  	return b, nil
   244  
   245  }
   246  
   247  func (s *sum64a) MarshalBinary() ([]byte, error) {
   248  	b := make([]byte, 0, marshaledSize64)
   249  	b = append(b, magic64a...)
   250  	b = appendUint64(b, uint64(*s))
   251  	return b, nil
   252  }
   253  
   254  func (s *sum128) MarshalBinary() ([]byte, error) {
   255  	b := make([]byte, 0, marshaledSize128)
   256  	b = append(b, magic128...)
   257  	b = appendUint64(b, s[0])
   258  	b = appendUint64(b, s[1])
   259  	return b, nil
   260  }
   261  
   262  func (s *sum128a) MarshalBinary() ([]byte, error) {
   263  	b := make([]byte, 0, marshaledSize128)
   264  	b = append(b, magic128a...)
   265  	b = appendUint64(b, s[0])
   266  	b = appendUint64(b, s[1])
   267  	return b, nil
   268  }
   269  
   270  func (s *sum32) UnmarshalBinary(b []byte) error {
   271  	if len(b) < len(magic32) || string(b[:len(magic32)]) != magic32 {
   272  		return errors.New("hash/fnv: invalid hash state identifier")
   273  	}
   274  	if len(b) != marshaledSize32 {
   275  		return errors.New("hash/fnv: invalid hash state size")
   276  	}
   277  	*s = sum32(readUint32(b[4:]))
   278  	return nil
   279  }
   280  
   281  func (s *sum32a) UnmarshalBinary(b []byte) error {
   282  	if len(b) < len(magic32a) || string(b[:len(magic32a)]) != magic32a {
   283  		return errors.New("hash/fnv: invalid hash state identifier")
   284  	}
   285  	if len(b) != marshaledSize32 {
   286  		return errors.New("hash/fnv: invalid hash state size")
   287  	}
   288  	*s = sum32a(readUint32(b[4:]))
   289  	return nil
   290  }
   291  
   292  func (s *sum64) UnmarshalBinary(b []byte) error {
   293  	if len(b) < len(magic64) || string(b[:len(magic64)]) != magic64 {
   294  		return errors.New("hash/fnv: invalid hash state identifier")
   295  	}
   296  	if len(b) != marshaledSize64 {
   297  		return errors.New("hash/fnv: invalid hash state size")
   298  	}
   299  	*s = sum64(readUint64(b[4:]))
   300  	return nil
   301  }
   302  
   303  func (s *sum64a) UnmarshalBinary(b []byte) error {
   304  	if len(b) < len(magic64a) || string(b[:len(magic64a)]) != magic64a {
   305  		return errors.New("hash/fnv: invalid hash state identifier")
   306  	}
   307  	if len(b) != marshaledSize64 {
   308  		return errors.New("hash/fnv: invalid hash state size")
   309  	}
   310  	*s = sum64a(readUint64(b[4:]))
   311  	return nil
   312  }
   313  
   314  func (s *sum128) UnmarshalBinary(b []byte) error {
   315  	if len(b) < len(magic128) || string(b[:len(magic128)]) != magic128 {
   316  		return errors.New("hash/fnv: invalid hash state identifier")
   317  	}
   318  	if len(b) != marshaledSize128 {
   319  		return errors.New("hash/fnv: invalid hash state size")
   320  	}
   321  	s[0] = readUint64(b[4:])
   322  	s[1] = readUint64(b[12:])
   323  	return nil
   324  }
   325  
   326  func (s *sum128a) UnmarshalBinary(b []byte) error {
   327  	if len(b) < len(magic128a) || string(b[:len(magic128a)]) != magic128a {
   328  		return errors.New("hash/fnv: invalid hash state identifier")
   329  	}
   330  	if len(b) != marshaledSize128 {
   331  		return errors.New("hash/fnv: invalid hash state size")
   332  	}
   333  	s[0] = readUint64(b[4:])
   334  	s[1] = readUint64(b[12:])
   335  	return nil
   336  }
   337  
   338  func readUint32(b []byte) uint32 {
   339  	_ = b[3]
   340  	return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
   341  }
   342  
   343  func appendUint32(b []byte, x uint32) []byte {
   344  	a := [4]byte{
   345  		byte(x >> 24),
   346  		byte(x >> 16),
   347  		byte(x >> 8),
   348  		byte(x),
   349  	}
   350  	return append(b, a[:]...)
   351  }
   352  
   353  func appendUint64(b []byte, x uint64) []byte {
   354  	a := [8]byte{
   355  		byte(x >> 56),
   356  		byte(x >> 48),
   357  		byte(x >> 40),
   358  		byte(x >> 32),
   359  		byte(x >> 24),
   360  		byte(x >> 16),
   361  		byte(x >> 8),
   362  		byte(x),
   363  	}
   364  	return append(b, a[:]...)
   365  }
   366  
   367  func readUint64(b []byte) uint64 {
   368  	_ = b[7]
   369  	return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
   370  		uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
   371  }
   372  

View as plain text