📄 ztvdeflate.pas
字号:
If (Flush <> Z_FINISH) Then
Begin
Result := Z_OK;
Exit;
End;
If (s^.noheader <> 0) Then
Begin
Result := Z_STREAM_END;
Exit;
End;
{ Write the lib trailer (adler32) }
putShortMSB(s^, word(strm.adler Shr 16));
putShortMSB(s^, word(strm.adler And $FFFF));
flush_pending(strm);
s^.noheader := -1;
If (s^.pending <> 0) Then
Result := Z_OK
Else
Result := Z_STREAM_END;
End;
//-------------------------------------------------------------
Function deflateCopy(dest, source: ztv_streamp): _int;
{$IFNDEF MAXSEG_64K}
Var
ds: deflate_state_ptr;
ss: deflate_state_ptr;
overlay: pushfArray;
{$ENDIF}
Begin
{$IFDEF MAXSEG_64K}
Result := Z_STREAM_ERROR;
Exit;
{$ELSE}
If (source = Z_NULL) Or (dest = Z_NULL) Or (source^.state = Z_NULL) Then
Begin
Result := Z_STREAM_ERROR;
Exit;
End;
ss := deflate_state_ptr(source^.state);
dest^ := source^;
ds := deflate_state_ptr(ZALLOC(dest^, 1, SizeOf(deflate_state)));
If (ds = Z_NULL) Then
Begin
Result := Z_MEM_ERROR;
Exit;
End;
dest^.state := pInternal_state(ds);
ds^ := ss^;
ds^.strm := dest;
ds^.window := pzByteArray(ZALLOC(dest^, ds^.w_size, 2 * SizeOf(Byte)));
ds^.prev := pzPosfArray(ZALLOC(dest^, ds^.w_size, SizeOf(_Pos)));
ds^.head := pzPosfArray(ZALLOC(dest^, ds^.hash_size, SizeOf(_Pos)));
overlay := pushfArray(ZALLOC(dest^, ds^.lit_bufsize, SizeOf(ush) + 2));
ds^.pending_buf := pzByteArray(overlay);
If (ds^.window = Z_NULL) Or (ds^.prev = Z_NULL) Or (ds^.head = Z_NULL)
Or (ds^.pending_buf = Z_NULL) Then
Begin
_deflateEnd(dest^);
Result := Z_MEM_ERROR;
Exit;
End;
CopyMem(@ss^.window^, @ds^.window^, ds^.w_size * 2 * SizeOf(Byte));
CopyMem(@ss^.prev^, @ds^.prev^, ds^.w_size * SizeOf(_Pos));
CopyMem(@ss^.head^, @ds^.head^, ds^.hash_size * SizeOf(_Pos));
CopyMem(@ss^.pending_buf^, @ds^.pending_buf^, word(ds^.pending_buf_size));
ds^.pending_out := @ds^.pending_buf^[ptr2int(ss^.pending_out) - ptr2int(ss^.pending_buf)];
ds^.d_buf := pushfArray(@overlay^[ds^.lit_bufsize Div SizeOf(ush)]);
ds^.l_buf := puchfArray(@ds^.pending_buf^[(1 + SizeOf(ush)) * ds^.lit_bufsize]);
ds^.l_desc.dyn_tree := tree_ptr(@ds^.dyn_ltree);
ds^.d_desc.dyn_tree := tree_ptr(@ds^.dyn_dtree);
ds^.bl_desc.dyn_tree := tree_ptr(@ds^.bl_tree);
Result := Z_OK;
{$ENDIF}
End;
//-------------------------------------------------------------
Function read_buf(strm: ztv_streamp; Buf: _pBytef; size: _unsigned): _int;
Var
Len: _unsigned;
Begin
Len := strm^.avail_in;
If (Len > size) Then
Len := size;
If (Len = 0) Then
Begin
Result := 0;
Exit;
End;
Dec(strm^.avail_in, Len);
If deflate_state_ptr(strm^.state)^.noheader = 0 Then
strm^.adler := _adler(strm^.adler, strm^.next_in, Len);
//CopyMem(@strm^.next_in^, @Buf^, Len);
Move(strm^.next_in^, Buf^, Len);
If (Not strm^.cb.Protect) Then
Crc32_buf(@Buf^, Len, strm^.cb.CRC);
inc(strm^.next_in, Len);
strm^.total_in := strm^.total_in + Len;
Result := _int(Len);
End;
//-------------------------------------------------------------
Procedure lm_init(Var s: deflate_state);
Begin
s.window_size := longint(u_long(2) * u_long(s.w_size));
s.head^[s.hash_size - 1] := ZNIL;
zmemzero(_pBytef(s.head), _unsigned(s.hash_size - 1) * SizeOf(s.head^[0]));
{ Set the default configuration parameters: }
s.max_lazy_match := configuration_table[s.level].max_lazy;
s.good_match := configuration_table[s.level].good_length;
s.nice_match := configuration_table[s.level].nice_length;
s.max_chain_length := configuration_table[s.level].max_chain;
s.strstart := 0;
s.block_start := longint(0);
s.lookahead := 0;
s.prev_length := MIN_MATCH - 1;
s.match_length := MIN_MATCH - 1;
s.match_available := False;
s.ins_h := 0;
End;
//-------------------------------------------------------------
{.$IFNDEF ASMV}
{$IFNDEF FASTEST}
Function longest_match(Var s: deflate_state;
cur_match: IPos { current match }
): word;
Label
nextstep;
Var
chain_length: _unsigned; { max hash chain length }
{register} Scan: _pBytef; { current string }
{register} match: _pBytef; { matched string }
{register} Len: _int; { length of current match }
best_len: _int; { best match length so far }
nice_match: _int; { stop if match LongInt enough }
limit: IPos;
prev: pzPosfArray;
wmask: word;
{$IFDEF UNALIGNED_OK}
{register} strend: _pBytef;
{register} scan_start: ush;
{register} scan_end: ush;
{$ELSE}
{register} strend: _pBytef;
{register} scan_end1: Byte;
{register} scan_end: Byte;
{$ENDIF}
Var
MAX_DIST: word;
Begin
chain_length := s.max_chain_length; { max hash chain length }
Scan := @(s.window^[s.strstart]);
best_len := s.prev_length; { best match length so far }
nice_match := s.nice_match; { stop if match LongInt enough }
{$IFDEF DEFLATE64}
MAX_DIST := s.w_size - MIN_LOOKAHEAD_DEF64;
{$ELSE}
MAX_DIST := s.w_size - MIN_LOOKAHEAD;
{$ENDIF}
{In order to simplify the code, particularly on 16 bit machines, match
distances are limited to MAX_DIST instead of WSIZE. }
If s.strstart > IPos(MAX_DIST) Then
limit := s.strstart - IPos(MAX_DIST)
Else
limit := ZNIL;
{ Stop when cur_match becomes <= limit. To simplify the code,
we prevent matches with the string of window index 0. }
prev := s.prev;
wmask := s.w_mask;
{$IFDEF UNALIGNED_OK}
{ Compare two bytes at a time. Note: this is not always beneficial.
Try with and without -DUNALIGNED_OK to check. }
strend := _pBytef(@(s.window^[s.strstart + MAX_MATCH - 1]));
scan_start := pushf(Scan)^;
scan_end := pushfArray(Scan)^[best_len - 1]; { fix }
{$ELSE}
strend := _pBytef(@(s.window^[s.strstart + MAX_MATCH]));
{$IFOPT R+}{$R-}{$DEFINE NoRangeCheck}{$ENDIF}
scan_end1 := pzByteArray(Scan)^[best_len - 1];
{$IFDEF NoRangeCheck}{$R+}{$UNDEF NoRangeCheck}{$ENDIF}
scan_end := pzByteArray(Scan)^[best_len];
{$ENDIF}
If (s.prev_length >= s.good_match) Then
chain_length := chain_length Shr 2;
If (word(nice_match) > s.lookahead) Then
nice_match := s.lookahead;
Repeat
match := @(s.window^[cur_match]);
{$UNDEF DO_UNALIGNED_OK}
{$IFDEF UNALIGNED_OK}
{$IFDEF MAX_MATCH_IS_258}
{$DEFINE DO_UNALIGNED_OK}
{$ENDIF}
{$ENDIF}
{$IFDEF DO_UNALIGNED_OK}
{ This code assumes sizeof(_unsigned short) = 2. Do not use
UNALIGNED_OK if your compiler uses a different size. }
{$IFOPT R+}{$R-}{$DEFINE NoRangeCheck}{$ENDIF}
If (pushfArray(match)^[best_len - 1] <> scan_end) Or
(pushf(match)^ <> scan_start) Then
Goto nextstep; {continue;}
{$IFDEF NoRangeCheck}{$R+}{$UNDEF NoRangeCheck}{$ENDIF}
inc(Scan);
inc(match);
Repeat
inc(Scan, 2);
inc(match, 2);
If (pushf(Scan)^ <> pushf(match)^) Then break;
inc(Scan, 2);
inc(match, 2);
If (pushf(Scan)^ <> pushf(match)^) Then break;
inc(Scan, 2);
inc(match, 2);
If (pushf(Scan)^ <> pushf(match)^) Then break;
inc(Scan, 2);
inc(match, 2);
If (pushf(Scan)^ <> pushf(match)^) Then break;
Until (ptr2int(Scan) >= ptr2int(strend));
//The "do while" generates better code on most compilers }
//While (ptr2int(Scan) < ptr2int(strend)) Do
//Begin
// inc(Scan, 2);
// inc(match, 2);
// If (pushf(Scan)^ <> pushf(match)^) Then break;
//End;
If (Scan^ = match^) Then
inc(Scan);
Len := (MAX_MATCH - 1) - _int(ptr2int(strend)) + _int(ptr2int(Scan));
Scan := strend;
Dec(Scan, (MAX_MATCH - 1));
{$ELSE} { UNALIGNED_OK }
{$IFOPT R+}{$R-}{$DEFINE NoRangeCheck}{$ENDIF}
If (pzByteArray(match)^[best_len] <> scan_end) Or
(pzByteArray(match)^[best_len - 1] <> scan_end1) Or
(match^ <> Scan^) Then
Goto nextstep; {continue;}
{$IFDEF NoRangeCheck}{$R+}{$UNDEF NoRangeCheck}{$ENDIF}
inc(match);
If (match^ <> pzByteArray(Scan)^[1]) Then
Goto nextstep; {continue;}
inc(Scan, 2);
inc(match);
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));
{While (ptr2int(Scan) < ptr2int(strend)) Do
Begin
inc(Scan);
inc(match);
If (Scan^ <> match^) Then break;
End;}
Len := MAX_MATCH - _int(ptr2int(strend) - ptr2int(Scan));
Scan := strend;
Dec(Scan, MAX_MATCH);
{$ENDIF} { UNALIGNED_OK }
If (Len > best_len) Then
Begin
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 (word(best_len) <= s.lookahead) Then
longest_match := word(best_len)
Else
longest_match := s.lookahead;
End;
{.$ENDIF}{ ASMV }
//-------------------------------------------------------------
{$ELSE} { FASTEST }
Function longest_match(Var s
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -