home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 April A / Pcwk4a98.iso / PROGRAM / PASCAL / DUMPING / ADLER32.PAS next >
Pascal/Delphi Source File  |  1995-03-17  |  5KB  |  176 lines

  1. Unit  Adler32 ;
  2.  
  3. {
  4.    Written 1995 by Oliver Fromme <fromme@rz.tu-clausthal.de>.
  5.    Donated to the public domain.
  6.  
  7.    Freely usable, freely distributable.
  8.    Nobody may claim copyright on this code.
  9.  
  10.    This unit provides an Adler32 check, as specified in the ziplib library.
  11. }
  12.  
  13. {$A+,B-,D+,I-,l+,T-,V+,X+,Y+,S-,R-,Q-}
  14.  
  15. {$UNDEF NOASM} {Enable this DEFINE if you want to use Pascal routines
  16.                   instead of fast Assembly routines.}
  17.  
  18.  
  19.  
  20. Interface
  21.  
  22. Type  tAdler = Record
  23.                   Case Integer Of
  24.                      0 : (Value : LongInt) ; {treated as unsigned 32 bit}
  25.                      1 : (S1,S2 : Word)
  26.                End ;
  27.  
  28. Procedure  InitAdler32 (Var Adler : tAdler) ;
  29.    {Initializes the given variable for Adler32 calculation.}
  30.  
  31. Procedure  UpdateAdler32 (Var Adler : tAdler ; Var InBuf ; InLen : Word) ;
  32.    {Updates the given Adler variable.  Checks 'InLen' bytes at 'InBuf'.}
  33.  
  34. Function  FinalAdler32 (Adler : tAdler) : LongInt ;
  35.    {This returns the actual Adler32 value.
  36.     Note that the actual variable is not changed, so you can continue
  37.     updating it.}
  38.  
  39. {
  40.    Procedure  Example ;
  41.       Var  my_Adler : tAdler ;
  42.       Begin
  43.          InitAdler (my_Adler) ;
  44.          UpdateAdler32 (my_Adler,data1,SizeOf(data1) ;
  45.          UpdateAdler32 (my_Adler,data2,SizeOf(data2) ;
  46.          UpdateAdler32 (my_Adler,data3,SizeOf(data3) ;
  47.          tAdler := FinalAdler(my_Adler) ;
  48.          WriteLn ('Adler32 of data1-data3 is ',my_Adler)
  49.       End ;
  50. }
  51.  
  52.  
  53.  
  54. Implementation
  55.  
  56. Const  Adler_BASE = 65521 ; {largest prime smaller than 65536}
  57.        Adler_NMAX = 5552 ; {NMAX is the largest n such that
  58.                             255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1}
  59.  
  60. Procedure  InitAdler32 (Var Adler : tAdler) ;
  61.    Begin
  62.       Adler.Value := 1 {S1 :=1 ; S2 := 0}
  63.    End {InitAdler32} ;
  64.  
  65. {$IFDEF NOASM}
  66.  
  67. Procedure  UpdateAdler32 (Var Adler : tAdler ; Var InBuf ; InLen : Word) ;
  68.    Var  BytePtr   : ^Byte ;
  69.         wcount,i  : Word ;
  70.         Sum1,Sum2 : LongInt ;
  71.    Begin
  72.       Sum1 := Adler.S1 ;
  73.       Sum2 := Adler.S2 ;
  74.       BytePtr := Addr(InBuf) ;
  75.       While InLen<>0 Do Begin
  76.          If InLen<Adler_NMAX Then
  77.             wcount := InLen
  78.          Else
  79.             wcount := Adler_NMAX ;
  80.          For i:=1 To wcount Do Begin
  81.             Inc (Sum1,BytePtr^) ;
  82.             Inc (Sum2,Sum1) ;
  83.             Inc (BytePtr)
  84.          End ;
  85.          Dec (InLen,wcount) ;
  86.          {The following requires ASM because Pascal's LongInt is signed.
  87.           It's also possible to add a constant to Sum1 (or Sum2) if it's
  88.           negative, but that would be slower.}
  89.          Asm
  90.             {Sum1 := Sum1 Mod Adler_BASE ;}
  91.                 mov     ax,word ptr Sum1
  92.                 mov     dx,word ptr Sum1+2
  93.                 mov     bx,Adler_BASE
  94.                 div     bx
  95.                 mov     word ptr Sum1,dx
  96.                 mov     word ptr Sum1+2,0
  97.             {Sum2 := Sum2 Mod Adler_BASE}
  98.                 mov     ax,word ptr Sum2
  99.                 mov     dx,word ptr Sum2+2
  100.                 mov     bx,Adler_BASE
  101.                 div     bx
  102.                 mov     word ptr Sum2,dx
  103.                 mov     word ptr Sum2+2,0
  104.          End ;
  105.       End ;
  106.       Adler.S1 := Sum1 ;
  107.       Adler.S2 := Sum2
  108.    End {UpdateAdler32} ;
  109.  
  110. {$ELSE}
  111.  
  112. Procedure  UpdateAdler32 (Var Adler : tAdler ; Var InBuf ; InLen : Word) ;
  113.    Assembler ;
  114.    Asm
  115.                 push    ds
  116.                 push    bp
  117.                 les     di,Adler
  118.                 lds     si,InBuf
  119.                 mov     cx,InLen
  120.                 mov     bx,es:[di]      {dx:bx = S1}
  121.                 xor     dx,dx
  122.                 mov     bp,es:[di+2]    {di:bp = S2}
  123.                 xor     di,di
  124.         {outer While loop}
  125.         @wloop: test    cx,cx
  126.                 jz      @wend
  127.                 mov     ax,Adler_NMAX
  128.                 cmp     cx,ax
  129.                 jae     @lab1
  130.                 mov     ax,cx
  131.         @lab1:  sub     cx,ax
  132.                 push    cx
  133.                 mov     cx,ax
  134.                 xor     ah,ah
  135.         {inner For loop}
  136.         @floop: lodsb
  137.                 add     bx,ax
  138.                 adc     dx,0
  139.                 add     bp,bx
  140.                 adc     di,dx
  141.                 dec     cx
  142.                 jnz     @floop
  143.         {end of inner For loop}
  144.                 mov     cx,Adler_BASE
  145.         {Sum1 := Sum1 Mod Adler_BASE}
  146.                 mov     ax,bx
  147.                 div     cx
  148.                 mov     bx,dx
  149.         {Sum2 := Sum2 Mod Adler_BASE}
  150.                 mov     ax,bp
  151.                 mov     dx,di
  152.                 div     cx
  153.                 mov     bp,dx
  154.                 xor     dx,dx
  155.                 xor     di,di
  156.                 pop     cx
  157.                 jmp     @wloop
  158.         {end of outer While loop}
  159.         @wend:
  160.                 mov     ax,bp
  161.                 pop     bp
  162.                 mov     di,word ptr Adler
  163.                 mov     es:[di],bx
  164.                 mov     es:[di+2],ax
  165.                 pop     ds
  166.    End {UpdateAdler32} ;
  167.  
  168. {$ENDIF}
  169.  
  170. Function  FinalAdler32 (Adler : tAdler) : LongInt ;
  171.    Begin
  172.       FinalAdler32 := Adler.Value
  173.    End {FinalAdler32} ;
  174.  
  175. End.
  176.