decoder
alarming
autosfx
aysalia
calllib
checksum-tools
colormanager
cryptochat
currency_converter
delphiutils
distributed
dpcstudio
dpg2
fastphp
fileformats
filter_foundry
forest
gridgame
ht46f47_simulator
indexer_suite
ipe_artfile_utils
javautils
jumper
lightgame
logviewer
musikbox
mystic_house
oidconverter
oidinfo_api
oidinfo_new_design
oidplus
personal-webbase
php_antispam
php_clientchallenge
php_guestbook
php_utils
plumbers
prepend
recyclebinunit
simple_log_event
sokoban
spacemission
stackman
userdetect2
uuid_mac_utils
vgwhois
vnag
webcounter
winbugtracker
yt_downloader
BlueGrey
calm
Elegant
Català-Valencià – Catalan
中文 – Chinese (Simplified)
中文 – Chinese (Traditional)
Česky – Czech
Dansk – Danish
Nederlands – Dutch
English – English
Suomi – Finnish
Français – French
Deutsch – German
עברית – Hebrew
हिंदी – Hindi
Magyar – Hungarian
Bahasa Indonesia – Indonesian
Italiano – Italian
日本語 – Japanese
한국어 – Korean
Македонски – Macedonian
मराठी – Marathi
Norsk – Norwegian
Polski – Polish
Português – Portuguese
Português – Portuguese (Brazil)
Русский – Russian
Slovenčina – Slovak
Slovenščina – Slovenian
Español – Spanish
Svenska – Swedish
Türkçe – Turkish
Українська – Ukrainian
Oëzbekcha – Uzbek
Subversion Repositories
decoder
decoder
/
trunk
/
VCL_DEC
/
CRC.pas
– Rev 2
Rev
Blame
|
Last modification
|
View Log
|
RSS feed
{Copyright: Hagen Reddmann HaReddmann at T-Online dot de
Author: Hagen Reddmann
Remarks: Public Domain, this Copyright must be included
known Problems: none
Version: 5.1, Delphi Encryption Compendium
Delphi 2-7, BCB 3-4, designed and testet under D3-7
Description: threadsafe CRC Checksum functions as single unit.
Implementation of Cyclic Redundance Checking.
Supports ALL possible CRC's, per default are follow
Standard CRC's supported:
CRC-8, CRC-10, CRC-12 (Mobil Telephone),
CRC-16, CRC-16-CCITT, CRC-16-ZModem,
CRC-24 (PGP's MIME64 Armor CRC),
CRC-32, CRC-32-CCITT and CRC-32-ZModem.
Remarks:
- this unit should be fully PIC safe, means Kylix compatible
- this unit consume only 728 - max. 952 Bytes code if all functions are used
- 2 * 4 Bytes in Datasegment (BSS) are used
- on runtime it need two memoryblocks of size 2x1056 bytes if
CRC16() and CRC32() are called, if none of both is used no memory are need
- on multithread application and the use of CRC16() or CRC32() You should call
CRCInitThreadSafe at initialization of the application or before threaded
use of CRC16() or CRC32().
- yes, we could it realy more speedup, as example loop unrolling, but then the
code grows and i wanted a good compromiss between speed and size.
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
}
unit
CRC
;
{$I VER.INC}
interface
type
// CRC Definitions Structure
PCRCDef
=
^
TCRCDef
;
TCRCDef
=
packed
record
// don't reorder or change this structure
Table
:
array
[
0
..
255
]
of
Cardinal
;
// Lookuptable, precomputed in CRCSetup
CRC
:
Cardinal
;
// intermediate CRC
Inverse
:
LongBool
;
// is this Polynomial a inverse function
Shift
:
Cardinal
;
// Shift Value for CRCCode, more speed
InitVector
:
Cardinal
;
// Startvalue of CRC Computation
FinalVector
:
Cardinal
;
// final XOR Vector of computed CRC
Mask
:
Cardinal
;
// precomputed AND Mask of computed CRC
Bits
:
Cardinal
;
// Bitsize of CRC
Polynomial
:
Cardinal
;
// used Polynomial
end
;
// SizeOf(TCRCDef) = 1056 = 0420h
// predefined Standard CRC Types
TCRCType
=
(
CRC_8
,
CRC_10
,
CRC_12
,
CRC_16
,
CRC_16CCITT
,
CRC_16XModem
,
CRC_24
,
CRC_32
,
CRC_32CCITT
,
CRC_32ZModem
)
;
type
TReadMethod
=
function
(
var
Buffer
;
Count
:
LongInt
)
:
LongInt
of
object
;
// calculates a CRC over Buffer with Size Bytes Length, used Algo in CRCType, all is done in one Step
function
CRCCalc
(
CRCType
:
TCRCType
;
const
Buffer
;
Size
:
Cardinal
)
:
Cardinal
;
// use a callback
function
CRCCalcEx
(
CRCType
:
TCRCType
;
ReadMethod
:
TReadMethod
;
Size
:
Cardinal
{$IFDEF VER_D4H} = $FFFFFFFF{$ENDIF}
)
:
Cardinal
;
// initialize CRC Definition with CRCType Standard CRC
function
CRCInit
(
var
CRCDef
:
TCRCDef
;
CRCType
:
TCRCType
)
:
Boolean
;
// initilaize CRC Definition with a custom Algorithm
function
CRCSetup
(
var
CRCDef
:
TCRCDef
;
Polynomial
,
Bits
,
InitVector
,
FinalVector
:
Cardinal
;
Inverse
:
LongBool
)
:
Boolean
;
// process over Buffer with Size Bytes Length a CRC definied in CRCDef.
// Result is actual computed CRC with correction, same as CRCDone(),
// CRCDef.CRC holds the actual computed CRC, a second/more call to CRCCode
// computes than both/more buffers as one buffer.
function
CRCCode
(
var
CRCDef
:
TCRCDef
;
const
Buffer
;
Size
:
Cardinal
)
:
Cardinal
;
// use a callback, eg. TStream.Read(). I hate D4 because ther don't love here overloaded procedures
function
CRCCodeEx
(
var
CRCDef
:
TCRCDef
;
ReadMethod
:
TReadMethod
;
Size
:
Cardinal
{$IFDEF VER_D4H} = $FFFFFFFF{$ENDIF}
)
:
Cardinal
;
// retruns corrected CRC as definied in CRCDef, and reset CRCDef.CRC to InitVector
function
CRCDone
(
var
CRCDef
:
TCRCDef
)
:
Cardinal
;
// predefined CRC16-Standard, call CRC := CRC16(0, Data, SizeOf(Data));
function
CRC16
(
CRC
:
Word
;
const
Buffer
;
Size
:
Cardinal
)
:
Word
;
// predefined CRC32-CCITT, call CRC := CRC32(0, Data, SizeOf(Data));
function
CRC32
(
CRC
:
Cardinal
;
const
Buffer
;
Size
:
Cardinal
)
:
Cardinal
;
// make it threadsafe
procedure
CRCInitThreadSafe
;
{ how to use:
var
CRC16: Word;
begin
CRC16 := CRCCalc(CRC_16, Data, SizeOf(Data)); // all in one
end;
var
CRC: TCRCDef;
CRC32: Cardinal;
begin
CRCInit(CRC, CRC_32); // setup CRC data structure
CRCCode(CRC, Data, SizeOf(Data)); // returns correct CRC32 for this Data
CRCCode(CRC, PChar(String)^, Length(String)); // returns correct CRC32 for String AND CRC.CRC holds intermediate
CRC32 := CRCDone(CRC); // returns correct CRC32 for Data + String
// after CRCDone we can restart a new calculation
end;
above examples are fully threadsafe and requiere ~ $0420 Bytes Stackspace.
}
implementation
function
CRCSetup
(
var
CRCDef
:
TCRCDef
;
Polynomial
,
Bits
,
InitVector
,
FinalVector
:
Cardinal
;
Inverse
:
LongBool
)
:
Boolean
;
register
;
asm
// initialize CRCDef according to the parameters, calculate the lookup table
CMP ECX
,
8
JB
@@
8
PUSH EBX
PUSH EDI
PUSH ESI
MOV
[
EAX
]
.
TCRCDef
.
Polynomial
,
EDX
MOV
[
EAX
]
.
TCRCDef
.
Bits
,
ECX
MOV EBX
,
InitVector
MOV EDI
,
FinalVector
MOV ESI
,
Inverse
MOV
[
EAX
]
.
TCRCDef
.
CRC
,
EBX
MOV
[
EAX
]
.
TCRCDef
.
InitVector
,
EBX
MOV
[
EAX
]
.
TCRCDef
.
FinalVector
,
EDI
MOV
[
EAX
]
.
TCRCDef
.
Inverse
,
ESI
XOR
EDI
,
EDI
LEA EBX
,
[
ECX
-
8
]
SUB ECX
,
32
DEC EDI
NEG ECX
SHR
EDI
,
CL
MOV
[
EAX
]
.
TCRCDef
.
Shift
,
EBX
MOV
[
EAX
]
.
TCRCDef
.
Mask
,
EDI
TEST ESI
,
ESI
JZ
@@
5
XOR
EBX
,
EBX
MOV ECX
,
[
EAX
]
.
TCRCDef
.
Bits
@@
1
:
SHR
EDX
,
1
ADC EBX
,
EBX
DEC ECX
JNZ
@@
1
NOP
MOV ECX
,
255
NOP
@@
20
:
MOV EDX
,
ECX
SHR
EDX
,
1
JNC
@@
21
XOR
EDX
,
EBX
@@
21
:
SHR
EDX
,
1
JNC
@@
22
XOR
EDX
,
EBX
@@
22
:
SHR
EDX
,
1
JNC
@@
23
XOR
EDX
,
EBX
@@
23
:
SHR
EDX
,
1
JNC
@@
24
XOR
EDX
,
EBX
@@
24
:
SHR
EDX
,
1
JNC
@@
25
XOR
EDX
,
EBX
@@
25
:
SHR
EDX
,
1
JNC
@@
26
XOR
EDX
,
EBX
@@
26
:
SHR
EDX
,
1
JNC
@@
27
XOR
EDX
,
EBX
@@
27
:
SHR
EDX
,
1
JNC
@@
28
XOR
EDX
,
EBX
@@
28
:
MOV
[
EAX
+
ECX
*
4
]
,
EDX
DEC ECX
JNL
@@
20
JMP
@@
7
@@
5
:
AND
EDX
,
EDI
ROL EDX
,
CL
MOV EBX
,
255
// can be coded branchfree
@@
60
:
MOV ESI
,
EBX
SHL
ESI
,
25
JNC
@@
61
XOR
ESI
,
EDX
@@
61
:
ADD ESI
,
ESI
JNC
@@
62
XOR
ESI
,
EDX
@@
62
:
ADD ESI
,
ESI
JNC
@@
63
XOR
ESI
,
EDX
@@
63
:
ADD ESI
,
ESI
JNC
@@
64
XOR
ESI
,
EDX
@@
64
:
ADD ESI
,
ESI
JNC
@@
65
XOR
ESI
,
EDX
@@
65
:
ADD ESI
,
ESI
JNC
@@
66
XOR
ESI
,
EDX
@@
66
:
ADD ESI
,
ESI
JNC
@@
67
XOR
ESI
,
EDX
@@
67
:
ADD ESI
,
ESI
JNC
@@
68
XOR
ESI
,
EDX
@@
68
:
ROR ESI
,
CL
MOV
[
EAX
+
EBX
*
4
]
,
ESI
DEC EBX
JNL
@@
60
@@
7
:
POP ESI
POP EDI
POP EBX
@@
8
:
CMC
SBB EAX
,
EAX
NEG EAX
end
;
function
CRCCode
(
var
CRCDef
:
TCRCDef
;
const
Buffer
;
Size
:
Cardinal
)
:
Cardinal
;
register
;
asm
// do the CRC computation
JECXZ
@@
5
TEST EDX
,
EDX
JZ
@@
5
PUSH ESI
PUSH EBX
MOV ESI
,
EAX
CMP
[
EAX
]
.
TCRCDef
.
Inverse
,
0
MOV EAX
,
[
ESI
]
.
TCRCDef
.
CRC
JZ
@@
2
XOR
EBX
,
EBX
@@
1
:
MOV BL
,
[
EDX
]
XOR
BL
,
AL
SHR
EAX
,
8
INC EDX
XOR
EAX
,
[
ESI
+
EBX
*
4
]
DEC ECX
JNZ
@@
1
JMP
@@
4
@@
2
:
PUSH EDI
MOV EBX
,
EAX
MOV EDI
,
ECX
MOV ECX
,
[
ESI
]
.
TCRCDef
.
Shift
MOV EBX
,
EAX
@@
3
:
SHR
EBX
,
CL
SHL
EAX
,
8
XOR
BL
,
[
EDX
]
INC EDX
MOVZX EBX
,
BL
XOR
EAX
,
[
ESI
+
EBX
*
4
]
DEC EDI
MOV EBX
,
EAX
JNZ
@@
3
POP EDI
@@
4
:
MOV
[
ESI
]
.
TCRCDef
.
CRC
,
EAX
XOR
EAX
,
[
ESI
]
.
TCRCDef
.
FinalVector
AND
EAX
,
[
ESI
]
.
TCRCDef
.
Mask
POP EBX
POP ESI
RET
@@
5
:
MOV EAX
,
[
EAX
]
.
TCRCDef
.
CRC
end
;
function
CRCCodeEx
(
var
CRCDef
:
TCRCDef
;
ReadMethod
:
TReadMethod
;
Size
:
Cardinal
)
:
Cardinal
;
var
Buffer
:
array
[
0
..
1023
]
of
Char
;
Count
:
LongInt
;
begin
repeat
if
Size >
SizeOf
(
Buffer
)
then
Count
:
=
SizeOf
(
Buffer
)
else
Count
:
=
Size
;
Count
:
=
ReadMethod
(
Buffer
,
Count
)
;
Result
:
=
CRCCode
(
CRCDef
,
Buffer
,
Count
)
;
Dec
(
Size
,
Count
)
;
until
(
Size
=
0
)
or
(
Count
=
0
)
;
end
;
function
CRCInit
(
var
CRCDef
:
TCRCDef
;
CRCType
:
TCRCType
)
:
Boolean
;
register
;
type
PCRCTab
=
^
TCRCTab
;
TCRCTab
=
array
[
TCRCType
]
of
packed
record
Poly
,
Bits
,
Init
,
FInit
:
Cardinal
;
Inverse
:
LongBool
;
end
;
{$IFOPT O-}{$O+}{$DEFINE NoOpt}{$ENDIF}
procedure
CRCTab
;
asm
// Polynom Bits InitVec FinitVec Inverse
DD
$000000D1
,
8
,
$00000000
,
$00000000
,
-
1
// CRC_8 GSM/ERR
DD
$00000233
,
10
,
$00000000
,
$00000000
,
-
1
// CRC_10 ATM/OAM Cell
DD
$0000080F
,
12
,
$00000000
,
$00000000
,
-
1
// CRC_12
DD
$00008005
,
16
,
$00000000
,
$00000000
,
-
1
// CRC_16 ARC,IBM
DD
$00001021
,
16
,
$00001D0F
,
$00000000
,
0
// CRC_16 CCITT ITU
DD
$00008408
,
16
,
$00000000
,
$00000000
,
-
1
// CRC_16 XModem
DD
$00864CFB
,
24
,
$00B704CE
,
$00000000
,
0
// CRC_24
DD
$9DB11213
,
32
,
$FFFFFFFF
,
$FFFFFFFF
,
-
1
// CRC_32
DD
$04C11DB7
,
32
,
$FFFFFFFF
,
$FFFFFFFF
,
-
1
// CRC_32CCITT
DD
$04C11DB7
,
32
,
$FFFFFFFF
,
$00000000
,
-
1
// CRC_32ZModem
// some other CRC's, not all yet verfied
// DD $00000007, 8, $00000000, $00000000, -1 // CRC_8 ATM/HEC
// DD $00000007, 8, $00000000, $00000000, 0 // CRC_8 the SMBus Working Group
// DD $00004599, 15, $00000000, $00000000, -1 // CRC_15 CANBus
// DD $00001021, 16, $00000000, $00000000, 0 // CRC_16ZModem
// DD $00001021, 16, $0000FFFF, $00000000, 0 // CRC_16 CCITT British Aerospace
// DD $00004003, 16, $00000000, $00000000, -1 // CRC_16 reversed
// DD $00001005, 16, $00000000, $00000000, -1 // CRC_16 X25
// DD $00000053, 16, $00000000, $00000000, -1 // BasicCard 16Bit CRC (sparse poly for Crypto MCU)
// DD $000000C5, 32, $00000000, $00000000, -1 // BasicCard 32Bit CRC
// http://dbforums.com/showthread.php?threadid=122012
end
;
{$IFDEF NoOpt}{$O-}{$ENDIF}
begin
with
PCRCTab
(
@
CRCTab
)
[
CRCType
]
do
Result
:
=
CRCSetup
(
CRCDef
,
Poly
,
Bits
,
Init
,
FInit
,
Inverse
)
;
end
;
function
CRCDone
(
var
CRCDef
:
TCRCDef
)
:
Cardinal
;
register
;
asm
// finalize CRCDef after a computation
MOV EDX
,
[
EAX
]
.
TCRCDef
.
CRC
MOV ECX
,
[
EAX
]
.
TCRCDef
.
InitVector
XOR
EDX
,
[
EAX
]
.
TCRCDef
.
FinalVector
MOV
[
EAX
]
.
TCRCDef
.
CRC
,
ECX
AND
EDX
,
[
EAX
]
.
TCRCDef
.
Mask
MOV EAX
,
EDX
end
;
function
CRCCalc
(
CRCType
:
TCRCType
;
const
Buffer
;
Size
:
Cardinal
)
:
Cardinal
;
// inplace calculation
var
CRC
:
TCRCDef
;
begin
CRCInit
(
CRC
,
CRCType
)
;
Result
:
=
CRCCode
(
CRC
,
Buffer
,
Size
)
;
end
;
function
CRCCalcEx
(
CRCType
:
TCRCType
;
ReadMethod
:
TReadMethod
;
Size
:
Cardinal
)
:
Cardinal
;
var
CRC
:
TCRCDef
;
begin
CRCInit
(
CRC
,
CRCType
)
;
Result
:
=
CRCCodeEx
(
CRC
,
ReadMethod
,
Size
)
;
end
;
// predefined CRC16/CRC32CCITT, avoid slower lookuptable computation by use of precomputation
var
FCRC16
:
PCRCDef
=
nil
;
FCRC32
:
PCRCDef
=
nil
;
function
CRC16Init
:
Pointer
;
begin
GetMem
(
FCRC16
,
SizeOf
(
TCRCDef
)
)
;
CRCInit
(
FCRC16
^
,
CRC_16
)
;
Result
:
=
FCRC16
;
end
;
function
CRC16
(
CRC
:
Word
;
const
Buffer
;
Size
:
Cardinal
)
:
Word
;
asm
JECXZ
@@
2
PUSH EDI
PUSH ESI
MOV EDI
,
ECX
{$IFDEF PIC}
MOV ESI
,
[
EBX
]
.
FCRC16
{$ELSE}
MOV ESI
,
FCRC16
{$ENDIF}
XOR
ECX
,
ECX
TEST ESI
,
ESI
JZ
@@
3
@@
1
:
MOV CL
,
[
EDX
]
XOR
CL
,
AL
SHR
EAX
,
8
INC EDX
XOR
EAX
,
[
ESI
+
ECX
*
4
]
DEC EDI
JNZ
@@
1
POP ESI
POP EDI
@@
2
:
RET
@@
3
:
PUSH EAX
PUSH EDX
CALL CRC16Init
MOV ESI
,
EAX
XOR
ECX
,
ECX
POP EDX
POP EAX
JMP
@@
1
end
;
function
CRC32Init
:
Pointer
;
begin
GetMem
(
FCRC32
,
SizeOf
(
TCRCDef
)
)
;
CRCInit
(
FCRC32
^
,
CRC_32CCITT
)
;
Result
:
=
FCRC32
;
end
;
function
CRC32
(
CRC
:
Cardinal
;
const
Buffer
;
Size
:
Cardinal
)
:
Cardinal
;
asm
JECXZ
@@
2
PUSH EDI
PUSH ESI
NOT
EAX
// inverse Input CRC
MOV EDI
,
ECX
{$IFDEF PIC}
MOV ESI
,
[
EBX
]
.
FCRC32
{$ELSE}
MOV ESI
,
FCRC32
{$ENDIF}
XOR
ECX
,
ECX
TEST ESI
,
ESI
JZ
@@
3
@@
1
:
MOV CL
,
[
EDX
]
XOR
CL
,
AL
SHR
EAX
,
8
INC EDX
XOR
EAX
,
[
ESI
+
ECX
*
4
]
DEC EDI
JNZ
@@
1
NOT
EAX
// inverse Output CRC
POP ESI
POP EDI
@@
2
:
RET
@@
3
:
PUSH EAX
PUSH EDX
CALL CRC32Init
MOV ESI
,
EAX
XOR
ECX
,
ECX
POP EDX
POP EAX
JMP
@@
1
end
;
procedure
CRCInitThreadSafe
;
begin
CRC16Init
;
CRC32Init
;
end
;
initialization
finalization
if
FCRC16 <>
nil
then
FreeMem
(
FCRC16
)
;
if
FCRC32 <>
nil
then
FreeMem
(
FCRC32
)
;
end
.