home *** CD-ROM | disk | FTP | other *** search
- Unit InfFast;
-
- {
- inffast.h and
- inffast.c -- process literals and length/distance pairs fast
- Copyright (C) 1995-1998 Mark Adler
-
- Pascal tranlastion
- Copyright (C) 1998 by Jacques Nomssi Nzali
- For conditions of distribution and use, see copyright notice in readme.txt
- }
-
-
- interface
-
- {$I zconf.inc}
-
- uses
- {$ifdef DEBUG}
- strutils,
- {$ENDIF}
- zutil, zlib;
-
- function inflate_fast( bl : uInt;
- bd : uInt;
- tl : pInflate_huft;
- td : pInflate_huft;
- var s : inflate_blocks_state;
- var z : z_stream) : int;
-
-
- implementation
-
- uses
- infutil;
-
-
- { Called with number of bytes left to write in window at least 258
- (the maximum string length) and number of input bytes available
- at least ten. The ten bytes are six bytes for the longest length/
- distance pair plus four bytes for overloading the bit buffer. }
-
- function inflate_fast( bl : uInt;
- bd : uInt;
- tl : pInflate_huft;
- td : pInflate_huft;
- var s : inflate_blocks_state;
- var z : z_stream) : int;
-
- var
- t : pInflate_huft; { temporary pointer }
- e : uInt; { extra bits or operation }
- b : uLong; { bit buffer }
- k : uInt; { bits in bit buffer }
- p : pBytef; { input data pointer }
- n : uInt; { bytes available there }
- q : pBytef; { output window write pointer }
- m : uInt; { bytes to end of window or read pointer }
- ml : uInt; { mask for literal/length tree }
- md : uInt; { mask for distance tree }
- c : uInt; { bytes to copy }
- d : uInt; { distance back to copy from }
- r : pBytef; { copy source pointer }
- begin
- { load input, output, bit values (macro LOAD) }
- p := z.next_in;
- n := z.avail_in;
- b := s.bitb;
- k := s.bitk;
- q := s.write;
- if ptr2int(q) < ptr2int(s.read) then
- m := uInt(ptr2int(s.read)-ptr2int(q)-1)
- else
- m := uInt(ptr2int(s.zend)-ptr2int(q));
-
- { initialize masks }
- ml := inflate_mask[bl];
- md := inflate_mask[bd];
-
- { do until not enough input or output space for fast loop }
- repeat { assume called with (m >= 258) and (n >= 10) }
- { get literal/length code }
- {GRABBITS(20);} { max bits for literal/length code }
- while (k < 20) do
- begin
- Dec(n);
- b := b or (uLong(p^) shl k);
- Inc(p);
- Inc(k, 8);
- end;
-
- t := @(huft_ptr(tl)^[uInt(b) and ml]);
-
- e := t^.exop;
- if (e = 0) then
- begin
- {DUMPBITS(t^.bits);}
- b := b shr t^.bits;
- Dec(k, t^.bits);
- {$IFDEF DEBUG}
- if (t^.base >= $20) and (t^.base < $7f) then
- Tracevv('inflate: * literal '+char(t^.base))
- else
- Tracevv('inflate: * literal '+ IntToStr(t^.base));
- {$ENDIF}
- q^ := Byte(t^.base);
- Inc(q);
- Dec(m);
- continue;
- end;
- repeat
- {DUMPBITS(t^.bits);}
- b := b shr t^.bits;
- Dec(k, t^.bits);
-
- if (e and 16 <> 0) then
- begin
- { get extra bits for length }
- e := e and 15;
- c := t^.base + (uInt(b) and inflate_mask[e]);
- {DUMPBITS(e);}
- b := b shr e;
- Dec(k, e);
- {$IFDEF DEBUG}
- Tracevv('inflate: * length ' + IntToStr(c));
- {$ENDIF}
- { decode distance base of block to copy }
- {GRABBITS(15);} { max bits for distance code }
- while (k < 15) do
- begin
- Dec(n);
- b := b or (uLong(p^) shl k);
- Inc(p);
- Inc(k, 8);
- end;
-
- t := @huft_ptr(td)^[uInt(b) and md];
- e := t^.exop;
- repeat
- {DUMPBITS(t^.bits);}
- b := b shr t^.bits;
- Dec(k, t^.bits);
-
- if (e and 16 <> 0) then
- begin
- { get extra bits to add to distance base }
- e := e and 15;
- {GRABBITS(e);} { get extra bits (up to 13) }
- while (k < e) do
- begin
- Dec(n);
- b := b or (uLong(p^) shl k);
- Inc(p);
- Inc(k, 8);
- end;
-
- d := t^.base + (uInt(b) and inflate_mask[e]);
- {DUMPBITS(e);}
- b := b shr e;
- Dec(k, e);
-
- {$IFDEF DEBUG}
- Tracevv('inflate: * distance '+IntToStr(d));
- {$ENDIF}
- { do the copy }
- Dec(m, c);
- if (uInt(ptr2int(q) - ptr2int(s.window)) >= d) then { offset before dest }
- begin { just copy }
- r := q;
- Dec(r, d);
- q^ := r^; Inc(q); Inc(r); Dec(c); { minimum count is three, }
- q^ := r^; Inc(q); Inc(r); Dec(c); { so unroll loop a little }
- end
- else { else offset after destination }
- begin
- e := d - uInt(ptr2int(q) - ptr2int(s.window)); { bytes from offset to end }
- r := s.zend;
- Dec(r, e); { pointer to offset }
- if (c > e) then { if source crosses, }
- begin
- Dec(c, e); { copy to end of window }
- repeat
- q^ := r^;
- Inc(q);
- Inc(r);
- Dec(e);
- until (e=0);
- r := s.window; { copy rest from start of window }
- end;
- end;
- repeat { copy all or what's left }
- q^ := r^;
- Inc(q);
- Inc(r);
- Dec(c);
- until (c = 0);
- break;
- end
- else
- if (e and 64 = 0) then
- begin
- Inc(t, t^.base + (uInt(b) and inflate_mask[e]));
- e := t^.exop;
- end
- else
- begin
- z.msg := 'invalid distance code';
- {UNGRAB}
- c := z.avail_in-n;
- if (k shr 3) < c then
- c := k shr 3;
- Inc(n, c);
- Dec(p, c);
- Dec(k, c shl 3);
- {UPDATE}
- s.bitb := b;
- s.bitk := k;
- z.avail_in := n;
- Inc(z.total_in, ptr2int(p)-ptr2int(z.next_in));
- z.next_in := p;
- s.write := q;
-
- inflate_fast := Z_DATA_ERROR;
- exit;
- end;
- until FALSE;
- break;
- end;
- if (e and 64 = 0) then
- begin
- {t += t->base;
- e = (t += ((uInt)b & inflate_mask[e]))->exop;}
-
- Inc(t, t^.base + (uInt(b) and inflate_mask[e]));
- e := t^.exop;
- if (e = 0) then
- begin
- {DUMPBITS(t^.bits);}
- b := b shr t^.bits;
- Dec(k, t^.bits);
-
- {$IFDEF DEBUG}
- if (t^.base >= $20) and (t^.base < $7f) then
- Tracevv('inflate: * literal '+char(t^.base))
- else
- Tracevv('inflate: * literal '+IntToStr(t^.base));
- {$ENDIF}
- q^ := Byte(t^.base);
- Inc(q);
- Dec(m);
- break;
- end;
- end
- else
- if (e and 32 <> 0) then
- begin
- {$IFDEF DEBUG}
- Tracevv('inflate: * end of block');
- {$ENDIF}
- {UNGRAB}
- c := z.avail_in-n;
- if (k shr 3) < c then
- c := k shr 3;
- Inc(n, c);
- Dec(p, c);
- Dec(k, c shl 3);
- {UPDATE}
- s.bitb := b;
- s.bitk := k;
- z.avail_in := n;
- Inc(z.total_in, ptr2int(p)-ptr2int(z.next_in));
- z.next_in := p;
- s.write := q;
- inflate_fast := Z_STREAM_END;
- exit;
- end
- else
- begin
- z.msg := 'invalid literal/length code';
- {UNGRAB}
- c := z.avail_in-n;
- if (k shr 3) < c then
- c := k shr 3;
- Inc(n, c);
- Dec(p, c);
- Dec(k, c shl 3);
- {UPDATE}
- s.bitb := b;
- s.bitk := k;
- z.avail_in := n;
- Inc(z.total_in, ptr2int(p)-ptr2int(z.next_in));
- z.next_in := p;
- s.write := q;
- inflate_fast := Z_DATA_ERROR;
- exit;
- end;
- until FALSE;
- until (m < 258) or (n < 10);
-
- { not enough input or output--restore pointers and return }
- {UNGRAB}
- c := z.avail_in-n;
- if (k shr 3) < c then
- c := k shr 3;
- Inc(n, c);
- Dec(p, c);
- Dec(k, c shl 3);
- {UPDATE}
- s.bitb := b;
- s.bitk := k;
- z.avail_in := n;
- Inc(z.total_in, ptr2int(p)-ptr2int(z.next_in));
- z.next_in := p;
- s.write := q;
- inflate_fast := Z_OK;
- end;
-
- end.