doublecmd/components/dcpcrypt/Hashes/dccrc32.pp

143 lines
4.5 KiB
ObjectPascal

{
Double Commander
-------------------------------------------------------------------------
Fast CRC32 calculation algorithm
http://create.stephan-brumme.com/crc32
Copyright (C) 2011-2015 Stephan Brumme. All rights reserved.
Slicing-by-16 contributed by Bulat Ziganshin
See http://create.stephan-brumme.com/disclaimer.html
Pascal tranlastion
Copyright (C) 2015 Alexander Koblov (alexx2000@mail.ru)
This software is provided 'as-is', without any express or implied warranty.
In no event will the author be held liable for any damages arising from the
use of this software. Permission is granted to anyone to use this software
for any purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software.
2. If you use this software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
3. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
}
unit DCcrc32;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils;
procedure crc32_init;
function crc32_16bytes(const data: PByte; length: Integer; previousCrc32: Cardinal = 0): Cardinal;
implementation
{$R-}{$Q-}
const
/// zlib's CRC32 polynomial
Polynomial: Cardinal = $EDB88320;
var
HaveTable: Boolean = False;
Crc32Lookup: array[0..15, 0..255] of Cardinal;
procedure crc32_init;
var
i, j: Integer;
crc: Cardinal;
slice: Integer;
begin
if HaveTable then Exit;
//// same algorithm as crc32_bitwise
for i := 0 to $FF do
begin
crc := Cardinal(i);
for j := 0 to 7 do
begin
if (crc and 1) <> 0 then
crc := Polynomial xor (crc shr 1)
else
crc := (crc shr 1);
end;
Crc32Lookup[0][i] := crc;
end;
// ... and the following slicing-by-8 algorithm (from Intel):
// http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf
// http://sourceforge.net/projects/slicing-by-8/
for i := 0 to $FF do
begin
for slice := 1 to 15 do
Crc32Lookup[slice][i] := (Crc32Lookup[slice - 1][i] shr 8) xor Crc32Lookup[0][Crc32Lookup[slice - 1][i] and $FF];
end;
HaveTable:= True;
end;
/// compute CRC32 (Slicing-by-16 algorithm)
function crc32_16bytes(const data: PByte; length: Integer; previousCrc32: Cardinal = 0): Cardinal;
const
Unroll = 4;
BytesAtOnce = 16 * Unroll;
var
crc: cardinal;
unrolling: integer;
current: PLongWord;
currentChar: PByte;
one, two, three, four: cardinal;
begin
crc := previousCrc32 xor $FFFFFFFF;
current := PLongWord(data);
// enabling optimization (at least -O2) automatically unrolls the inner for-loop
while (length >= BytesAtOnce) do
begin
for unrolling := 0 to Unroll - 1 do
begin
one := current^ xor crc; Inc(current);
two := current^; Inc(current);
three := current^; Inc(current);
four := current^; Inc(current);
crc := Crc32Lookup[ 0][(four shr 24) and $FF] xor
Crc32Lookup[ 1][(four shr 16) and $FF] xor
Crc32Lookup[ 2][(four shr 8) and $FF] xor
Crc32Lookup[ 3][ four and $FF] xor
Crc32Lookup[ 4][(three shr 24) and $FF] xor
Crc32Lookup[ 5][(three shr 16) and $FF] xor
Crc32Lookup[ 6][(three shr 8) and $FF] xor
Crc32Lookup[ 7][ three and $FF] xor
Crc32Lookup[ 8][(two shr 24) and $FF] xor
Crc32Lookup[ 9][(two shr 16) and $FF] xor
Crc32Lookup[10][(two shr 8) and $FF] xor
Crc32Lookup[11][ two and $FF] xor
Crc32Lookup[12][(one shr 24) and $FF] xor
Crc32Lookup[13][(one shr 16) and $FF] xor
Crc32Lookup[14][(one shr 8) and $FF] xor
Crc32Lookup[15][ one and $FF];
end;
length -= BytesAtOnce;
end;
currentChar := PByte(current);
// remaining 1 to 63 bytes (standard algorithm)
while (length <> 0) do
begin
crc := (crc shr 8) xor Crc32Lookup[0][(crc and $FF) xor currentChar^];
Inc(currentChar);
Dec(length);
end;
Result:= crc xor $FFFFFFFF;
end;
end.