crc32_fast.c 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. /// \file crc32.c
  4. /// \brief CRC32 calculation
  5. ///
  6. /// Calculate the CRC32 using the slice-by-eight algorithm.
  7. /// It is explained in this document:
  8. /// http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf
  9. /// The code in this file is not the same as in Intel's paper, but
  10. /// the basic principle is identical.
  11. //
  12. // Author: Lasse Collin
  13. //
  14. // This file has been put into the public domain.
  15. // You can do whatever you want with this file.
  16. //
  17. ///////////////////////////////////////////////////////////////////////////////
  18. #include "check.h"
  19. #include "crc_macros.h"
  20. // If you make any changes, do some benchmarking! Seemingly unrelated
  21. // changes can very easily ruin the performance (and very probably is
  22. // very compiler dependent).
  23. extern LZMA_API(uint32_t)
  24. lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc)
  25. {
  26. crc = ~crc;
  27. #ifdef WORDS_BIGENDIAN
  28. crc = bswap32(crc);
  29. #endif
  30. if (size > 8) {
  31. // Fix the alignment, if needed. The if statement above
  32. // ensures that this won't read past the end of buf[].
  33. while ((uintptr_t)(buf) & 7) {
  34. crc = lzma_crc32_table[0][*buf++ ^ A(crc)] ^ S8(crc);
  35. --size;
  36. }
  37. // Calculate the position where to stop.
  38. const uint8_t *const limit = buf + (size & ~(size_t)(7));
  39. // Calculate how many bytes must be calculated separately
  40. // before returning the result.
  41. size &= (size_t)(7);
  42. // Calculate the CRC32 using the slice-by-eight algorithm.
  43. while (buf < limit) {
  44. crc ^= aligned_read32ne(buf);
  45. buf += 4;
  46. crc = lzma_crc32_table[7][A(crc)]
  47. ^ lzma_crc32_table[6][B(crc)]
  48. ^ lzma_crc32_table[5][C(crc)]
  49. ^ lzma_crc32_table[4][D(crc)];
  50. const uint32_t tmp = aligned_read32ne(buf);
  51. buf += 4;
  52. // At least with some compilers, it is critical for
  53. // performance, that the crc variable is XORed
  54. // between the two table-lookup pairs.
  55. crc = lzma_crc32_table[3][A(tmp)]
  56. ^ lzma_crc32_table[2][B(tmp)]
  57. ^ crc
  58. ^ lzma_crc32_table[1][C(tmp)]
  59. ^ lzma_crc32_table[0][D(tmp)];
  60. }
  61. }
  62. while (size-- != 0)
  63. crc = lzma_crc32_table[0][*buf++ ^ A(crc)] ^ S8(crc);
  64. #ifdef WORDS_BIGENDIAN
  65. crc = bswap32(crc);
  66. #endif
  67. return ~crc;
  68. }