123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- MODULE CRC; (** AUTHOR "prk/TF"; PURPOSE "CRC utilities"; *)
- (**
- * History:
- *
- * 28.09.2000 added CRC32 support -- TF
- * 08.01.2007 added SetCRC procedures to enable other initial values (staubesv)
- *)
- IMPORT
- SYSTEM, Streams;
- CONST
- Init16 = -1; (* initial CRC16 value *)
- Init32 = LONGINT(0FFFFFFFFH) ; (* initial CRC32 value *)
- TYPE
- CRC16Stream* = OBJECT(Streams.Writer)
- VAR
- crc* : INTEGER;
- PROCEDURE &InitStream*;
- BEGIN
- crc := Init16;
- InitWriter(Send, 256)
- END InitStream;
- PROCEDURE Send*(CONST buf: ARRAY OF CHAR; ofs, len: LONGINT; propagate: BOOLEAN; VAR res: WORD);
- VAR fcs, idx: SET; i: LONGINT;
- BEGIN
- fcs := SYSTEM.VAL( SET, crc ) * SYSTEM.VAL( SET, 0FFFFH );
- FOR i := ofs TO ofs + len - 1 DO
- idx := SYSTEM.VAL( SET, SYSTEM.VAL( LONGINT, fcs ) DIV 256 ) / SYSTEM.VAL( SET, LONG( ORD( buf[i] ) ) );
- fcs := CRC16Table[SYSTEM.VAL( LONGINT, idx) MOD 256] / SYSTEM.VAL( SET, SYSTEM.VAL( LONGINT, fcs ) * 256 )
- END;
- crc := SHORT( SYSTEM.VAL( LONGINT, fcs * SYSTEM.VAL( SET, 0FFFFH ) ) );
- res := Streams.Ok
- END Send;
- PROCEDURE SetCRC*(crc : INTEGER);
- BEGIN
- Update();
- SELF.crc := crc;
- END SetCRC;
- PROCEDURE GetCRC*(): INTEGER;
- BEGIN
- Update();
- RETURN crc
- END GetCRC;
- END CRC16Stream;
- CRC32Stream* = OBJECT(Streams.Writer)
- VAR
- crc : LONGINT;
- PROCEDURE &InitStream*;
- BEGIN
- crc := Init32;
- InitWriter(Send, 256)
- END InitStream;
- PROCEDURE Reset*;
- BEGIN
- Update();
- crc := Init32
- END Reset;
- PROCEDURE Send*(CONST buf: ARRAY OF CHAR; ofs, len: LONGINT; propagate: BOOLEAN; VAR res: WORD);
- VAR idx: LONGINT;
- BEGIN
- WHILE len > 0 DO
- idx := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, crc) / SYSTEM.VAL(SET, LONG(ORD(buf[ofs])))) MOD 100H;
- crc := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, CRC32Table[idx])/SYSTEM.VAL(SET, LSH(crc, -8)));
- DEC(len); INC(ofs)
- END;
- res := Streams.Ok
- END Send;
- PROCEDURE SetCRC*(crc : LONGINT);
- BEGIN
- Update();
- SELF.crc := crc;
- END SetCRC;
- PROCEDURE GetCRC*():LONGINT;
- BEGIN
- Update();
- RETURN SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, crc)/{0..31})
- END GetCRC;
- PROCEDURE GetUninvertedCRC*():LONGINT;
- BEGIN
- Update();
- RETURN crc
- END GetUninvertedCRC;
- END CRC32Stream;
- TYPE CRC32*= OBJECT
- VAR crc : LONGINT;
- PROCEDURE &Init*;
- BEGIN
- crc := LONGINT(0FFFFFFFFH);
- END Init;
- (* standard use: one character at a time *)
- PROCEDURE Char*(c: CHAR);
- VAR idx: LONGINT;
- BEGIN
- idx := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, crc) / SYSTEM.VAL(SET, LONG(ORD(c)))) MOD 100H;
- crc := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, CRC32Table[idx])/SYSTEM.VAL(SET, LSH(crc, -8)));
- END Char;
- (* nonstandard use - add a LONGINT; LSB *)
- PROCEDURE Add*(i: LONGINT);
- VAR idx: LONGINT;
- BEGIN
- i:= SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, crc) / SYSTEM.VAL(SET, i));
- idx := i MOD 100H;
- crc := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, CRC32Table[idx])/SYSTEM.VAL(SET, LSH(crc, -8)));
- idx := i DIV 100H MOD 100H;
- crc := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, CRC32Table[idx])/SYSTEM.VAL(SET, LSH(crc, -8)));
- idx := i DIV 10000H MOD 100H;
- crc := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, CRC32Table[idx])/SYSTEM.VAL(SET, LSH(crc, -8)));
- idx := i DIV 1000000H MOD 100H;
- crc := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, CRC32Table[idx])/SYSTEM.VAL(SET, LSH(crc, -8)));
- END Add;
- PROCEDURE Get*():LONGINT;
- BEGIN
- RETURN SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, crc)/{0..31})
- END Get;
- END CRC32;
- VAR
- CRC16Table, CRC32Table: ARRAY 256 OF SET;
- PROCEDURE InitTable16;
- VAR fcs, t: SET; d, i, k: LONGINT;
- BEGIN
- FOR i := 0 TO 255 DO
- fcs := { }; d := i*256;
- FOR k := 0 TO 7 DO
- t := fcs; fcs := SYSTEM.VAL( SET, SYSTEM.VAL( LONGINT, fcs ) * 2 );
- IF (t / SYSTEM.VAL( SET, d )) * SYSTEM.VAL( SET, 8000H ) # {} THEN fcs := fcs / SYSTEM.VAL( SET, 1021H ) END;
- d := d * 2
- END;
- CRC16Table[i] := fcs * SYSTEM.VAL( SET, 0FFFFH )
- END
- END InitTable16;
- PROCEDURE InitTable32;
- CONST poly = LONGINT(0EDB88320H);
- VAR n, c, k: LONGINT;
- BEGIN
- FOR n := 0 TO 255 DO
- c := n;
- FOR k := 0 TO 7 DO
- IF ODD(c) THEN c := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, poly) / SYSTEM.VAL(SET, LSH(c, -1)))
- ELSE c := LSH(c, -1)
- END
- END;
- CRC32Table[n] := SYSTEM.VAL(SET, c)
- END
- END InitTable32;
- BEGIN
- InitTable16;
- InitTable32
- END CRC.
- System.Free CRC ~
|