📄 gzio.pas
字号:
gzputc := int(ord(c))
{$ELSE}
gzputc := int(c)
{$ENDIF}
else
gzputc := -1;
end;
{ GZPUTS ====================================================================
Writes the given null-terminated string to the compressed file, excluding
the terminating null character.
gzputs returns the number of characters written, or -1 in case of error.
============================================================================}
function gzputs (f:gzfile; s:PChar) : int;
begin
gzputs := gzwrite (f, voidp(s), strlen(s));
end;
{ DO_FLUSH ==================================================================
Flushes all pending output into the compressed file.
The parameter flush is as in the zdeflate() function.
============================================================================}
function do_flush (f:gzfile; flush:int) : int;
var
len : uInt;
done : boolean;
s : gz_streamp;
written : integer;
begin
done := false;
s := gz_streamp(f);
if (s = NIL) or (s^.mode <> 'w') then begin
do_flush := Z_STREAM_ERROR;
exit;
end;
s^.stream.avail_in := 0; { should be zero already anyway }
while true do begin
len := Z_BUFSIZE - s^.stream.avail_out;
if (len <> 0) then begin
{$I-}
blockwrite(s^.gzfile, s^.outbuf^, len, written);
{$I+}
if (written <> len) then begin
s^.z_err := Z_ERRNO;
do_flush := Z_ERRNO;
exit;
end;
s^.stream.next_out := s^.outbuf;
s^.stream.avail_out := Z_BUFSIZE;
end;
if (done = true) then break;
s^.z_err := deflate(s^.stream, flush);
{ Ignore the second of two consecutive flushes: }
if (len = 0) and (s^.z_err = Z_BUF_ERROR) then s^.z_err := Z_OK;
{ deflate has finished flushing only when it hasn't used up
all the available space in the output buffer: }
done := (s^.stream.avail_out <> 0) or (s^.z_err = Z_STREAM_END);
if (s^.z_err <> Z_OK) and (s^.z_err <> Z_STREAM_END) then break;
end; {WHILE}
if (s^.z_err = Z_STREAM_END) then do_flush:=Z_OK else do_flush:=s^.z_err;
end;
{ GZFLUSH ===================================================================
Flushes all pending output into the compressed file.
The parameter flush is as in the zdeflate() function.
The return value is the zlib error number (see function gzerror below).
gzflush returns Z_OK if the flush parameter is Z_FINISH and all output
could be flushed.
gzflush should be called only when strictly necessary because it can
degrade compression.
============================================================================}
function gzflush (f:gzfile; flush:int) : int;
var
err : int;
s : gz_streamp;
begin
s := gz_streamp(f);
err := do_flush (f, flush);
if (err <> 0) then begin
gzflush := err;
exit;
end;
if (s^.z_err = Z_STREAM_END) then gzflush := Z_OK else gzflush := s^.z_err;
end;
{$ENDIF} (* NO DEFLATE *)
{ GZREWIND ==================================================================
Rewinds input file.
============================================================================}
function gzrewind (f:gzFile) : int;
var
s:gz_streamp;
begin
s := gz_streamp(f);
if (s = NIL) or (s^.mode <> 'r') then begin
gzrewind := -1;
exit;
end;
s^.z_err := Z_OK;
s^.z_eof := false;
s^.stream.avail_in := 0;
s^.stream.next_in := s^.inbuf;
if (s^.startpos = 0) then begin { not a compressed file }
{$I-}
seek (s^.gzfile, 0);
{$I+}
gzrewind := 0;
exit;
end;
inflateReset(s^.stream);
{$I-}
seek (s^.gzfile, s^.startpos);
{$I+}
gzrewind := int(IOResult);
exit;
end;
{ GZSEEK ====================================================================
Sets the starting position for the next gzread or gzwrite on the given
compressed file. The offset represents a number of bytes from the beginning
of the uncompressed stream.
gzseek returns the resulting offset, or -1 in case of error.
SEEK_END is not implemented, returns error.
In this version of the library, gzseek can be extremely slow.
============================================================================}
function gzseek (f:gzfile; offset:z_off_t; whence:int) : z_off_t;
var
s : gz_streamp;
size : uInt;
begin
s := gz_streamp(f);
if (s = NIL) or (whence = SEEK_END) or (s^.z_err = Z_ERRNO)
or (s^.z_err = Z_DATA_ERROR) then begin
gzseek := z_off_t(-1);
exit;
end;
if (s^.mode = 'w') then begin
{$IFDEF NO_DEFLATE}
gzseek := z_off_t(-1);
exit;
{$ELSE}
if (whence = SEEK_SET) then dec(offset, s^.stream.total_out);
if (offset < 0) then begin;
gzseek := z_off_t(-1);
exit;
end;
{ At this point, offset is the number of zero bytes to write. }
if (s^.inbuf = Z_NULL) then begin
GetMem (s^.inbuf, Z_BUFSIZE);
zmemzero(s^.inbuf, Z_BUFSIZE);
end;
while (offset > 0) do begin
size := Z_BUFSIZE;
if (offset < Z_BUFSIZE) then size := uInt(offset);
size := gzwrite(f, s^.inbuf, size);
if (size = 0) then begin
gzseek := z_off_t(-1);
exit;
end;
dec (offset,size);
end;
gzseek := z_off_t(s^.stream.total_in);
exit;
{$ENDIF}
end;
{ Rest of function is for reading only }
{ compute absolute position }
if (whence = SEEK_CUR) then inc (offset, s^.stream.total_out);
if (offset < 0) then begin
gzseek := z_off_t(-1);
exit;
end;
if (s^.transparent = true) then begin
s^.stream.avail_in := 0;
s^.stream.next_in := s^.inbuf;
{$I-}
seek (s^.gzfile, offset);
{$I+}
if (IOResult <> 0) then begin
gzseek := z_off_t(-1);
exit;
end;
s^.stream.total_in := uLong(offset);
s^.stream.total_out := uLong(offset);
gzseek := z_off_t(offset);
exit;
end;
{ For a negative seek, rewind and use positive seek }
if (uLong(offset) >= s^.stream.total_out)
then dec (offset, s^.stream.total_out)
else if (gzrewind(f) <> 0) then begin
gzseek := z_off_t(-1);
exit;
end;
{ offset is now the number of bytes to skip. }
if (offset <> 0) and (s^.outbuf = Z_NULL)
then GetMem (s^.outbuf, Z_BUFSIZE);
while (offset > 0) do begin
size := Z_BUFSIZE;
if (offset < Z_BUFSIZE) then size := int(offset);
size := gzread (f, s^.outbuf, size);
if (size <= 0) then begin
gzseek := z_off_t(-1);
exit;
end;
dec(offset, size);
end;
gzseek := z_off_t(s^.stream.total_out);
end;
{ GZTELL ====================================================================
Returns the starting position for the next gzread or gzwrite on the
given compressed file. This position represents a number of bytes in the
uncompressed data stream.
============================================================================}
function gztell (f:gzfile) : z_off_t;
begin
gztell := gzseek (f, 0, SEEK_CUR);
end;
{ GZEOF =====================================================================
Returns TRUE when EOF has previously been detected reading the given
input stream, otherwise FALSE.
============================================================================}
function gzeof (f:gzfile) : boolean;
var
s:gz_streamp;
begin
s := gz_streamp(f);
if (s=NIL) or (s^.mode<>'r') then
gzeof := false
else
gzeof := s^.z_eof;
end;
{ PUTLONG ===================================================================
Outputs a Longint in LSB order to the given file
============================================================================}
procedure putLong (var f:file; x:uLong);
var
n : int;
c : byte;
begin
for n:=0 to 3 do begin
c := x and $FF;
blockwrite (f, c, 1);
x := x shr 8;
end;
end;
{ GZCLOSE ===================================================================
Flushes all pending output if necessary, closes the compressed file
and deallocates all the (de)compression state.
The return value is the zlib error number (see function gzerror below).
============================================================================}
function gzclose (f:gzFile) : int;
var
err : int;
s : gz_streamp;
begin
s := gz_streamp(f);
if (s = NIL) then begin
gzclose := Z_STREAM_ERROR;
exit;
end;
if (s^.mode = 'w') then begin
{$IFDEF NO_DEFLATE}
gzclose := Z_STREAM_ERROR;
exit;
{$ELSE}
err := do_flush (f, Z_FINISH);
if (err <> Z_OK) then begin
gzclose := destroy (gz_streamp(f));
exit;
end;
putLong (s^.gzfile, s^.crc);
putLong (s^.gzfile, s^.stream.total_in);
{$ENDIF}
end;
gzclose := destroy (gz_streamp(f));
end;
{ GZERROR ===================================================================
Returns the error message for the last error which occured on the
given compressed file. errnum is set to zlib error number. If an
error occured in the file system and not in the compression library,
errnum is set to Z_ERRNO and the application may consult errno
to get the exact error code.
============================================================================}
function gzerror (f:gzfile; var errnum:int) : string;
var
m : string;
s : gz_streamp;
begin
s := gz_streamp(f);
if (s = NIL) then begin
errnum := Z_STREAM_ERROR;
gzerror := zError(Z_STREAM_ERROR);
end;
errnum := s^.z_err;
if (errnum = Z_OK) then begin
gzerror := zError(Z_OK);
exit;
end;
m := s^.stream.msg;
if (errnum = Z_ERRNO) then m := '';
if (m = '') then m := zError(s^.z_err);
s^.msg := s^.path+': '+m;
gzerror := s^.msg;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -