123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- 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
- zbase;
- function inflate_fast( bl : cardinal;
- bd : cardinal;
- tl : pInflate_huft;
- td : pInflate_huft;
- var s : inflate_blocks_state;
- var z : z_stream) : integer;
- 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 : cardinal;
- bd : cardinal;
- tl : pInflate_huft;
- td : pInflate_huft;
- var s : inflate_blocks_state;
- var z : z_stream) : integer;
- var
- t : pInflate_huft; { temporary pointer }
- e : cardinal; { extra bits or operation }
- b : longint; { bit buffer }
- k : cardinal; { bits in bit buffer }
- p : Pbyte; { input data pointer }
- n : cardinal; { bytes available there }
- q : Pbyte; { output window write pointer }
- m : cardinal; { bytes to end of window or read pointer }
- ml : cardinal; { mask for literal/length tree }
- md : cardinal; { mask for distance tree }
- c : cardinal; { bytes to copy }
- d : cardinal; { distance back to copy from }
- r : Pbyte; { 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 ptruint(q) < ptruint(s.read) then
- m := cardinal(ptruint(s.read)-ptruint(q)-1)
- else
- m := cardinal(ptruint(s.zend)-ptruint(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 (longint(p^) shl k);
- inc(p);
- inc(k, 8);
- end;
- t := @(huft_ptr(tl)^[cardinal(b) and ml]);
- e := t^.exop;
- if (e = 0) then
- begin
- {DUMPBITS(t^.bits);}
- b := b shr t^.bits;
- dec(k, t^.bits);
- {$IFDEF ZLIB_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 + (cardinal(b) and inflate_mask[e]);
- {DUMPBITS(e);}
- b := b shr e;
- dec(k, e);
- {$IFDEF ZLIB_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 (longint(p^) shl k);
- inc(p);
- inc(k, 8);
- end;
- t := @huft_ptr(td)^[cardinal(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 (longint(p^) shl k);
- inc(p);
- inc(k, 8);
- end;
- d := t^.base + (cardinal(b) and inflate_mask[e]);
- {DUMPBITS(e);}
- b := b shr e;
- dec(k, e);
- {$IFDEF ZLIB_DEBUG}
- Tracevv('inflate: * distance '+IntToStr(d));
- {$ENDIF}
- { do the copy }
- dec(m, c);
- if (cardinal(ptruint(q) - ptruint(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 - cardinal(ptruint(q) - ptruint(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 + (cardinal(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, ptruint(p)-ptruint(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 += ((cardinal)b & inflate_mask[e]))->exop;}
- inc(t, t^.base + (cardinal(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 ZLIB_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 ZLIB_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, ptruint(p)-ptruint(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, ptruint(p)-ptruint(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, ptruint(p)-ptruint(z.next_in));
- z.next_in := p;
- s.write := q;
- inflate_fast := Z_OK;
- end;
- end.
|