113 lines
2.8 KiB
C++
113 lines
2.8 KiB
C++
// This CRC function is based on Intel Slicing-by-8 algorithm.
|
|
//
|
|
// Original Intel Slicing-by-8 code is available here:
|
|
//
|
|
// http://sourceforge.net/projects/slicing-by-8/
|
|
//
|
|
// Original Intel Slicing-by-8 code is licensed as:
|
|
//
|
|
// Copyright (c) 2004-2006 Intel Corporation - All Rights Reserved
|
|
//
|
|
// This software program is licensed subject to the BSD License,
|
|
// available at http://www.opensource.org/licenses/bsd-license.html
|
|
|
|
|
|
#include "rar.hpp"
|
|
|
|
#ifndef SFX_MODULE
|
|
// User suggested to avoid BSD license in SFX module, so they do not need
|
|
// to include the license to SFX archive.
|
|
#define USE_SLICING
|
|
#endif
|
|
|
|
static uint crc_tables[8][256]; // Tables for Slicing-by-8.
|
|
|
|
|
|
// Build the classic CRC32 lookup table.
|
|
// We also provide this function to legacy RAR and ZIP decryption code.
|
|
void InitCRC32(uint *CRCTab)
|
|
{
|
|
if (CRCTab[1]!=0)
|
|
return;
|
|
for (uint I=0;I<256;I++)
|
|
{
|
|
uint C=I;
|
|
for (uint J=0;J<8;J++)
|
|
C=(C & 1) ? (C>>1)^0xEDB88320 : (C>>1);
|
|
CRCTab[I]=C;
|
|
}
|
|
}
|
|
|
|
|
|
static void InitTables()
|
|
{
|
|
InitCRC32(crc_tables[0]);
|
|
|
|
#ifdef USE_SLICING
|
|
for (uint I=0;I<256;I++) // Build additional lookup tables.
|
|
{
|
|
uint C=crc_tables[0][I];
|
|
for (uint J=1;J<8;J++)
|
|
{
|
|
C=crc_tables[0][(byte)C]^(C>>8);
|
|
crc_tables[J][I]=C;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
struct CallInitCRC {CallInitCRC() {InitTables();}} static CallInit32;
|
|
|
|
uint CRC32(uint StartCRC,const void *Addr,size_t Size)
|
|
{
|
|
byte *Data=(byte *)Addr;
|
|
|
|
#ifdef USE_SLICING
|
|
// Align Data to 8 for better performance.
|
|
for (;Size>0 && ((size_t)Data & 7);Size--,Data++)
|
|
StartCRC=crc_tables[0][(byte)(StartCRC^Data[0])]^(StartCRC>>8);
|
|
|
|
for (;Size>=8;Size-=8,Data+=8)
|
|
{
|
|
#ifdef BIG_ENDIAN
|
|
StartCRC ^= Data[0]|(Data[1] << 8)|(Data[2] << 16)|(Data[3] << 24);
|
|
uint NextData = Data[4]|(Data[5] << 8)|(Data[6] << 16)|(Data[7] << 24);
|
|
#else
|
|
StartCRC ^= *(uint32 *) Data;
|
|
uint NextData = *(uint32 *) (Data+4);
|
|
#endif
|
|
StartCRC = crc_tables[7][(byte) StartCRC ] ^
|
|
crc_tables[6][(byte)(StartCRC >> 8) ] ^
|
|
crc_tables[5][(byte)(StartCRC >> 16)] ^
|
|
crc_tables[4][(byte)(StartCRC >> 24)] ^
|
|
crc_tables[3][(byte) NextData ] ^
|
|
crc_tables[2][(byte)(NextData >> 8) ] ^
|
|
crc_tables[1][(byte)(NextData >> 16)] ^
|
|
crc_tables[0][(byte)(NextData >> 24)];
|
|
}
|
|
#endif
|
|
|
|
for (;Size>0;Size--,Data++) // Process left data.
|
|
StartCRC=crc_tables[0][(byte)(StartCRC^Data[0])]^(StartCRC>>8);
|
|
|
|
return StartCRC;
|
|
}
|
|
|
|
|
|
#ifndef SFX_MODULE
|
|
// For RAR 1.4 archives in case somebody still has them.
|
|
ushort Checksum14(ushort StartCRC,const void *Addr,size_t Size)
|
|
{
|
|
byte *Data=(byte *)Addr;
|
|
for (size_t I=0;I<Size;I++)
|
|
{
|
|
StartCRC=(StartCRC+Data[I])&0xffff;
|
|
StartCRC=((StartCRC<<1)|(StartCRC>>15))&0xffff;
|
|
}
|
|
return StartCRC;
|
|
}
|
|
#endif
|
|
|
|
|