crc.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. // This CRC function is based on Intel Slicing-by-8 algorithm.
  2. //
  3. // Original Intel Slicing-by-8 code is available here:
  4. //
  5. // http://sourceforge.net/projects/slicing-by-8/
  6. //
  7. // Original Intel Slicing-by-8 code is licensed as:
  8. //
  9. // Copyright (c) 2004-2006 Intel Corporation - All Rights Reserved
  10. //
  11. // This software program is licensed subject to the BSD License,
  12. // available at http://www.opensource.org/licenses/bsd-license.html
  13. #include "rar.hpp"
  14. #ifndef SFX_MODULE
  15. // User suggested to avoid BSD license in SFX module, so they do not need
  16. // to include the license to SFX archive.
  17. #define USE_SLICING
  18. #endif
  19. static uint crc_tables[8][256]; // Tables for Slicing-by-8.
  20. // Build the classic CRC32 lookup table.
  21. // We also provide this function to legacy RAR and ZIP decryption code.
  22. void InitCRC32(uint *CRCTab)
  23. {
  24. if (CRCTab[1]!=0)
  25. return;
  26. for (uint I=0;I<256;I++)
  27. {
  28. uint C=I;
  29. for (uint J=0;J<8;J++)
  30. C=(C & 1) ? (C>>1)^0xEDB88320 : (C>>1);
  31. CRCTab[I]=C;
  32. }
  33. }
  34. static void InitTables()
  35. {
  36. InitCRC32(crc_tables[0]);
  37. #ifdef USE_SLICING
  38. for (uint I=0;I<256;I++) // Build additional lookup tables.
  39. {
  40. uint C=crc_tables[0][I];
  41. for (uint J=1;J<8;J++)
  42. {
  43. C=crc_tables[0][(byte)C]^(C>>8);
  44. crc_tables[J][I]=C;
  45. }
  46. }
  47. #endif
  48. }
  49. struct CallInitCRC {CallInitCRC() {InitTables();}} static CallInit32;
  50. uint CRC32(uint StartCRC,const void *Addr,size_t Size)
  51. {
  52. byte *Data=(byte *)Addr;
  53. #ifdef USE_SLICING
  54. // Align Data to 8 for better performance.
  55. for (;Size>0 && ((size_t)Data & 7);Size--,Data++)
  56. StartCRC=crc_tables[0][(byte)(StartCRC^Data[0])]^(StartCRC>>8);
  57. for (;Size>=8;Size-=8,Data+=8)
  58. {
  59. #ifdef BIG_ENDIAN
  60. StartCRC ^= Data[0]|(Data[1] << 8)|(Data[2] << 16)|(Data[3] << 24);
  61. uint NextData = Data[4]|(Data[5] << 8)|(Data[6] << 16)|(Data[7] << 24);
  62. #else
  63. StartCRC ^= *(uint32 *) Data;
  64. uint NextData = *(uint32 *) (Data+4);
  65. #endif
  66. StartCRC = crc_tables[7][(byte) StartCRC ] ^
  67. crc_tables[6][(byte)(StartCRC >> 8) ] ^
  68. crc_tables[5][(byte)(StartCRC >> 16)] ^
  69. crc_tables[4][(byte)(StartCRC >> 24)] ^
  70. crc_tables[3][(byte) NextData ] ^
  71. crc_tables[2][(byte)(NextData >> 8) ] ^
  72. crc_tables[1][(byte)(NextData >> 16)] ^
  73. crc_tables[0][(byte)(NextData >> 24)];
  74. }
  75. #endif
  76. for (;Size>0;Size--,Data++) // Process left data.
  77. StartCRC=crc_tables[0][(byte)(StartCRC^Data[0])]^(StartCRC>>8);
  78. return StartCRC;
  79. }
  80. #ifndef SFX_MODULE
  81. // For RAR 1.4 archives in case somebody still has them.
  82. ushort Checksum14(ushort StartCRC,const void *Addr,size_t Size)
  83. {
  84. byte *Data=(byte *)Addr;
  85. for (size_t I=0;I<Size;I++)
  86. {
  87. StartCRC=(StartCRC+Data[I])&0xffff;
  88. StartCRC=((StartCRC<<1)|(StartCRC>>15))&0xffff;
  89. }
  90. return StartCRC;
  91. }
  92. #endif