mirror of
https://github.com/doublecmd/doublecmd.git
synced 2026-06-21 09:58:13 +00:00
143 lines
4.5 KiB
ObjectPascal
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.
|
|
|