bszlib.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:275k
- s.match_start := cur_match;
- best_len := len;
- if (len >= nice_match) then
- break;
- {$IFOPT R+} {$R-} {$DEFINE NoRangeCheck} {$ENDIF}
- {$ifdef UNALIGNED_OK}
- scan_end := pzByteArray(scan)^[best_len-1];
- {$else}
- scan_end1 := pzByteArray(scan)^[best_len-1];
- scan_end := pzByteArray(scan)^[best_len];
- {$endif}
- {$IFDEF NoRangeCheck} {$R+} {$UNDEF NoRangeCheck} {$ENDIF}
- end;
- nextstep:
- cur_match := prev^[cur_match and wmask];
- Dec(chain_length);
- until (cur_match <= limit) or (chain_length = 0);
- if (uInt(best_len) <= s.lookahead) then
- longest_match := uInt(best_len)
- else
- longest_match := s.lookahead;
- end;
- {$endif} { ASMV }
- {$else} { FASTEST }
- { ---------------------------------------------------------------------------
- Optimized version for level = 1 only }
- {local}
- function longest_match(var s : deflate_state;
- cur_match : IPos { current match }
- ) : uInt;
- var
- {register} scan : pBytef; { current string }
- {register} match : pBytef; { matched string }
- {register} len : int; { length of current match }
- {register} strend : pBytef;
- begin
- scan := @s.window^[s.strstart];
- strend := @s.window^[s.strstart + MAX_MATCH];
- { The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
- It is easy to get rid of this optimization if necessary. }
- {$IFDEF DEBUG}
- Assert((s.hash_bits >= 8) and (MAX_MATCH = 258), 'Code too clever');
- Assert(ulg(s.strstart) <= s.window_size-MIN_LOOKAHEAD, 'need lookahead');
- Assert(cur_match < s.strstart, 'no future');
- {$ENDIF}
- match := s.window + cur_match;
- { Return failure if the match length is less than 2: }
- if (match[0] <> scan[0]) or (match[1] <> scan[1]) then
- begin
- longest_match := MIN_MATCH-1;
- exit;
- end;
- { The check at best_len-1 can be removed because it will be made
- again later. (This heuristic is not always a win.)
- It is not necessary to compare scan[2] and match[2] since they
- are always equal when the other bytes match, given that
- the hash keys are equal and that HASH_BITS >= 8. }
- scan += 2, match += 2;
- Assert(scan^ = match^, 'match[2]?');
- { We check for insufficient lookahead only every 8th comparison;
- the 256th check will be made at strstart+258. }
- repeat
- Inc(scan); Inc(match); if scan^<>match^ then break;
- Inc(scan); Inc(match); if scan^<>match^ then break;
- Inc(scan); Inc(match); if scan^<>match^ then break;
- Inc(scan); Inc(match); if scan^<>match^ then break;
- Inc(scan); Inc(match); if scan^<>match^ then break;
- Inc(scan); Inc(match); if scan^<>match^ then break;
- Inc(scan); Inc(match); if scan^<>match^ then break;
- Inc(scan); Inc(match); if scan^<>match^ then break;
- until (ptr2int(scan) >= ptr2int(strend));
- Assert(scan <= s.window+unsigned(s.window_size-1), 'wild scan');
- len := MAX_MATCH - int(strend - scan);
- if (len < MIN_MATCH) then
- begin
- return := MIN_MATCH - 1;
- exit;
- end;
- s.match_start := cur_match;
- if len <= s.lookahead then
- longest_match := len
- else
- longest_match := s.lookahead;
- end;
- {$endif} { FASTEST }
- {$ifdef DEBUG}
- { ===========================================================================
- Check that the match at match_start is indeed a match. }
- {local}
- procedure check_match(var s : deflate_state;
- start, match : IPos;
- length : int);
- begin
- exit;
- { check that the match is indeed a match }
- if (zmemcmp(pBytef(@s.window^[match]),
- pBytef(@s.window^[start]), length) <> EQUAL) then
- begin
- WriteLn(' start ',start,', match ',match ,' length ', length);
- repeat
- Write(char(s.window^[match]), char(s.window^[start]));
- Inc(match);
- Inc(start);
- Dec(length);
- Until (length = 0);
- z_error('invalid match');
- end;
- if (z_verbose > 1) then
- begin
- Write('\[',start-match,',',length,']');
- repeat
- Write(char(s.window^[start]));
- Inc(start);
- Dec(length);
- Until (length = 0);
- end;
- end;
- {$endif}
- { ===========================================================================
- Fill the window when the lookahead becomes insufficient.
- Updates strstart and lookahead.
- IN assertion: lookahead < MIN_LOOKAHEAD
- OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
- At least one byte has been read, or avail_in = 0; reads are
- performed for at least two bytes (required for the zip translate_eol
- option -- not supported here). }
- {local}
- procedure fill_window(var s : deflate_state);
- var
- {register} n, m : unsigned;
- {register} p : pPosf;
- more : unsigned; { Amount of free space at the end of the window. }
- wsize : uInt;
- begin
- wsize := s.w_size;
- repeat
- more := unsigned(s.window_size -ulg(s.lookahead) -ulg(s.strstart));
- { Deal with !@#$% 64K limit: }
- if (more = 0) and (s.strstart = 0) and (s.lookahead = 0) then
- more := wsize
- else
- if (more = unsigned(-1)) then
- begin
- { Very unlikely, but possible on 16 bit machine if strstart = 0
- and lookahead = 1 (input done one byte at time) }
- Dec(more);
- { If the window is almost full and there is insufficient lookahead,
- move the upper half to the lower one to make room in the upper half.}
- end
- else
- if (s.strstart >= wsize+ {MAX_DIST}wsize-MIN_LOOKAHEAD) then
- begin
- zmemcpy( pBytef(s.window), pBytef(@(s.window^[wsize])),
- unsigned(wsize));
- Dec(s.match_start, wsize);
- Dec(s.strstart, wsize); { we now have strstart >= MAX_DIST }
- Dec(s.block_start, long(wsize));
- { Slide the hash table (could be avoided with 32 bit values
- at the expense of memory usage). We slide even when level = 0
- to keep the hash table consistent if we switch back to level > 0
- later. (Using level 0 permanently is not an optimal usage of
- zlib, so we don't care about this pathological case.) }
- n := s.hash_size;
- p := @s.head^[n];
- repeat
- Dec(p);
- m := p^;
- if (m >= wsize) then
- p^ := Pos(m-wsize)
- else
- p^ := Pos(ZNIL);
- Dec(n);
- Until (n=0);
- n := wsize;
- {$ifndef FASTEST}
- p := @s.prev^[n];
- repeat
- Dec(p);
- m := p^;
- if (m >= wsize) then
- p^ := Pos(m-wsize)
- else
- p^:= Pos(ZNIL);
- { If n is not on any hash chain, prev^[n] is garbage but
- its value will never be used. }
- Dec(n);
- Until (n=0);
- {$endif}
- Inc(more, wsize);
- end;
- if (s.strm^.avail_in = 0) then
- exit;
- {* If there was no sliding:
- * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
- * more == window_size - lookahead - strstart
- * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
- * => more >= window_size - 2*WSIZE + 2
- * In the BIG_MEM or MMAP case (not yet supported),
- * window_size == input_size + MIN_LOOKAHEAD &&
- * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
- * Otherwise, window_size == 2*WSIZE so more >= 2.
- * If there was sliding, more >= WSIZE. So in all cases, more >= 2. }
- {$IFDEF DEBUG}
- Assert(more >= 2, 'more < 2');
- {$ENDIF}
- n := read_buf(s.strm, pBytef(@(s.window^[s.strstart + s.lookahead])),
- more);
- Inc(s.lookahead, n);
- { Initialize the hash value now that we have some input: }
- if (s.lookahead >= MIN_MATCH) then
- begin
- s.ins_h := s.window^[s.strstart];
- {UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]);}
- s.ins_h := ((s.ins_h shl s.hash_shift) xor s.window^[s.strstart+1])
- and s.hash_mask;
- {$ifdef MIN_MATCH <> 3}
- Call UPDATE_HASH() MIN_MATCH-3 more times
- {$endif}
- end;
- { If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
- but this is not important since only literal bytes will be emitted. }
- until (s.lookahead >= MIN_LOOKAHEAD) or (s.strm^.avail_in = 0);
- end;
- { ===========================================================================
- Flush the current block, with given end-of-file flag.
- IN assertion: strstart is set to the end of the current match. }
- procedure FLUSH_BLOCK_ONLY(var s : deflate_state; eof : boolean); {macro}
- begin
- if (s.block_start >= Long(0)) then
- _tr_flush_block(s, pcharf(@s.window^[unsigned(s.block_start)]),
- ulg(long(s.strstart) - s.block_start), eof)
- else
- _tr_flush_block(s, pcharf(Z_NULL),
- ulg(long(s.strstart) - s.block_start), eof);
- s.block_start := s.strstart;
- flush_pending(s.strm^);
- {$IFDEF DEBUG}
- Tracev('[FLUSH]');
- {$ENDIF}
- end;
- { Same but force premature exit if necessary.
- macro FLUSH_BLOCK(var s : deflate_state; eof : boolean) : boolean;
- var
- result : block_state;
- begin
- FLUSH_BLOCK_ONLY(s, eof);
- if (s.strm^.avail_out = 0) then
- begin
- if eof then
- result := finish_started
- else
- result := need_more;
- exit;
- end;
- end;
- }
- { ===========================================================================
- Copy without compression as much as possible from the input stream, return
- the current block state.
- This function does not insert new strings in the dictionary since
- uncompressible data is probably not useful. This function is used
- only for the level=0 compression option.
- NOTE: this function should be optimized to avoid extra copying from
- window to pending_buf. }
- {local}
- function deflate_stored(var s : deflate_state; flush : int) : block_state;
- { Stored blocks are limited to 0xffff bytes, pending_buf is limited
- to pending_buf_size, and each stored block has a 5 byte header: }
- var
- max_block_size : ulg;
- max_start : ulg;
- begin
- max_block_size := $ffff;
- if (max_block_size > s.pending_buf_size - 5) then
- max_block_size := s.pending_buf_size - 5;
- { Copy as much as possible from input to output: }
- while TRUE do
- begin
- { Fill the window as much as possible: }
- if (s.lookahead <= 1) then
- begin
- {$IFDEF DEBUG}
- Assert( (s.strstart < s.w_size + {MAX_DIST}s.w_size-MIN_LOOKAHEAD) or
- (s.block_start >= long(s.w_size)), 'slide too late');
- {$ENDIF}
- fill_window(s);
- if (s.lookahead = 0) and (flush = Z_NO_FLUSH) then
- begin
- deflate_stored := need_more;
- exit;
- end;
- if (s.lookahead = 0) then
- break; { flush the current block }
- end;
- {$IFDEF DEBUG}
- Assert(s.block_start >= long(0), 'block gone');
- {$ENDIF}
- Inc(s.strstart, s.lookahead);
- s.lookahead := 0;
- { Emit a stored block if pending_buf will be full: }
- max_start := s.block_start + max_block_size;
- if (s.strstart = 0) or (ulg(s.strstart) >= max_start) then
- begin
- { strstart = 0 is possible when wraparound on 16-bit machine }
- {$WARNINGS OFF}
- s.lookahead := uInt(s.strstart - max_start);
- {$WARNINGS ON}
- s.strstart := uInt(max_start);
- {FLUSH_BLOCK(s, FALSE);}
- FLUSH_BLOCK_ONLY(s, FALSE);
- if (s.strm^.avail_out = 0) then
- begin
- deflate_stored := need_more;
- exit;
- end;
- end;
- { Flush if we may have to slide, otherwise block_start may become
- negative and the data will be gone: }
- if (s.strstart - uInt(s.block_start) >= {MAX_DIST}
- s.w_size-MIN_LOOKAHEAD) then
- begin
- {FLUSH_BLOCK(s, FALSE);}
- FLUSH_BLOCK_ONLY(s, FALSE);
- if (s.strm^.avail_out = 0) then
- begin
- deflate_stored := need_more;
- exit;
- end;
- end;
- end;
- {FLUSH_BLOCK(s, flush = Z_FINISH);}
- FLUSH_BLOCK_ONLY(s, flush = Z_FINISH);
- if (s.strm^.avail_out = 0) then
- begin
- if flush = Z_FINISH then
- deflate_stored := finish_started
- else
- deflate_stored := need_more;
- exit;
- end;
- if flush = Z_FINISH then
- deflate_stored := finish_done
- else
- deflate_stored := block_done;
- end;
- { ===========================================================================
- Compress as much as possible from the input stream, return the current
- block state.
- This function does not perform lazy evaluation of matches and inserts
- new strings in the dictionary only for unmatched strings or for short
- matches. It is used only for the fast compression options. }
- {local}
- function deflate_fast(var s : deflate_state; flush : int) : block_state;
- var
- hash_head : IPos; { head of the hash chain }
- bflush : boolean; { set if current block must be flushed }
- begin
- hash_head := ZNIL;
- while TRUE do
- begin
- { Make sure that we always have enough lookahead, except
- at the end of the input file. We need MAX_MATCH bytes
- for the next match, plus MIN_MATCH bytes to insert the
- string following the next match. }
- if (s.lookahead < MIN_LOOKAHEAD) then
- begin
- fill_window(s);
- if (s.lookahead < MIN_LOOKAHEAD) and (flush = Z_NO_FLUSH) then
- begin
- deflate_fast := need_more;
- exit;
- end;
- if (s.lookahead = 0) then
- break; { flush the current block }
- end;
- { Insert the string window[strstart .. strstart+2] in the
- dictionary, and set hash_head to the head of the hash chain: }
- if (s.lookahead >= MIN_MATCH) then
- begin
- INSERT_STRING(s, s.strstart, hash_head);
- end;
- { Find the longest match, discarding those <= prev_length.
- At this point we have always match_length < MIN_MATCH }
- if (hash_head <> ZNIL) and
- (s.strstart - hash_head <= (s.w_size-MIN_LOOKAHEAD){MAX_DIST}) then
- begin
- { To simplify the code, we prevent matches with the string
- of window index 0 (in particular we have to avoid a match
- of the string with itself at the start of the input file). }
- if (s.strategy <> Z_HUFFMAN_ONLY) then
- begin
- s.match_length := longest_match (s, hash_head);
- end;
- { longest_match() sets match_start }
- end;
- if (s.match_length >= MIN_MATCH) then
- begin
- {$IFDEF DEBUG}
- check_match(s, s.strstart, s.match_start, s.match_length);
- {$ENDIF}
- {_tr_tally_dist(s, s.strstart - s.match_start,
- s.match_length - MIN_MATCH, bflush);}
- bflush := _tr_tally(s, s.strstart - s.match_start,
- s.match_length - MIN_MATCH);
- Dec(s.lookahead, s.match_length);
- { Insert new strings in the hash table only if the match length
- is not too large. This saves time but degrades compression. }
- {$ifndef FASTEST}
- if (s.match_length <= s.max_insert_length)
- and (s.lookahead >= MIN_MATCH) then
- begin
- Dec(s.match_length); { string at strstart already in hash table }
- repeat
- Inc(s.strstart);
- INSERT_STRING(s, s.strstart, hash_head);
- { strstart never exceeds WSIZE-MAX_MATCH, so there are
- always MIN_MATCH bytes ahead. }
- Dec(s.match_length);
- until (s.match_length = 0);
- Inc(s.strstart);
- end
- else
- {$endif}
- begin
- Inc(s.strstart, s.match_length);
- s.match_length := 0;
- s.ins_h := s.window^[s.strstart];
- {UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]);}
- s.ins_h := (( s.ins_h shl s.hash_shift) xor
- s.window^[s.strstart+1]) and s.hash_mask;
- if MIN_MATCH <> 3 then { the linker removes this }
- begin
- {Call UPDATE_HASH() MIN_MATCH-3 more times}
- end;
- { If lookahead < MIN_MATCH, ins_h is garbage, but it does not
- matter since it will be recomputed at next deflate call. }
- end;
- end
- else
- begin
- { No match, output a literal byte }
- {$IFDEF DEBUG}
- Tracevv(char(s.window^[s.strstart]));
- {$ENDIF}
- {_tr_tally_lit (s, 0, s.window^[s.strstart], bflush);}
- bflush := _tr_tally (s, 0, s.window^[s.strstart]);
- Dec(s.lookahead);
- Inc(s.strstart);
- end;
- if bflush then
- begin {FLUSH_BLOCK(s, FALSE);}
- FLUSH_BLOCK_ONLY(s, FALSE);
- if (s.strm^.avail_out = 0) then
- begin
- deflate_fast := need_more;
- exit;
- end;
- end;
- end;
- {FLUSH_BLOCK(s, flush = Z_FINISH);}
- FLUSH_BLOCK_ONLY(s, flush = Z_FINISH);
- if (s.strm^.avail_out = 0) then
- begin
- if flush = Z_FINISH then
- deflate_fast := finish_started
- else
- deflate_fast := need_more;
- exit;
- end;
- if flush = Z_FINISH then
- deflate_fast := finish_done
- else
- deflate_fast := block_done;
- end;
- { ===========================================================================
- Same as above, but achieves better compression. We use a lazy
- evaluation for matches: a match is finally adopted only if there is
- no better match at the next window position. }
- {local}
- function deflate_slow(var s : deflate_state; flush : int) : block_state;
- var
- hash_head : IPos; { head of hash chain }
- bflush : boolean; { set if current block must be flushed }
- var
- max_insert : uInt;
- begin
- hash_head := ZNIL;
- { Process the input block. }
- while TRUE do
- begin
- { Make sure that we always have enough lookahead, except
- at the end of the input file. We need MAX_MATCH bytes
- for the next match, plus MIN_MATCH bytes to insert the
- string following the next match. }
- if (s.lookahead < MIN_LOOKAHEAD) then
- begin
- fill_window(s);
- if (s.lookahead < MIN_LOOKAHEAD) and (flush = Z_NO_FLUSH) then
- begin
- deflate_slow := need_more;
- exit;
- end;
- if (s.lookahead = 0) then
- break; { flush the current block }
- end;
- { Insert the string window[strstart .. strstart+2] in the
- dictionary, and set hash_head to the head of the hash chain: }
- if (s.lookahead >= MIN_MATCH) then
- begin
- INSERT_STRING(s, s.strstart, hash_head);
- end;
- { Find the longest match, discarding those <= prev_length. }
- s.prev_length := s.match_length;
- s.prev_match := s.match_start;
- s.match_length := MIN_MATCH-1;
- if (hash_head <> ZNIL) and (s.prev_length < s.max_lazy_match) and
- (s.strstart - hash_head <= {MAX_DIST}(s.w_size-MIN_LOOKAHEAD)) then
- begin
- { To simplify the code, we prevent matches with the string
- of window index 0 (in particular we have to avoid a match
- of the string with itself at the start of the input file). }
- if (s.strategy <> Z_HUFFMAN_ONLY) then
- begin
- s.match_length := longest_match (s, hash_head);
- end;
- { longest_match() sets match_start }
- if (s.match_length <= 5) and ((s.strategy = Z_FILTERED) or
- ((s.match_length = MIN_MATCH) and
- (s.strstart - s.match_start > TOO_FAR))) then
- begin
- { If prev_match is also MIN_MATCH, match_start is garbage
- but we will ignore the current match anyway. }
- s.match_length := MIN_MATCH-1;
- end;
- end;
- { If there was a match at the previous step and the current
- match is not better, output the previous match: }
- if (s.prev_length >= MIN_MATCH)
- and (s.match_length <= s.prev_length) then
- begin
- max_insert := s.strstart + s.lookahead - MIN_MATCH;
- { Do not insert strings in hash table beyond this. }
- {$ifdef DEBUG}
- check_match(s, s.strstart-1, s.prev_match, s.prev_length);
- {$endif}
- {_tr_tally_dist(s, s->strstart -1 - s->prev_match,
- s->prev_length - MIN_MATCH, bflush);}
- bflush := _tr_tally(s, s.strstart -1 - s.prev_match,
- s.prev_length - MIN_MATCH);
- { Insert in hash table all strings up to the end of the match.
- strstart-1 and strstart are already inserted. If there is not
- enough lookahead, the last two strings are not inserted in
- the hash table. }
- Dec(s.lookahead, s.prev_length-1);
- Dec(s.prev_length, 2);
- repeat
- Inc(s.strstart);
- if (s.strstart <= max_insert) then
- begin
- INSERT_STRING(s, s.strstart, hash_head);
- end;
- Dec(s.prev_length);
- until (s.prev_length = 0);
- s.match_available := FALSE;
- s.match_length := MIN_MATCH-1;
- Inc(s.strstart);
- if (bflush) then {FLUSH_BLOCK(s, FALSE);}
- begin
- FLUSH_BLOCK_ONLY(s, FALSE);
- if (s.strm^.avail_out = 0) then
- begin
- deflate_slow := need_more;
- exit;
- end;
- end;
- end
- else
- if (s.match_available) then
- begin
- { If there was no match at the previous position, output a
- single literal. If there was a match but the current match
- is longer, truncate the previous match to a single literal. }
- {$IFDEF DEBUG}
- Tracevv(char(s.window^[s.strstart-1]));
- {$ENDIF}
- bflush := _tr_tally (s, 0, s.window^[s.strstart-1]);
- if bflush then
- begin
- FLUSH_BLOCK_ONLY(s, FALSE);
- end;
- Inc(s.strstart);
- Dec(s.lookahead);
- if (s.strm^.avail_out = 0) then
- begin
- deflate_slow := need_more;
- exit;
- end;
- end
- else
- begin
- { There is no previous match to compare with, wait for
- the next step to decide. }
- s.match_available := TRUE;
- Inc(s.strstart);
- Dec(s.lookahead);
- end;
- end;
- {$IFDEF DEBUG}
- Assert (flush <> Z_NO_FLUSH, 'no flush?');
- {$ENDIF}
- if (s.match_available) then
- begin
- {$IFDEF DEBUG}
- Tracevv(char(s.window^[s.strstart-1]));
- bflush :=
- {$ENDIF}
- _tr_tally (s, 0, s.window^[s.strstart-1]);
- s.match_available := FALSE;
- end;
- {FLUSH_BLOCK(s, flush = Z_FINISH);}
- FLUSH_BLOCK_ONLY(s, flush = Z_FINISH);
- if (s.strm^.avail_out = 0) then
- begin
- if flush = Z_FINISH then
- deflate_slow := finish_started
- else
- deflate_slow := need_more;
- exit;
- end;
- if flush = Z_FINISH then
- deflate_slow := finish_done
- else
- deflate_slow := block_done;
- end;
- { Tables for deflate from PKZIP's appnote.txt. }
- Const
- border : Array [0..18] Of Word { Order of the bit length code lengths }
- = (16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15);
- { Notes beyond the 1.93a appnote.txt:
- 1. Distance pointers never point before the beginning of the output
- stream.
- 2. Distance pointers can point back across blocks, up to 32k away.
- 3. There is an implied maximum of 7 bits for the bit length table and
- 15 bits for the actual data.
- 4. If only one code exists, then it is encoded using one bit. (Zero
- would be more efficient, but perhaps a little confusing.) If two
- codes exist, they are coded using one bit each (0 and 1).
- 5. There is no way of sending zero distance codes--a dummy must be
- sent if there are none. (History: a pre 2.0 version of PKZIP would
- store blocks with no distance codes, but this was discovered to be
- too harsh a criterion.) Valid only for 1.93a. 2.04c does allow
- zero distance codes, which is sent as one code of zero bits in
- length.
- 6. There are up to 286 literal/length codes. Code 256 represents the
- end-of-block. Note however that the static length tree defines
- 288 codes just to fill out the Huffman codes. Codes 286 and 287
- cannot be used though, since there is no length base or extra bits
- defined for them. Similarily, there are up to 30 distance codes.
- However, static trees define 32 codes (all 5 bits) to fill out the
- Huffman codes, but the last two had better not show up in the data.
- 7. Unzip can check dynamic Huffman blocks for complete code sets.
- The exception is that a single code would not be complete (see #4).
- 8. The five bits following the block type is really the number of
- literal codes sent minus 257.
- 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
- (1+6+6). Therefore, to output three times the length, you output
- three codes (1+1+1), whereas to output four times the same length,
- you only need two codes (1+3). Hmm.
- 10. In the tree reconstruction algorithm, Code = Code + Increment
- only if BitLength(i) is not zero. (Pretty obvious.)
- 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19)
- 12. Note: length code 284 can represent 227-258, but length code 285
- really is 258. The last length deserves its own, short code
- since it gets used a lot in very redundant files. The length
- 258 is special since 258 - 3 (the min match length) is 255.
- 13. The literal/length and distance code bit lengths are read as a
- single stream of lengths. It is possible (and advantageous) for
- a repeat code (16, 17, or 18) to go across the boundary between
- the two sets of lengths. }
- procedure inflate_blocks_reset (var s : inflate_blocks_state;
- var z : z_stream;
- c : puLong); { check value on output }
- begin
- if (c <> Z_NULL) then
- c^ := s.check;
- if (s.mode = BTREE) or (s.mode = DTREE) then
- ZFREE(z, s.sub.trees.blens);
- if (s.mode = CODES) then
- inflate_codes_free(s.sub.decode.codes, z);
- s.mode := ZTYPE;
- s.bitk := 0;
- s.bitb := 0;
- s.write := s.window;
- s.read := s.window;
- if Assigned(s.checkfn) then
- begin
- s.check := s.checkfn(uLong(0), pBytef(NIL), 0);
- z.adler := s.check;
- end;
- {$IFDEF DEBUG}
- Tracev('inflate: blocks reset');
- {$ENDIF}
- end;
- function inflate_blocks_new(var z : z_stream;
- c : check_func; { check function }
- w : uInt { window size }
- ) : pInflate_blocks_state;
- var
- s : pInflate_blocks_state;
- begin
- s := pInflate_blocks_state( ZALLOC(z,1, sizeof(inflate_blocks_state)) );
- if (s = Z_NULL) then
- begin
- inflate_blocks_new := s;
- exit;
- end;
- s^.hufts := huft_ptr( ZALLOC(z, sizeof(inflate_huft), MANY) );
- if (s^.hufts = Z_NULL) then
- begin
- ZFREE(z, s);
- inflate_blocks_new := Z_NULL;
- exit;
- end;
- s^.window := pBytef( ZALLOC(z, 1, w) );
- if (s^.window = Z_NULL) then
- begin
- ZFREE(z, s^.hufts);
- ZFREE(z, s);
- inflate_blocks_new := Z_NULL;
- exit;
- end;
- s^.zend := s^.window;
- Inc(s^.zend, w);
- s^.checkfn := c;
- s^.mode := ZTYPE;
- {$IFDEF DEBUG}
- Tracev('inflate: blocks allocated');
- {$ENDIF}
- inflate_blocks_reset(s^, z, Z_NULL);
- inflate_blocks_new := s;
- end;
- function inflate_blocks (var s : inflate_blocks_state;
- var z : z_stream;
- r : int) : int; { initial return code }
- label
- start_btree, start_dtree,
- start_blkdone, start_dry,
- start_codes;
- var
- t : uInt; { temporary storage }
- 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 }
- { fixed code blocks }
- var
- bl, bd : uInt;
- tl, td : pInflate_huft;
- var
- h : pInflate_huft;
- i, j, c : uInt;
- var
- cs : pInflate_codes_state;
- begin
- { copy input/output information to locals }
- 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));
- { decompress an inflated block }
- { process input based on current state }
- while True do
- Case s.mode of
- ZTYPE:
- begin
- {NEEDBITS(3);}
- while (k < 3) do
- begin
- {NEEDBYTE;}
- if (n <> 0) then
- r :=Z_OK
- else
- begin
- {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_blocks := inflate_flush(s,z,r);
- exit;
- end;
- Dec(n);
- b := b or (uLong(p^) shl k);
- Inc(p);
- Inc(k, 8);
- end;
- t := uInt(b) and 7;
- s.last := boolean(t and 1);
- case (t shr 1) of
- 0: { stored }
- begin
- {$IFDEF DEBUG}
- if s.last then
- Tracev('inflate: stored block (last)')
- else
- Tracev('inflate: stored block');
- {$ENDIF}
- {DUMPBITS(3);}
- b := b shr 3;
- Dec(k, 3);
- t := k and 7; { go to byte boundary }
- {DUMPBITS(t);}
- b := b shr t;
- Dec(k, t);
- s.mode := LENS; { get length of stored block }
- end;
- 1: { fixed }
- begin
- begin
- {$IFDEF DEBUG}
- if s.last then
- Tracev('inflate: fixed codes blocks (last)')
- else
- Tracev('inflate: fixed codes blocks');
- {$ENDIF}
- inflate_trees_fixed(bl, bd, tl, td, z);
- s.sub.decode.codes := inflate_codes_new(bl, bd, tl, td, z);
- if (s.sub.decode.codes = Z_NULL) then
- begin
- r := Z_MEM_ERROR;
- { update pointers and return }
- 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_blocks := inflate_flush(s,z,r);
- exit;
- end;
- end;
- {DUMPBITS(3);}
- b := b shr 3;
- Dec(k, 3);
- s.mode := CODES;
- end;
- 2: { dynamic }
- begin
- {$IFDEF DEBUG}
- if s.last then
- Tracev('inflate: dynamic codes block (last)')
- else
- Tracev('inflate: dynamic codes block');
- {$ENDIF}
- {DUMPBITS(3);}
- b := b shr 3;
- Dec(k, 3);
- s.mode := TABLE;
- end;
- 3:
- begin { illegal }
- {DUMPBITS(3);}
- b := b shr 3;
- Dec(k, 3);
- s.mode := BLKBAD;
- z.msg := 'invalid block type';
- r := Z_DATA_ERROR;
- { update pointers and return }
- 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_blocks := inflate_flush(s,z,r);
- exit;
- end;
- end;
- end;
- LENS:
- begin
- {NEEDBITS(32);}
- while (k < 32) do
- begin
- {NEEDBYTE;}
- if (n <> 0) then
- r :=Z_OK
- else
- begin
- {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_blocks := inflate_flush(s,z,r);
- exit;
- end;
- Dec(n);
- b := b or (uLong(p^) shl k);
- Inc(p);
- Inc(k, 8);
- end;
- if (((not b) shr 16) and $ffff) <> (b and $ffff) then
- begin
- s.mode := BLKBAD;
- z.msg := 'invalid stored block lengths';
- r := Z_DATA_ERROR;
- { update pointers and return }
- 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_blocks := inflate_flush(s,z,r);
- exit;
- end;
- s.sub.left := uInt(b) and $ffff;
- k := 0;
- b := 0; { dump bits }
- {$IFDEF DEBUG}
- Tracev('inflate: stored length '+IntToStr(s.sub.left));
- {$ENDIF}
- if s.sub.left <> 0 then
- s.mode := STORED
- else
- if s.last then
- s.mode := DRY
- else
- s.mode := ZTYPE;
- end;
- STORED:
- begin
- if (n = 0) then
- begin
- { update pointers and return }
- 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_blocks := inflate_flush(s,z,r);
- exit;
- end;
- {NEEDOUT}
- if (m = 0) then
- begin
- {WRAP}
- if (q = s.zend) and (s.read <> s.window) then
- begin
- q := s.window;
- if ptr2int(q) < ptr2int(s.read) then
- m := uInt(ptr2int(s.read)-ptr2int(q)-1)
- else
- m := uInt(ptr2int(s.zend)-ptr2int(q));
- end;
- if (m = 0) then
- begin
- {FLUSH}
- s.write := q;
- r := inflate_flush(s,z,r);
- 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));
- {WRAP}
- if (q = s.zend) and (s.read <> s.window) then
- begin
- q := s.window;
- if ptr2int(q) < ptr2int(s.read) then
- m := uInt(ptr2int(s.read)-ptr2int(q)-1)
- else
- m := uInt(ptr2int(s.zend)-ptr2int(q));
- end;
- if (m = 0) then
- begin
- {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_blocks := inflate_flush(s,z,r);
- exit;
- end;
- end;
- end;
- r := Z_OK;
- t := s.sub.left;
- if (t > n) then
- t := n;
- if (t > m) then
- t := m;
- zmemcpy(q, p, t);
- Inc(p, t); Dec(n, t);
- Inc(q, t); Dec(m, t);
- Dec(s.sub.left, t);
- if (s.sub.left = 0) then
- begin
- {$IFDEF DEBUG}
- if (ptr2int(q) >= ptr2int(s.read)) then
- Tracev('inflate: stored end '+
- IntToStr(z.total_out + ptr2int(q) - ptr2int(s.read)) + ' total out')
- else
- Tracev('inflate: stored end '+
- IntToStr(z.total_out + ptr2int(s.zend) - ptr2int(s.read) +
- ptr2int(q) - ptr2int(s.window)) + ' total out');
- {$ENDIF}
- if s.last then
- s.mode := DRY
- else
- s.mode := ZTYPE;
- end;
- end;
- TABLE:
- begin
- {NEEDBITS(14);}
- while (k < 14) do
- begin
- {NEEDBYTE;}
- if (n <> 0) then
- r :=Z_OK
- else
- begin
- {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_blocks := inflate_flush(s,z,r);
- exit;
- end;
- Dec(n);
- b := b or (uLong(p^) shl k);
- Inc(p);
- Inc(k, 8);
- end;
- t := uInt(b) and $3fff;
- s.sub.trees.table := t;
- {$ifndef PKZIP_BUG_WORKAROUND}
- if ((t and $1f) > 29) or (((t shr 5) and $1f) > 29) then
- begin
- s.mode := BLKBAD;
- z.msg := 'too many length or distance symbols';
- r := Z_DATA_ERROR;
- { update pointers and return }
- 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_blocks := inflate_flush(s,z,r);
- exit;
- end;
- {$endif}
- t := 258 + (t and $1f) + ((t shr 5) and $1f);
- s.sub.trees.blens := puIntArray( ZALLOC(z, t, sizeof(uInt)) );
- if (s.sub.trees.blens = Z_NULL) then
- begin
- r := Z_MEM_ERROR;
- { update pointers and return }
- 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_blocks := inflate_flush(s,z,r);
- exit;
- end;
- {DUMPBITS(14);}
- b := b shr 14;
- Dec(k, 14);
- s.sub.trees.index := 0;
- {$IFDEF DEBUG}
- Tracev('inflate: table sizes ok');
- {$ENDIF}
- s.mode := BTREE;
- { fall trough case is handled by the while }
- { try GOTO for speed - Nomssi }
- goto start_btree;
- end;
- BTREE:
- begin
- start_btree:
- while (s.sub.trees.index < 4 + (s.sub.trees.table shr 10)) do
- begin
- {NEEDBITS(3);}
- while (k < 3) do
- begin
- {NEEDBYTE;}
- if (n <> 0) then
- r :=Z_OK
- else
- begin
- {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_blocks := inflate_flush(s,z,r);
- exit;
- end;
- Dec(n);
- b := b or (uLong(p^) shl k);
- Inc(p);
- Inc(k, 8);
- end;
- s.sub.trees.blens^[border[s.sub.trees.index]] := uInt(b) and 7;
- Inc(s.sub.trees.index);
- {DUMPBITS(3);}
- b := b shr 3;
- Dec(k, 3);
- end;
- while (s.sub.trees.index < 19) do
- begin
- s.sub.trees.blens^[border[s.sub.trees.index]] := 0;
- Inc(s.sub.trees.index);
- end;
- s.sub.trees.bb := 7;
- t := inflate_trees_bits(s.sub.trees.blens^, s.sub.trees.bb,
- s.sub.trees.tb, s.hufts^, z);
- if (t <> Z_OK) then
- begin
- ZFREE(z, s.sub.trees.blens);
- r := t;
- if (r = Z_DATA_ERROR) then
- s.mode := BLKBAD;
- { update pointers and return }
- 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_blocks := inflate_flush(s,z,r);
- exit;
- end;
- s.sub.trees.index := 0;
- {$IFDEF DEBUG}
- Tracev('inflate: bits tree ok');
- {$ENDIF}
- s.mode := DTREE;
- { fall through again }
- goto start_dtree;
- end;
- DTREE:
- begin
- start_dtree:
- while TRUE do
- begin
- t := s.sub.trees.table;
- if not (s.sub.trees.index < 258 +
- (t and $1f) + ((t shr 5) and $1f)) then
- break;
- t := s.sub.trees.bb;
- {NEEDBITS(t);}
- while (k < t) do
- begin
- {NEEDBYTE;}
- if (n <> 0) then
- r :=Z_OK
- else
- begin
- {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_blocks := inflate_flush(s,z,r);
- exit;
- end;
- Dec(n);
- b := b or (uLong(p^) shl k);
- Inc(p);
- Inc(k, 8);
- end;
- h := s.sub.trees.tb;
- Inc(h, uInt(b) and inflate_mask[t]);
- t := h^.Bits;
- c := h^.Base;
- if (c < 16) then
- begin
- {DUMPBITS(t);}
- b := b shr t;
- Dec(k, t);
- s.sub.trees.blens^[s.sub.trees.index] := c;
- Inc(s.sub.trees.index);
- end
- else { c = 16..18 }
- begin
- if c = 18 then
- begin
- i := 7;
- j := 11;
- end
- else
- begin
- i := c - 14;
- j := 3;
- end;
- {NEEDBITS(t + i);}
- while (k < t + i) do
- begin
- {NEEDBYTE;}
- if (n <> 0) then
- r :=Z_OK
- else
- begin
- {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_blocks := inflate_flush(s,z,r);
- exit;
- end;
- Dec(n);
- b := b or (uLong(p^) shl k);
- Inc(p);
- Inc(k, 8);
- end;
- {DUMPBITS(t);}
- b := b shr t;
- Dec(k, t);
- Inc(j, uInt(b) and inflate_mask[i]);
- {DUMPBITS(i);}
- b := b shr i;
- Dec(k, i);
- i := s.sub.trees.index;
- t := s.sub.trees.table;
- if (i + j > 258 + (t and $1f) + ((t shr 5) and $1f)) or
- ((c = 16) and (i < 1)) then
- begin
- ZFREE(z, s.sub.trees.blens);
- s.mode := BLKBAD;
- z.msg := 'invalid bit length repeat';
- r := Z_DATA_ERROR;
- { update pointers and return }
- 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_blocks := inflate_flush(s,z,r);
- exit;
- end;
- if c = 16 then
- c := s.sub.trees.blens^[i - 1]
- else
- c := 0;
- repeat
- s.sub.trees.blens^[i] := c;
- Inc(i);
- Dec(j);
- until (j=0);
- s.sub.trees.index := i;
- end;
- end; { while }
- s.sub.trees.tb := Z_NULL;
- begin
- bl := 9; { must be <= 9 for lookahead assumptions }
- bd := 6; { must be <= 9 for lookahead assumptions }
- t := s.sub.trees.table;
- t := inflate_trees_dynamic(257 + (t and $1f),
- 1 + ((t shr 5) and $1f),
- s.sub.trees.blens^, bl, bd, tl, td, s.hufts^, z);
- ZFREE(z, s.sub.trees.blens);
- if (t <> Z_OK) then
- begin
- if (t = uInt(Z_DATA_ERROR)) then
- s.mode := BLKBAD;
- r := t;
- { update pointers and return }
- 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_blocks := inflate_flush(s,z,r);
- exit;
- end;
- {$IFDEF DEBUG}
- Tracev('inflate: trees ok');
- {$ENDIF}
- { c renamed to cs }
- cs := inflate_codes_new(bl, bd, tl, td, z);
- if (cs = Z_NULL) then
- begin
- r := Z_MEM_ERROR;
- { update pointers and return }
- 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_blocks := inflate_flush(s,z,r);
- exit;
- end;
- s.sub.decode.codes := cs;
- end;
- s.mode := CODES;
- { yet another falltrough }
- goto start_codes;
- end;
- CODES:
- begin
- start_codes:
- { update pointers }
- 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;
- r := inflate_codes(s, z, r);
- if (r <> Z_STREAM_END) then
- begin
- inflate_blocks := inflate_flush(s, z, r);
- exit;
- end;
- r := Z_OK;
- inflate_codes_free(s.sub.decode.codes, z);
- { load local pointers }
- 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));
- {$IFDEF DEBUG}
- if (ptr2int(q) >= ptr2int(s.read)) then
- Tracev('inflate: codes end '+
- IntToStr(z.total_out + ptr2int(q) - ptr2int(s.read)) + ' total out')
- else
- Tracev('inflate: codes end '+
- IntToStr(z.total_out + ptr2int(s.zend) - ptr2int(s.read) +
- ptr2int(q) - ptr2int(s.window)) + ' total out');
- {$ENDIF}
- if (not s.last) then
- begin
- s.mode := ZTYPE;
- continue; { break for switch statement in C-code }
- end;
- {$ifndef patch112}
- if (k > 7) then { return unused byte, if any }
- begin
- {$IFDEF DEBUG}
- Assert(k < 16, 'inflate_codes grabbed too many bytes');
- {$ENDIF}
- Dec(k, 8);
- Inc(n);
- Dec(p); { can always return one }
- end;
- {$endif}
- s.mode := DRY;
- { another falltrough }
- goto start_dry;
- end;
- DRY:
- begin
- start_dry:
- {FLUSH}
- s.write := q;
- r := inflate_flush(s,z,r);
- q := s.write;
- { not needed anymore, we are done:
- if ptr2int(q) < ptr2int(s.read) then
- m := uInt(ptr2int(s.read)-ptr2int(q)-1)
- else
- m := uInt(ptr2int(s.zend)-ptr2int(q));
- }
- if (s.read <> s.write) then
- begin
- { update pointers and return }
- 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_blocks := inflate_flush(s,z,r);
- exit;
- end;
- s.mode := BLKDONE;
- goto start_blkdone;
- end;
- BLKDONE:
- begin
- start_blkdone:
- r := Z_STREAM_END;
- { update pointers and return }
- 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_blocks := inflate_flush(s,z,r);
- exit;
- end;
- BLKBAD:
- begin
- r := Z_DATA_ERROR;
- { update pointers and return }
- 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_blocks := inflate_flush(s,z,r);
- exit;
- end;
- else
- begin
- r := Z_STREAM_ERROR;
- { update pointers and return }
- 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_blocks := inflate_flush(s,z,r);
- exit;
- end;
- end; { Case s.mode of }
- end;
- function inflate_blocks_free(s : pInflate_blocks_state;
- var z : z_stream) : int;
- begin
- inflate_blocks_reset(s^, z, Z_NULL);
- ZFREE(z, s^.window);
- ZFREE(z, s^.hufts);
- ZFREE(z, s);
- {$IFDEF DEBUG}
- Trace('inflate: blocks freed');
- {$ENDIF}
- inflate_blocks_free := Z_OK;
- end;
- procedure inflate_set_dictionary(var s : inflate_blocks_state;
- const d : array of byte; { dictionary }
- n : uInt); { dictionary length }
- begin
- zmemcpy(s.window, pBytef(@d), n);
- s.write := s.window;
- Inc(s.write, n);
- s.read := s.write;
- end;
- { Returns true if inflate is currently at the end of a block generated
- by Z_SYNC_FLUSH or Z_FULL_FLUSH.
- IN assertion: s <> Z_NULL }
- function inflate_blocks_sync_point(var s : inflate_blocks_state) : int;
- begin
- inflate_blocks_sync_point := int(s.mode = LENS);
- end;
- function inflate_codes_new (bl : uInt;
- bd : uInt;
- tl : pInflate_huft;
- td : pInflate_huft;
- var z : z_stream): pInflate_codes_state;
- var
- c : pInflate_codes_state;
- begin
- c := pInflate_codes_state( ZALLOC(z,1,sizeof(inflate_codes_state)) );
- if (c <> Z_NULL) then
- begin
- c^.mode := START;
- c^.lbits := Byte(bl);
- c^.dbits := Byte(bd);
- c^.ltree := tl;
- c^.dtree := td;
- {$IFDEF DEBUG}
- Tracev('inflate: codes new');
- {$ENDIF}
- end;
- inflate_codes_new := c;
- end;
- function inflate_codes(var s : inflate_blocks_state;
- var z : z_stream;
- r : int) : int;
- var
- j : uInt; { temporary storage }
- 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 }
- f : pBytef; { pointer to copy strings from }
- var
- c : pInflate_codes_state;
- begin
- c := s.sub.decode.codes; { codes state }
- { copy input/output information to locals }
- 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));
- { process input and output based on current state }
- while True do
- case (c^.mode) of
- { waiting for "i:"=input, "o:"=output, "x:"=nothing }
- START: { x: set up for LEN }
- begin
- {$ifndef SLOW}
- if (m >= 258) and (n >= 10) then
- begin
- {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;
- r := inflate_fast(c^.lbits, c^.dbits, c^.ltree, c^.dtree, s, z);
- {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));
- if (r <> Z_OK) then
- begin
- if (r = Z_STREAM_END) then
- c^.mode := WASH
- else
- c^.mode := BADCODE;
- continue; { break for switch-statement in C }
- end;
- end;
- {$endif} { not SLOW }
- c^.sub.code.need := c^.lbits;
- c^.sub.code.tree := c^.ltree;
- c^.mode := LEN; { falltrough }
- end;
- LEN: { i: get length/literal/eob next }
- begin
- j := c^.sub.code.need;
- {NEEDBITS(j);}
- while (k < j) do
- begin
- {NEEDBYTE;}
- if (n <> 0) then
- r :=Z_OK
- else
- begin
- {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_codes := inflate_flush(s,z,r);
- exit;
- end;
- Dec(n);
- b := b or (uLong(p^) shl k);
- Inc(p);
- Inc(k, 8);
- end;
- t := c^.sub.code.tree;
- Inc(t, uInt(b) and inflate_mask[j]);
- {DUMPBITS(t^.bits);}
- b := b shr t^.bits;
- Dec(k, t^.bits);
- e := uInt(t^.exop);
- if (e = 0) then { literal }
- begin
- c^.sub.lit := t^.base;
- {$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}
- c^.mode := LIT;
- continue; { break switch statement }
- end;
- if (e and 16 <> 0) then { length }
- begin
- c^.sub.copy.get := e and 15;
- c^.len := t^.base;
- c^.mode := LENEXT;
- continue; { break C-switch statement }
- end;
- if (e and 64 = 0) then { next table }
- begin
- c^.sub.code.need := e;
- c^.sub.code.tree := @huft_ptr(t)^[t^.base];
- continue; { break C-switch statement }
- end;
- if (e and 32 <> 0) then { end of block }
- begin
- {$IFDEF DEBUG}
- Tracevv('inflate: end of block');
- {$ENDIF}
- c^.mode := WASH;
- continue; { break C-switch statement }
- end;
- c^.mode := BADCODE; { invalid code }
- z.msg := 'invalid literal/length code';
- r := Z_DATA_ERROR;
- {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_codes := inflate_flush(s,z,r);
- exit;
- end;
- LENEXT: { i: getting length extra (have base) }
- begin
- j := c^.sub.copy.get;
- {NEEDBITS(j);}
- while (k < j) do
- begin
- {NEEDBYTE;}
- if (n <> 0) then
- r :=Z_OK
- else
- begin
- {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_codes := inflate_flush(s,z,r);
- exit;
- end;
- Dec(n);
- b := b or (uLong(p^) shl k);
- Inc(p);
- Inc(k, 8);
- end;
- Inc(c^.len, uInt(b and inflate_mask[j]));
- {DUMPBITS(j);}
- b := b shr j;
- Dec(k, j);
- c^.sub.code.need := c^.dbits;
- c^.sub.code.tree := c^.dtree;
- {$IFDEF DEBUG}
- Tracevv('inflate: length '+IntToStr(c^.len));
- {$ENDIF}
- c^.mode := DIST;
- { falltrough }
- end;
- DIST: { i: get distance next }
- begin
- j := c^.sub.code.need;
- {NEEDBITS(j);}
- while (k < j) do
- begin
- {NEEDBYTE;}
- if (n <> 0) then
- r :=Z_OK
- else
- begin
- {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_codes := inflate_flush(s,z,r);
- exit;
- end;
- Dec(n);
- b := b or (uLong(p^) shl k);
- Inc(p);
- Inc(k, 8);
- end;
- t := @huft_ptr(c^.sub.code.tree)^[uInt(b) and inflate_mask[j]];
- {DUMPBITS(t^.bits);}
- b := b shr t^.bits;
- Dec(k, t^.bits);
- e := uInt(t^.exop);
- if (e and 16 <> 0) then { distance }
- begin
- c^.sub.copy.get := e and 15;
- c^.sub.copy.dist := t^.base;
- c^.mode := DISTEXT;
- continue; { break C-switch statement }
- end;
- if (e and 64 = 0) then { next table }
- begin
- c^.sub.code.need := e;
- c^.sub.code.tree := @huft_ptr(t)^[t^.base];
- continue; { break C-switch statement }
- end;
- c^.mode := BADCODE; { invalid code }
- z.msg := 'invalid distance code';
- r := Z_DATA_ERROR;
- {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_codes := inflate_flush(s,z,r);
- exit;
- end;
- DISTEXT: { i: getting distance extra }
- begin
- j := c^.sub.copy.get;
- {NEEDBITS(j);}
- while (k < j) do
- begin
- {NEEDBYTE;}
- if (n <> 0) then
- r :=Z_OK
- else
- begin
- {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_codes := inflate_flush(s,z,r);
- exit;
- end;
- Dec(n);
- b := b or (uLong(p^) shl k);
- Inc(p);
- Inc(k, 8);
- end;
- Inc(c^.sub.copy.dist, uInt(b) and inflate_mask[j]);
- {DUMPBITS(j);}
- b := b shr j;
- Dec(k, j);
- {$IFDEF DEBUG}
- Tracevv('inflate: distance '+ IntToStr(c^.sub.copy.dist));
- {$ENDIF}
- c^.mode := COPY;
- { falltrough }
- end;
- COPY: { o: copying bytes in window, waiting for space }
- begin
- f := q;
- Dec(f, c^.sub.copy.dist);
- if (uInt(ptr2int(q) - ptr2int(s.window)) < c^.sub.copy.dist) then
- begin
- f := s.zend;
- Dec(f, c^.sub.copy.dist - uInt(ptr2int(q) - ptr2int(s.window)));
- end;
- while (c^.len <> 0) do
- begin
- {NEEDOUT}
- if (m = 0) then
- begin
- {WRAP}
- if (q = s.zend) and (s.read <> s.window) then
- begin
- q := s.window;
- if ptr2int(q) < ptr2int(s.read) then
- m := uInt(ptr2int(s.read)-ptr2int(q)-1)
- else
- m := uInt(ptr2int(s.zend)-ptr2int(q));
- end;
- if (m = 0) then
- begin
- {FLUSH}
- s.write := q;
- r := inflate_flush(s,z,r);
- 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));
- {WRAP}
- if (q = s.zend) and (s.read <> s.window) then
- begin
- q := s.window;
- if ptr2int(q) < ptr2int(s.read) then
- m := uInt(ptr2int(s.read)-ptr2int(q)-1)
- else
- m := uInt(ptr2int(s.zend)-ptr2int(q));
- end;
- if (m = 0) then
- begin
- {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_codes := inflate_flush(s,z,r);
- exit;
- end;
- end;
- end;
- r := Z_OK;
- {OUTBYTE( *f++)}
- q^ := f^;
- Inc(q);
- Inc(f);
- Dec(m);
- if (f = s.zend) then
- f := s.window;
- Dec(c^.len);
- end;
- c^.mode := START;
- { C-switch break; not needed }
- end;
- LIT: { o: got literal, waiting for output space }
- begin
- {NEEDOUT}
- if (m = 0) then
- begin
- {WRAP}
- if (q = s.zend) and (s.read <> s.window) then
- begin
- q := s.window;
- if ptr2int(q) < ptr2int(s.read) then
- m := uInt(ptr2int(s.read)-ptr2int(q)-1)
- else
- m := uInt(ptr2int(s.zend)-ptr2int(q));
- end;
- if (m = 0) then
- begin
- {FLUSH}
- s.write := q;
- r := inflate_flush(s,z,r);
- 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));
- {WRAP}
- if (q = s.zend) and (s.read <> s.window) then
- begin
- q := s.window;
- if ptr2int(q) < ptr2int(s.read) then
- m := uInt(ptr2int(s.read)-ptr2int(q)-1)
- else
- m := uInt(ptr2int(s.zend)-ptr2int(q));
- end;
- if (m = 0) then
- begin
- {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_codes := inflate_flush(s,z,r);
- exit;
- end;
- end;
- end;
- r := Z_OK;
- {OUTBYTE(c^.sub.lit);}
- q^ := c^.sub.lit;
- Inc(q);
- Dec(m);
- c^.mode := START;
- {break;}
- end;
- WASH: { o: got eob, possibly more output }
- begin
- {$ifdef patch112}
- if (k > 7) then { return unused byte, if any }
- begin
- {$IFDEF DEBUG}
- Assert(k < 16, 'inflate_codes grabbed too many bytes');
- {$ENDIF}
- Dec(k, 8);
- Inc(n);
- Dec(p); { can always return one }
- end;
- {$endif}
- {FLUSH}
- s.write := q;
- r := inflate_flush(s,z,r);
- 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));
- if (s.read <> s.write) then
- begin
- {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_codes := inflate_flush(s,z,r);
- exit;
- end;
- c^.mode := ZEND;
- { falltrough }
- end;
- ZEND:
- begin
- r := Z_STREAM_END;
- {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_codes := inflate_flush(s,z,r);
- exit;
- end;
- BADCODE: { x: got error }
- begin
- r := Z_DATA_ERROR;
- {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_codes := inflate_flush(s,z,r);
- exit;
- end;
- else
- begin
- r := Z_STREAM_ERROR;
- {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_codes := inflate_flush(s,z,r);
- exit;
- end;
- end;
- {NEED_DUMMY_RETURN - Delphi2+ dumb compilers complain without this }
- inflate_codes := Z_STREAM_ERROR;
- end;
- procedure inflate_codes_free(c : pInflate_codes_state;
- var z : z_stream);
- begin
- ZFREE(z, c);
- {$IFDEF DEBUG}
- Tracev('inflate: codes free');
- {$ENDIF}
- end;
- { 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;
- function inflateReset(var z : z_stream) : int;
- begin
- if (z.state = Z_NULL) then
- begin
- inflateReset := Z_STREAM_ERROR;
- exit;
- end;
- z.total_out := 0;
- z.total_in := 0;
- z.msg := '';
- if z.state^.nowrap then
- z.state^.mode := BLOCKS
- else
- z.state^.mode := METHOD;
- inflate_blocks_reset(z.state^.blocks^, z, Z_NULL);
- {$IFDEF DEBUG}
- Tracev('inflate: reset');
- {$ENDIF}
- inflateReset := Z_OK;
- end;
- function inflateEnd(var z : z_stream) : int;
- begin
- if (z.state = Z_NULL) or not Assigned(z.zfree) then
- begin
- inflateEnd := Z_STREAM_ERROR;
- exit;
- end;
- if (z.state^.blocks <> Z_NULL) then
- inflate_blocks_free(z.state^.blocks, z);
- ZFREE(z, z.state);
- z.state := Z_NULL;
- {$IFDEF DEBUG}
- Tracev('inflate: end');
- {$ENDIF}
- inflateEnd := Z_OK;
- end;
- function inflateInit2_(var z: z_stream;
- w : int;
- const version : string;
- stream_size : int) : int;
- begin
- if (version = '') or (version[1] <> ZLIB_VERSION[1]) or
- (stream_size <> sizeof(z_stream)) then
- begin
- inflateInit2_ := Z_VERSION_ERROR;
- exit;
- end;
- { initialize state }
- { SetLength(strm.msg, 255); }
- z.msg := '';
- if not Assigned(z.zalloc) then
- begin
- z.zalloc := zcalloc;
- z.opaque := voidpf(0);
- end;
- if not Assigned(z.zfree) then
- z.zfree := zcfree;
- z.state := pInternal_state( ZALLOC(z,1,sizeof(internal_state)) );
- if (z.state = Z_NULL) then
- begin
- inflateInit2_ := Z_MEM_ERROR;
- exit;
- end;
- z.state^.blocks := Z_NULL;
- { handle undocumented nowrap option (no zlib header or check) }
- z.state^.nowrap := FALSE;
- if (w < 0) then
- begin
- w := - w;
- z.state^.nowrap := TRUE;
- end;
- { set window size }
- if (w < 8) or (w > 15) then
- begin
- inflateEnd(z);
- inflateInit2_ := Z_STREAM_ERROR;
- exit;
- end;
- z.state^.wbits := uInt(w);
- { create inflate_blocks state }
- if z.state^.nowrap then
- z.state^.blocks := inflate_blocks_new(z, NIL, uInt(1) shl w)
- else
- z.state^.blocks := inflate_blocks_new(z, adler32, uInt(1) shl w);
- if (z.state^.blocks = Z_NULL) then
- begin
- inflateEnd(z);
- inflateInit2_ := Z_MEM_ERROR;
- exit;
- end;
- {$IFDEF DEBUG}
- Tracev('inflate: allocated');
- {$ENDIF}
- { reset state }
- inflateReset(z);
- inflateInit2_ := Z_OK;
- end;
- function inflateInit(var z : z_stream) : int;
- { inflateInit is a macro to allow checking the zlib version
- and the compiler's view of z_stream:
- }
- begin
- inflateInit := inflateInit2_(z, DEF_WBITS, ZLIB_VERSION, sizeof(z_stream));
- end;
- function inflateInit_(z : z_streamp;
- const version : string;
- stream_size : int) : int;
- begin
- { initialize state }
- if (z = Z_NULL) then
- inflateInit_ := Z_STREAM_ERROR
- else
- inflateInit_ := inflateInit2_(z^, DEF_WBITS, version, stream_size);
- end;
- function inflate(var z : z_stream;
- f : int) : int;
- var
- r : int;
- b : uInt;
- begin
- if (z.state = Z_NULL) or (z.next_in = Z_NULL) then
- begin
- inflate := Z_STREAM_ERROR;
- exit;
- end;
- if f = Z_FINISH then
- f := Z_BUF_ERROR
- else
- f := Z_OK;
- r := Z_BUF_ERROR;
- while True do
- case (z.state^.mode) of
- BLOCKS:
- begin
- r := inflate_blocks(z.state^.blocks^, z, r);
- if (r = Z_DATA_ERROR) then
- begin
- z.state^.mode := BAD;
- z.state^.sub.marker := 0; { can try inflateSync }
- continue; { break C-switch }
- end;
- if (r = Z_OK) then
- r := f;
- if (r <> Z_STREAM_END) then
- begin
- inflate := r;
- exit;
- end;
- r := f;
- inflate_blocks_reset(z.state^.blocks^, z, @z.state^.sub.check.was);
- if (z.state^.nowrap) then
- begin
- z.state^.mode := DONE;
- continue; { break C-switch }
- end;
- z.state^.mode := CHECK4; { falltrough }
- end;
- CHECK4:
- begin
- {NEEDBYTE}
- if (z.avail_in = 0) then
- begin
- inflate := r;
- exit;
- end;
- r := f;
- {z.state^.sub.check.need := uLong(NEXTBYTE(z)) shl 24;}
- Dec(z.avail_in);
- Inc(z.total_in);
- z.state^.sub.check.need := uLong(z.next_in^) shl 24;
- Inc(z.next_in);
- z.state^.mode := CHECK3; { falltrough }
- end;
- CHECK3:
- begin
- {NEEDBYTE}
- if (z.avail_in = 0) then
- begin
- inflate := r;
- exit;
- end;
- r := f;
- {Inc( z.state^.sub.check.need, uLong(NEXTBYTE(z)) shl 16);}
- Dec(z.avail_in);
- Inc(z.total_in);
- Inc(z.state^.sub.check.need, uLong(z.next_in^) shl 16);
- Inc(z.next_in);
- z.state^.mode := CHECK2; { falltrough }
- end;
- CHECK2:
- begin
- {NEEDBYTE}
- if (z.avail_in = 0) then
- begin
- inflate := r;
- exit;
- end;
- r := f;
- {Inc( z.state^.sub.check.need, uLong(NEXTBYTE(z)) shl 8);}
- Dec(z.avail_in);
- Inc(z.total_in);
- Inc(z.state^.sub.check.need, uLong(z.next_in^) shl 8);
- Inc(z.next_in);
- z.state^.mode := CHECK1; { falltrough }
- end;
- CHECK1:
- begin
- {NEEDBYTE}
- if (z.avail_in = 0) then
- begin
- inflate := r;
- exit;
- end;
- r := f;
- {Inc( z.state^.sub.check.need, uLong(NEXTBYTE(z)) );}
- Dec(z.avail_in);
- Inc(z.total_in);
- Inc(z.state^.sub.check.need, uLong(z.next_in^) );
- Inc(z.next_in);
- if (z.state^.sub.check.was <> z.state^.sub.check.need) then
- begin
- z.state^.mode := BAD;
- z.msg := 'incorrect data check';
- z.state^.sub.marker := 5; { can't try inflateSync }
- continue; { break C-switch }
- end;
- {$IFDEF DEBUG}
- Tracev('inflate: zlib check ok');
- {$ENDIF}
- z.state^.mode := DONE; { falltrough }
- end;
- DONE:
- begin
- inflate := Z_STREAM_END;
- exit;
- end;
- METHOD:
- begin
- {NEEDBYTE}
- if (z.avail_in = 0) then
- begin
- inflate := r;
- exit;
- end;
- r := f; {}
- {z.state^.sub.method := NEXTBYTE(z);}
- Dec(z.avail_in);
- Inc(z.total_in);
- z.state^.sub.method := z.next_in^;
- Inc(z.next_in);
- if ((z.state^.sub.method and $0f) <> Z_DEFLATED) then
- begin
- z.state^.mode := BAD;
- z.msg := 'unknown compression method';
- z.state^.sub.marker := 5; { can't try inflateSync }
- continue; { break C-switch }
- end;
- if ((z.state^.sub.method shr 4) + 8 > z.state^.wbits) then
- begin
- z.state^.mode := BAD;
- z.msg := 'invalid window size';
- z.state^.sub.marker := 5; { can't try inflateSync }
- continue; { break C-switch }
- end;
- z.state^.mode := FLAG;
- { fall trough }
- end;
- FLAG:
- begin
- {NEEDBYTE}
- if (z.avail_in = 0) then
- begin
- inflate := r;
- exit;
- end;
- r := f; {}
- {b := NEXTBYTE(z);}
- Dec(z.avail_in);
- Inc(z.total_in);
- b := z.next_in^;
- Inc(z.next_in);
- if (((z.state^.sub.method shl 8) + b) mod 31) <> 0 then {% mod ?}
- begin
- z.state^.mode := BAD;
- z.msg := 'incorrect header check';
- z.state^.sub.marker := 5; { can't try inflateSync }
- continue; { break C-switch }
- end;
- {$IFDEF DEBUG}
- Tracev('inflate: zlib header ok');
- {$ENDIF}
- if ((b and PRESET_DICT) = 0) then
- begin
- z.state^.mode := BLOCKS;
- continue; { break C-switch }
- end;
- z.state^.mode := DICT4;
- { falltrough }
- end;
- DICT4:
- begin
- if (z.avail_in = 0) then
- begin
- inflate := r;
- exit;
- end;
- r := f;
- {z.state^.sub.check.need := uLong(NEXTBYTE(z)) shl 24;}
- Dec(z.avail_in);
- Inc(z.total_in);
- z.state^.sub.check.need := uLong(z.next_in^) shl 24;
- Inc(z.next_in);
- z.state^.mode := DICT3; { falltrough }
- end;
- DICT3:
- begin
- if (z.avail_in = 0) then
- begin
- inflate := r;
- exit;
- end;
- r := f;
- {Inc(z.state^.sub.check.need, uLong(NEXTBYTE(z)) shl 16);}
- Dec(z.avail_in);
- Inc(z.total_in);
- Inc(z.state^.sub.check.need, uLong(z.next_in^) shl 16);
- Inc(z.next_in);
- z.state^.mode := DICT2; { falltrough }
- end;
- DICT2:
- begin
- if (z.avail_in = 0) then
- begin
- inflate := r;
- exit;
- end;
- r := f;
- {Inc(z.state^.sub.check.need, uLong(NEXTBYTE(z)) shl 8);}
- Dec(z.avail_in);
- Inc(z.total_in);
- Inc(z.state^.sub.check.need, uLong(z.next_in^) shl 8);
- Inc(z.next_in);
- z.state^.mode := DICT1; { falltrough }
- end;
- DICT1:
- begin
- if (z.avail_in = 0) then
- begin
- inflate := r;
- exit;
- end;
- { r := f; --- wird niemals benutzt }
- {Inc(z.state^.sub.check.need, uLong(NEXTBYTE(z)) );}
- Dec(z.avail_in);
- Inc(z.total_in);
- Inc(z.state^.sub.check.need, uLong(z.next_in^) );
- Inc(z.next_in);
- z.adler := z.state^.sub.check.need;
- z.state^.mode := DICT0;
- inflate := Z_NEED_DICT;
- exit;
- end;
- DICT0:
- begin
- z.state^.mode := BAD;
- z.msg := 'need dictionary';
- z.state^.sub.marker := 0; { can try inflateSync }
- inflate := Z_STREAM_ERROR;
- exit;
- end;
- BAD:
- begin
- inflate := Z_DATA_ERROR;
- exit;
- end;
- else
- begin
- inflate := Z_STREAM_ERROR;
- exit;
- end;
- end;
- {$ifdef NEED_DUMMY_result}