crc32_generic.go 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  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. // This file contains CRC32 algorithms that are not specific to any architecture
  5. // and don't use hardware acceleration.
  6. //
  7. // The simple (and slow) CRC32 implementation only uses a 256*4 bytes table.
  8. //
  9. // The slicing-by-8 algorithm is a faster implementation that uses a bigger
  10. // table (8*256*4 bytes).
  11. package crc32
  12. // simpleMakeTable allocates and constructs a Table for the specified
  13. // polynomial. The table is suitable for use with the simple algorithm
  14. // (simpleUpdate).
  15. func simpleMakeTable(poly uint32) *Table {
  16. t := new(Table)
  17. simplePopulateTable(poly, t)
  18. return t
  19. }
  20. // simplePopulateTable constructs a Table for the specified polynomial, suitable
  21. // for use with simpleUpdate.
  22. func simplePopulateTable(poly uint32, t *Table) {
  23. for i := 0; i < 256; i++ {
  24. crc := uint32(i)
  25. for j := 0; j < 8; j++ {
  26. if crc&1 == 1 {
  27. crc = (crc >> 1) ^ poly
  28. } else {
  29. crc >>= 1
  30. }
  31. }
  32. t[i] = crc
  33. }
  34. }
  35. // simpleUpdate uses the simple algorithm to update the CRC, given a table that
  36. // was previously computed using simpleMakeTable.
  37. func simpleUpdate(crc uint32, tab *Table, p []byte) uint32 {
  38. crc = ^crc
  39. for _, v := range p {
  40. crc = tab[byte(crc)^v] ^ (crc >> 8)
  41. }
  42. return ^crc
  43. }
  44. // Use slicing-by-8 when payload >= this value.
  45. const slicing8Cutoff = 16
  46. // slicing8Table is array of 8 Tables, used by the slicing-by-8 algorithm.
  47. type slicing8Table [8]Table
  48. // slicingMakeTable constructs a slicing8Table for the specified polynomial. The
  49. // table is suitable for use with the slicing-by-8 algorithm (slicingUpdate).
  50. func slicingMakeTable(poly uint32) *slicing8Table {
  51. t := new(slicing8Table)
  52. simplePopulateTable(poly, &t[0])
  53. for i := 0; i < 256; i++ {
  54. crc := t[0][i]
  55. for j := 1; j < 8; j++ {
  56. crc = t[0][crc&0xFF] ^ (crc >> 8)
  57. t[j][i] = crc
  58. }
  59. }
  60. return t
  61. }
  62. // slicingUpdate uses the slicing-by-8 algorithm to update the CRC, given a
  63. // table that was previously computed using slicingMakeTable.
  64. func slicingUpdate(crc uint32, tab *slicing8Table, p []byte) uint32 {
  65. if len(p) >= slicing8Cutoff {
  66. crc = ^crc
  67. for len(p) > 8 {
  68. crc ^= uint32(p[0]) | uint32(p[1])<<8 | uint32(p[2])<<16 | uint32(p[3])<<24
  69. crc = tab[0][p[7]] ^ tab[1][p[6]] ^ tab[2][p[5]] ^ tab[3][p[4]] ^
  70. tab[4][crc>>24] ^ tab[5][(crc>>16)&0xFF] ^
  71. tab[6][(crc>>8)&0xFF] ^ tab[7][crc&0xFF]
  72. p = p[8:]
  73. }
  74. crc = ^crc
  75. }
  76. if len(p) == 0 {
  77. return crc
  78. }
  79. return simpleUpdate(crc, &tab[0], p)
  80. }