📄 zdeflate.pas
字号:
end;
if s^.noheader <> 0 then
s^.status := BUSY_STATE
else
s^.status := INIT_STATE;
strm.adler := 1;
s^.last_flush := Z_NO_FLUSH;
_tr_init(s^);
lm_init(s^);
deflateReset := Z_OK;
end;
{ ======================================================================== }
function deflateParams(var strm : z_stream;
level : int;
strategy : int) : int;
var
s : deflate_state_ptr;
func : compress_func;
err : int;
begin
err := Z_OK;
if {(@strm = Z_NULL) or} (strm.state = Z_NULL) then
begin
deflateParams := Z_STREAM_ERROR;
exit;
end;
s := deflate_state_ptr(strm.state);
if (level = Z_DEFAULT_COMPRESSION) then
begin
level := 6;
end;
if (level < 0) or (level > 9) or (strategy < 0)
or (strategy > Z_HUFFMAN_ONLY) then
begin
deflateParams := Z_STREAM_ERROR;
exit;
end;
func := configuration_table[s^.level].func;
if (@func <> @configuration_table[level].func)
and (strm.total_in <> 0) then
begin
{ Flush the last buffer: }
err := deflate(strm, Z_PARTIAL_FLUSH);
end;
if (s^.level <> level) then
begin
s^.level := level;
s^.max_lazy_match := configuration_table[level].max_lazy;
s^.good_match := configuration_table[level].good_length;
s^.nice_match := configuration_table[level].nice_length;
s^.max_chain_length := configuration_table[level].max_chain;
end;
s^.strategy := strategy;
deflateParams := err;
end;
{ =========================================================================
Put a short in the pending buffer. The 16-bit value is put in MSB order.
IN assertion: the stream state is correct and there is enough room in
pending_buf. }
{local}
procedure putShortMSB (var s : deflate_state; b : uInt);
begin
s.pending_buf^[s.pending] := Byte(b shr 8);
Inc(s.pending);
s.pending_buf^[s.pending] := Byte(b and $ff);
Inc(s.pending);
end;
{ =========================================================================
Flush as much pending output as possible. All deflate() output goes
through this function so some applications may wish to modify it
to avoid allocating a large strm^.next_out buffer and copying into it.
(See also read_buf()). }
{local}
procedure flush_pending(var strm : z_stream);
var
len : unsigned;
s : deflate_state_ptr;
begin
s := deflate_state_ptr(strm.state);
len := s^.pending;
if (len > strm.avail_out) then
len := strm.avail_out;
if (len = 0) then
exit;
zmemcpy(strm.next_out, s^.pending_out, len);
Inc(strm.next_out, len);
Inc(s^.pending_out, len);
Inc(strm.total_out, len);
Dec(strm.avail_out, len);
Dec(s^.pending, len);
if (s^.pending = 0) then
begin
s^.pending_out := pBytef(s^.pending_buf);
end;
end;
{ ========================================================================= }
function deflate (var strm : z_stream; flush : int) : int;
var
old_flush : int; { value of flush param for previous deflate call }
s : deflate_state_ptr;
var
header : uInt;
level_flags : uInt;
var
bstate : block_state;
begin
if {(@strm = Z_NULL) or} (strm.state = Z_NULL)
or (flush > Z_FINISH) or (flush < 0) then
begin
deflate := Z_STREAM_ERROR;
exit;
end;
s := deflate_state_ptr(strm.state);
if (strm.next_out = Z_NULL) or
((strm.next_in = Z_NULL) and (strm.avail_in <> 0)) or
((s^.status = FINISH_STATE) and (flush <> Z_FINISH)) then
begin
{ERR_RETURN(strm^, Z_STREAM_ERROR);}
strm.msg := z_errmsg[z_errbase - Z_STREAM_ERROR];
deflate := Z_STREAM_ERROR;
exit;
end;
if (strm.avail_out = 0) then
begin
{ERR_RETURN(strm^, Z_BUF_ERROR);}
strm.msg := z_errmsg[z_errbase - Z_BUF_ERROR];
deflate := Z_BUF_ERROR;
exit;
end;
s^.strm := @strm; { just in case }
old_flush := s^.last_flush;
s^.last_flush := flush;
{ Write the zlib header }
if (s^.status = INIT_STATE) then
begin
header := (Z_DEFLATED + ((s^.w_bits-8) shl 4)) shl 8;
level_flags := (s^.level-1) shr 1;
if (level_flags > 3) then
level_flags := 3;
header := header or (level_flags shl 6);
if (s^.strstart <> 0) then
header := header or PRESET_DICT;
Inc(header, 31 - (header mod 31));
s^.status := BUSY_STATE;
putShortMSB(s^, header);
{ Save the adler32 of the preset dictionary: }
if (s^.strstart <> 0) then
begin
putShortMSB(s^, uInt(strm.adler shr 16));
putShortMSB(s^, uInt(strm.adler and $ffff));
end;
strm.adler := long(1);
end;
{ Flush as much pending output as possible }
if (s^.pending <> 0) then
begin
flush_pending(strm);
if (strm.avail_out = 0) then
begin
{ Since avail_out is 0, deflate will be called again with
more output space, but possibly with both pending and
avail_in equal to zero. There won't be anything to do,
but this is not an error situation so make sure we
return OK instead of BUF_ERROR at next call of deflate: }
s^.last_flush := -1;
deflate := Z_OK;
exit;
end;
{ Make sure there is something to do and avoid duplicate consecutive
flushes. For repeated and useless calls with Z_FINISH, we keep
returning Z_STREAM_END instead of Z_BUFF_ERROR. }
end
else
if (strm.avail_in = 0) and (flush <= old_flush)
and (flush <> Z_FINISH) then
begin
{ERR_RETURN(strm^, Z_BUF_ERROR);}
strm.msg := z_errmsg[z_errbase - Z_BUF_ERROR];
deflate := Z_BUF_ERROR;
exit;
end;
{ User must not provide more input after the first FINISH: }
if (s^.status = FINISH_STATE) and (strm.avail_in <> 0) then
begin
{ERR_RETURN(strm^, Z_BUF_ERROR);}
strm.msg := z_errmsg[z_errbase - Z_BUF_ERROR];
deflate := Z_BUF_ERROR;
exit;
end;
{ Start a new block or continue the current one. }
if (strm.avail_in <> 0) or (s^.lookahead <> 0)
or ((flush <> Z_NO_FLUSH) and (s^.status <> FINISH_STATE)) then
begin
bstate := configuration_table[s^.level].func(s^, flush);
if (bstate = finish_started) or (bstate = finish_done) then
s^.status := FINISH_STATE;
if (bstate = need_more) or (bstate = finish_started) then
begin
if (strm.avail_out = 0) then
s^.last_flush := -1; { avoid BUF_ERROR next call, see above }
deflate := Z_OK;
exit;
{ If flush != Z_NO_FLUSH && avail_out == 0, the next call
of deflate should use the same flush parameter to make sure
that the flush is complete. So we don't have to output an
empty block here, this will be done at next call. This also
ensures that for a very small output buffer, we emit at most
one empty block. }
end;
if (bstate = block_done) then
begin
if (flush = Z_PARTIAL_FLUSH) then
_tr_align(s^)
else
begin { FULL_FLUSH or SYNC_FLUSH }
_tr_stored_block(s^, pcharf(NIL), Long(0), FALSE);
{ For a full flush, this empty block will be recognized
as a special marker by inflate_sync(). }
if (flush = Z_FULL_FLUSH) then
begin
{macro CLEAR_HASH(s);} { forget history }
s^.head^[s^.hash_size-1] := ZNIL;
zmemzero(pBytef(s^.head), unsigned(s^.hash_size-1)*sizeof(s^.head^[0]));
end;
end;
flush_pending(strm);
if (strm.avail_out = 0) then
begin
s^.last_flush := -1; { avoid BUF_ERROR at next call, see above }
deflate := Z_OK;
exit;
end;
end;
end;
{$IFDEF DEBUG}
Assert(strm.avail_out > 0, 'bug2');
{$ENDIF}
if (flush <> Z_FINISH) then
begin
deflate := Z_OK;
exit;
end;
if (s^.noheader <> 0) then
begin
deflate := Z_STREAM_END;
exit;
end;
{ Write the zlib trailer (adler32) }
putShortMSB(s^, uInt(strm.adler shr 16));
putShortMSB(s^, uInt(strm.adler and $ffff));
flush_pending(strm);
{ If avail_out is zero, the application will call deflate again
to flush the rest. }
s^.noheader := -1; { write the trailer only once! }
if s^.pending <> 0 then
deflate := Z_OK
else
deflate := Z_STREAM_END;
end;
{ ========================================================================= }
function deflateEnd (var strm : z_stream) : int;
var
status : int;
s : deflate_state_ptr;
begin
if {(@strm = Z_NULL) or} (strm.state = Z_NULL) then
begin
deflateEnd := Z_STREAM_ERROR;
exit;
end;
s := deflate_state_ptr(strm.state);
status := s^.status;
if (status <> INIT_STATE) and (status <> BUSY_STATE) and
(status <> FINISH_STATE) then
begin
deflateEnd := Z_STREAM_ERROR;
exit;
end;
{ Deallocate in reverse order of allocations: }
TRY_FREE(strm, s^.pending_buf);
TRY_FREE(strm, s^.head);
TRY_FREE(strm, s^.prev);
TRY_FREE(strm, s^.window);
ZFREE(strm, s);
strm.state := Z_NULL;
if status = BUSY_STATE then
deflateEnd := Z_DATA_ERROR
else
deflateEnd := Z_OK;
end;
{ =========================================================================
Copy the source state to the destination state.
To simplify the source, this is not supported for 16-bit MSDOS (which
doesn't have enough memory anyway to duplicate compression states). }
{ ========================================================================= }
function deflateCopy (dest, source : z_streamp) : int;
{$ifndef MAXSEG_64K}
var
ds : deflate_state_ptr;
ss : deflate_state_ptr;
overlay : pushfArray;
{$endif}
begin
{$ifdef MAXSEG_64K}
deflateCopy := Z_STREAM_ERROR;
exit;
{$else}
if (source = Z_NULL) or (dest = Z_NULL) or (source^.state = Z_NULL) then
begin
deflateCopy := 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
deflateCopy := Z_MEM_ERROR;
exit;
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -