CRC.Mod 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. MODULE CRC; (** AUTHOR "prk/TF"; PURPOSE "CRC utilities"; *)
  2. (**
  3. * History:
  4. *
  5. * 28.09.2000 added CRC32 support -- TF
  6. * 08.01.2007 added SetCRC procedures to enable other initial values (staubesv)
  7. *)
  8. IMPORT
  9. SYSTEM, Streams;
  10. CONST
  11. Init16 = -1; (* initial CRC16 value *)
  12. Init32 = LONGINT(0FFFFFFFFH) ; (* initial CRC32 value *)
  13. TYPE
  14. CRC16Stream* = OBJECT(Streams.Writer)
  15. VAR
  16. crc* : INTEGER;
  17. PROCEDURE &InitStream*;
  18. BEGIN
  19. crc := Init16;
  20. InitWriter(Send, 256)
  21. END InitStream;
  22. PROCEDURE Send*(CONST buf: ARRAY OF CHAR; ofs, len: LONGINT; propagate: BOOLEAN; VAR res: WORD);
  23. VAR fcs, idx: SET; i: LONGINT;
  24. BEGIN
  25. fcs := SYSTEM.VAL( SET, crc ) * SYSTEM.VAL( SET, 0FFFFH );
  26. FOR i := ofs TO ofs + len - 1 DO
  27. idx := SYSTEM.VAL( SET, SYSTEM.VAL( LONGINT, fcs ) DIV 256 ) / SYSTEM.VAL( SET, LONG( ORD( buf[i] ) ) );
  28. fcs := CRC16Table[SYSTEM.VAL( LONGINT, idx) MOD 256] / SYSTEM.VAL( SET, SYSTEM.VAL( LONGINT, fcs ) * 256 )
  29. END;
  30. crc := SHORT( SYSTEM.VAL( LONGINT, fcs * SYSTEM.VAL( SET, 0FFFFH ) ) );
  31. res := Streams.Ok
  32. END Send;
  33. PROCEDURE SetCRC*(crc : INTEGER);
  34. BEGIN
  35. Update();
  36. SELF.crc := crc;
  37. END SetCRC;
  38. PROCEDURE GetCRC*(): INTEGER;
  39. BEGIN
  40. Update();
  41. RETURN crc
  42. END GetCRC;
  43. END CRC16Stream;
  44. CRC32Stream* = OBJECT(Streams.Writer)
  45. VAR
  46. crc : LONGINT;
  47. PROCEDURE &InitStream*;
  48. BEGIN
  49. crc := Init32;
  50. InitWriter(Send, 256)
  51. END InitStream;
  52. PROCEDURE Reset*;
  53. BEGIN
  54. Update();
  55. crc := Init32
  56. END Reset;
  57. PROCEDURE Send*(CONST buf: ARRAY OF CHAR; ofs, len: LONGINT; propagate: BOOLEAN; VAR res: WORD);
  58. VAR idx: LONGINT;
  59. BEGIN
  60. WHILE len > 0 DO
  61. idx := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, crc) / SYSTEM.VAL(SET, LONG(ORD(buf[ofs])))) MOD 100H;
  62. crc := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, CRC32Table[idx])/SYSTEM.VAL(SET, LSH(crc, -8)));
  63. DEC(len); INC(ofs)
  64. END;
  65. res := Streams.Ok
  66. END Send;
  67. PROCEDURE SetCRC*(crc : LONGINT);
  68. BEGIN
  69. Update();
  70. SELF.crc := crc;
  71. END SetCRC;
  72. PROCEDURE GetCRC*():LONGINT;
  73. BEGIN
  74. Update();
  75. RETURN SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, crc)/{0..31})
  76. END GetCRC;
  77. PROCEDURE GetUninvertedCRC*():LONGINT;
  78. BEGIN
  79. Update();
  80. RETURN crc
  81. END GetUninvertedCRC;
  82. END CRC32Stream;
  83. TYPE CRC32*= OBJECT
  84. VAR crc : LONGINT;
  85. PROCEDURE &Init*;
  86. BEGIN
  87. crc := LONGINT(0FFFFFFFFH);
  88. END Init;
  89. (* standard use: one character at a time *)
  90. PROCEDURE Char*(c: CHAR);
  91. VAR idx: LONGINT;
  92. BEGIN
  93. idx := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, crc) / SYSTEM.VAL(SET, LONG(ORD(c)))) MOD 100H;
  94. crc := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, CRC32Table[idx])/SYSTEM.VAL(SET, LSH(crc, -8)));
  95. END Char;
  96. (* nonstandard use - add a LONGINT; LSB *)
  97. PROCEDURE Add*(i: LONGINT);
  98. VAR idx: LONGINT;
  99. BEGIN
  100. i:= SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, crc) / SYSTEM.VAL(SET, i));
  101. idx := i MOD 100H;
  102. crc := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, CRC32Table[idx])/SYSTEM.VAL(SET, LSH(crc, -8)));
  103. idx := i DIV 100H MOD 100H;
  104. crc := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, CRC32Table[idx])/SYSTEM.VAL(SET, LSH(crc, -8)));
  105. idx := i DIV 10000H MOD 100H;
  106. crc := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, CRC32Table[idx])/SYSTEM.VAL(SET, LSH(crc, -8)));
  107. idx := i DIV 1000000H MOD 100H;
  108. crc := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, CRC32Table[idx])/SYSTEM.VAL(SET, LSH(crc, -8)));
  109. END Add;
  110. PROCEDURE Get*():LONGINT;
  111. BEGIN
  112. RETURN SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, crc)/{0..31})
  113. END Get;
  114. END CRC32;
  115. VAR
  116. CRC16Table, CRC32Table: ARRAY 256 OF SET;
  117. PROCEDURE InitTable16;
  118. VAR fcs, t: SET; d, i, k: LONGINT;
  119. BEGIN
  120. FOR i := 0 TO 255 DO
  121. fcs := { }; d := i*256;
  122. FOR k := 0 TO 7 DO
  123. t := fcs; fcs := SYSTEM.VAL( SET, SYSTEM.VAL( LONGINT, fcs ) * 2 );
  124. IF (t / SYSTEM.VAL( SET, d )) * SYSTEM.VAL( SET, 8000H ) # {} THEN fcs := fcs / SYSTEM.VAL( SET, 1021H ) END;
  125. d := d * 2
  126. END;
  127. CRC16Table[i] := fcs * SYSTEM.VAL( SET, 0FFFFH )
  128. END
  129. END InitTable16;
  130. PROCEDURE InitTable32;
  131. CONST poly = LONGINT(0EDB88320H);
  132. VAR n, c, k: LONGINT;
  133. BEGIN
  134. FOR n := 0 TO 255 DO
  135. c := n;
  136. FOR k := 0 TO 7 DO
  137. IF ODD(c) THEN c := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, poly) / SYSTEM.VAL(SET, LSH(c, -1)))
  138. ELSE c := LSH(c, -1)
  139. END
  140. END;
  141. CRC32Table[n] := SYSTEM.VAL(SET, c)
  142. END
  143. END InitTable32;
  144. BEGIN
  145. InitTable16;
  146. InitTable32
  147. END CRC.
  148. System.Free CRC ~