{$MODE FPC}
{$MODESWITCH DEFAULTPARAMETERS}
{$MODESWITCH OUT}
{$MODESWITCH RESULT}
unit dcrc32_table;

interface

//
//  GenerateCrc32Table
//
//      Calculates CRC-32 lookup-table.
//
//  Parameters:
//
//      PolyReversed: reversed polynomial representation
//      Table: pointer to 256 Cardinals for storing calculated table.
//             Content of the table before the function call does not matter.
//
//  Returns:
//
//      Table: colculated table
//
procedure GenerateCrc32Table(PolyReversed: Cardinal; Table: PCardinal);

//
//  AccumulateCrc32
//
//      Calculates CRC-32 checksum for next portion of data.
//
//  Parameters:
//
//      Checksum: current checksum
//      Table: CRC-32 lookup table with 256 Cardinals generated by
//             GenerateCrc32Table
//      P: start of the data
//      Size: size of the data
//      PEnd: end of the data, that is PEnd=P+Size
//
//  Returns:
//
//      Result: updated checksum
//
function AccumulateCrc32(Checksum: Cardinal; Table: PCardinal; P: Pointer; Size: SizeUInt): Cardinal; inline;
function AccumulateCrc32(Checksum: Cardinal; Table: PCardinal; P, PEnd: Pointer): Cardinal;

implementation

procedure GenerateCrc32Table(PolyReversed: Cardinal; Table: PCardinal);
var
  Crc, I, J: Cardinal;
begin
  for I := 0 to 255 do begin
    Crc := I;
    for J := 8 downto 1 do begin
      if (Crc and 1) <> 0 then begin
        Crc := (Crc shr 1) xor PolyReversed;
      end else begin
        Crc := Crc shr 1;
      end;
    end;
    Table^ := Crc;
    Inc(Table);
  end;
end;

function AccumulateCrc32(Checksum: Cardinal; Table: PCardinal; P: Pointer; Size: SizeUInt): Cardinal;
begin
  Result := AccumulateCrc32(Checksum, Table, P, P + Size);
end;

function AccumulateCrc32(Checksum: Cardinal; Table: PCardinal; P, PEnd: Pointer): Cardinal;
begin
  Result := Checksum;
  while P < PEnd do begin
    Result := (Result shr 8) xor Table[(Result xor Byte(P^)) and $FF];
    Inc(P);
  end;
end;

end.
