Home | History | Annotate | Download | only in crc64
      1 // Copyright 2009 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 crc64 implements the 64-bit cyclic redundancy check, or CRC-64,
      6 // checksum. See http://en.wikipedia.org/wiki/Cyclic_redundancy_check for
      7 // information.
      8 package crc64
      9 
     10 import "hash"
     11 
     12 // The size of a CRC-64 checksum in bytes.
     13 const Size = 8
     14 
     15 // Predefined polynomials.
     16 const (
     17 	// The ISO polynomial, defined in ISO 3309 and used in HDLC.
     18 	ISO = 0xD800000000000000
     19 
     20 	// The ECMA polynomial, defined in ECMA 182.
     21 	ECMA = 0xC96C5795D7870F42
     22 )
     23 
     24 // Table is a 256-word table representing the polynomial for efficient processing.
     25 type Table [256]uint64
     26 
     27 // MakeTable returns the Table constructed from the specified polynomial.
     28 func MakeTable(poly uint64) *Table {
     29 	t := new(Table)
     30 	for i := 0; i < 256; i++ {
     31 		crc := uint64(i)
     32 		for j := 0; j < 8; j++ {
     33 			if crc&1 == 1 {
     34 				crc = (crc >> 1) ^ poly
     35 			} else {
     36 				crc >>= 1
     37 			}
     38 		}
     39 		t[i] = crc
     40 	}
     41 	return t
     42 }
     43 
     44 // digest represents the partial evaluation of a checksum.
     45 type digest struct {
     46 	crc uint64
     47 	tab *Table
     48 }
     49 
     50 // New creates a new hash.Hash64 computing the CRC-64 checksum
     51 // using the polynomial represented by the Table.
     52 func New(tab *Table) hash.Hash64 { return &digest{0, tab} }
     53 
     54 func (d *digest) Size() int { return Size }
     55 
     56 func (d *digest) BlockSize() int { return 1 }
     57 
     58 func (d *digest) Reset() { d.crc = 0 }
     59 
     60 func update(crc uint64, tab *Table, p []byte) uint64 {
     61 	crc = ^crc
     62 	for _, v := range p {
     63 		crc = tab[byte(crc)^v] ^ (crc >> 8)
     64 	}
     65 	return ^crc
     66 }
     67 
     68 // Update returns the result of adding the bytes in p to the crc.
     69 func Update(crc uint64, tab *Table, p []byte) uint64 {
     70 	return update(crc, tab, p)
     71 }
     72 
     73 func (d *digest) Write(p []byte) (n int, err error) {
     74 	d.crc = update(d.crc, d.tab, p)
     75 	return len(p), nil
     76 }
     77 
     78 func (d *digest) Sum64() uint64 { return d.crc }
     79 
     80 func (d *digest) Sum(in []byte) []byte {
     81 	s := d.Sum64()
     82 	return append(in, byte(s>>56), byte(s>>48), byte(s>>40), byte(s>>32), byte(s>>24), byte(s>>16), byte(s>>8), byte(s))
     83 }
     84 
     85 // Checksum returns the CRC-64 checksum of data
     86 // using the polynomial represented by the Table.
     87 func Checksum(data []byte, tab *Table) uint64 { return update(0, tab, data) }
     88