Home | History | Annotate | Line # | Download | only in delphi
      1      1.1  christos {*******************************************************}
      2      1.1  christos {                                                       }
      3      1.1  christos {       Borland Delphi Supplemental Components          }
      4      1.1  christos {       ZLIB Data Compression Interface Unit            }
      5      1.1  christos {                                                       }
      6      1.1  christos {       Copyright (c) 1997,99 Borland Corporation       }
      7      1.1  christos {                                                       }
      8      1.1  christos {*******************************************************}
      9      1.1  christos 
     10      1.1  christos { Updated for zlib 1.2.x by Cosmin Truta <cosmint (a] cs.ubbcluj.ro> }
     11      1.1  christos 
     12      1.1  christos unit ZLib;
     13      1.1  christos 
     14      1.1  christos interface
     15      1.1  christos 
     16      1.1  christos uses SysUtils, Classes;
     17      1.1  christos 
     18      1.1  christos type
     19      1.1  christos   TAlloc = function (AppData: Pointer; Items, Size: Integer): Pointer; cdecl;
     20      1.1  christos   TFree = procedure (AppData, Block: Pointer); cdecl;
     21      1.1  christos 
     22      1.1  christos   // Internal structure.  Ignore.
     23      1.1  christos   TZStreamRec = packed record
     24      1.1  christos     next_in: PChar;       // next input byte
     25      1.1  christos     avail_in: Integer;    // number of bytes available at next_in
     26      1.1  christos     total_in: Longint;    // total nb of input bytes read so far
     27      1.1  christos 
     28      1.1  christos     next_out: PChar;      // next output byte should be put here
     29      1.1  christos     avail_out: Integer;   // remaining free space at next_out
     30      1.1  christos     total_out: Longint;   // total nb of bytes output so far
     31      1.1  christos 
     32      1.1  christos     msg: PChar;           // last error message, NULL if no error
     33      1.1  christos     internal: Pointer;    // not visible by applications
     34      1.1  christos 
     35      1.1  christos     zalloc: TAlloc;       // used to allocate the internal state
     36      1.1  christos     zfree: TFree;         // used to free the internal state
     37      1.1  christos     AppData: Pointer;     // private data object passed to zalloc and zfree
     38      1.1  christos 
     39      1.1  christos     data_type: Integer;   // best guess about the data type: ascii or binary
     40      1.1  christos     adler: Longint;       // adler32 value of the uncompressed data
     41      1.1  christos     reserved: Longint;    // reserved for future use
     42      1.1  christos   end;
     43      1.1  christos 
     44      1.1  christos   // Abstract ancestor class
     45      1.1  christos   TCustomZlibStream = class(TStream)
     46      1.1  christos   private
     47      1.1  christos     FStrm: TStream;
     48      1.1  christos     FStrmPos: Integer;
     49      1.1  christos     FOnProgress: TNotifyEvent;
     50      1.1  christos     FZRec: TZStreamRec;
     51      1.1  christos     FBuffer: array [Word] of Char;
     52      1.1  christos   protected
     53      1.1  christos     procedure Progress(Sender: TObject); dynamic;
     54      1.1  christos     property OnProgress: TNotifyEvent read FOnProgress write FOnProgress;
     55      1.1  christos     constructor Create(Strm: TStream);
     56      1.1  christos   end;
     57      1.1  christos 
     58      1.1  christos { TCompressionStream compresses data on the fly as data is written to it, and
     59      1.1  christos   stores the compressed data to another stream.
     60      1.1  christos 
     61      1.1  christos   TCompressionStream is write-only and strictly sequential. Reading from the
     62      1.1  christos   stream will raise an exception. Using Seek to move the stream pointer
     63      1.1  christos   will raise an exception.
     64      1.1  christos 
     65      1.1  christos   Output data is cached internally, written to the output stream only when
     66      1.1  christos   the internal output buffer is full.  All pending output data is flushed
     67      1.1  christos   when the stream is destroyed.
     68      1.1  christos 
     69      1.1  christos   The Position property returns the number of uncompressed bytes of
     70      1.1  christos   data that have been written to the stream so far.
     71      1.1  christos 
     72      1.1  christos   CompressionRate returns the on-the-fly percentage by which the original
     73      1.1  christos   data has been compressed:  (1 - (CompressedBytes / UncompressedBytes)) * 100
     74      1.1  christos   If raw data size = 100 and compressed data size = 25, the CompressionRate
     75      1.1  christos   is 75%
     76      1.1  christos 
     77      1.1  christos   The OnProgress event is called each time the output buffer is filled and
     78      1.1  christos   written to the output stream.  This is useful for updating a progress
     79      1.1  christos   indicator when you are writing a large chunk of data to the compression
     80      1.1  christos   stream in a single call.}
     81      1.1  christos 
     82      1.1  christos 
     83      1.1  christos   TCompressionLevel = (clNone, clFastest, clDefault, clMax);
     84      1.1  christos 
     85      1.1  christos   TCompressionStream = class(TCustomZlibStream)
     86      1.1  christos   private
     87      1.1  christos     function GetCompressionRate: Single;
     88      1.1  christos   public
     89      1.1  christos     constructor Create(CompressionLevel: TCompressionLevel; Dest: TStream);
     90      1.1  christos     destructor Destroy; override;
     91      1.1  christos     function Read(var Buffer; Count: Longint): Longint; override;
     92      1.1  christos     function Write(const Buffer; Count: Longint): Longint; override;
     93      1.1  christos     function Seek(Offset: Longint; Origin: Word): Longint; override;
     94      1.1  christos     property CompressionRate: Single read GetCompressionRate;
     95      1.1  christos     property OnProgress;
     96      1.1  christos   end;
     97      1.1  christos 
     98      1.1  christos { TDecompressionStream decompresses data on the fly as data is read from it.
     99      1.1  christos 
    100      1.1  christos   Compressed data comes from a separate source stream.  TDecompressionStream
    101      1.1  christos   is read-only and unidirectional; you can seek forward in the stream, but not
    102      1.1  christos   backwards.  The special case of setting the stream position to zero is
    103      1.1  christos   allowed.  Seeking forward decompresses data until the requested position in
    104      1.1  christos   the uncompressed data has been reached.  Seeking backwards, seeking relative
    105      1.1  christos   to the end of the stream, requesting the size of the stream, and writing to
    106      1.1  christos   the stream will raise an exception.
    107      1.1  christos 
    108      1.1  christos   The Position property returns the number of bytes of uncompressed data that
    109      1.1  christos   have been read from the stream so far.
    110      1.1  christos 
    111      1.1  christos   The OnProgress event is called each time the internal input buffer of
    112      1.1  christos   compressed data is exhausted and the next block is read from the input stream.
    113      1.1  christos   This is useful for updating a progress indicator when you are reading a
    114      1.1  christos   large chunk of data from the decompression stream in a single call.}
    115      1.1  christos 
    116      1.1  christos   TDecompressionStream = class(TCustomZlibStream)
    117      1.1  christos   public
    118      1.1  christos     constructor Create(Source: TStream);
    119      1.1  christos     destructor Destroy; override;
    120      1.1  christos     function Read(var Buffer; Count: Longint): Longint; override;
    121      1.1  christos     function Write(const Buffer; Count: Longint): Longint; override;
    122      1.1  christos     function Seek(Offset: Longint; Origin: Word): Longint; override;
    123      1.1  christos     property OnProgress;
    124      1.1  christos   end;
    125      1.1  christos 
    126      1.1  christos 
    127      1.1  christos 
    128      1.1  christos { CompressBuf compresses data, buffer to buffer, in one call.
    129      1.1  christos    In: InBuf = ptr to compressed data
    130      1.1  christos        InBytes = number of bytes in InBuf
    131      1.1  christos   Out: OutBuf = ptr to newly allocated buffer containing decompressed data
    132      1.1  christos        OutBytes = number of bytes in OutBuf   }
    133      1.1  christos procedure CompressBuf(const InBuf: Pointer; InBytes: Integer;
    134      1.1  christos                       out OutBuf: Pointer; out OutBytes: Integer);
    135      1.1  christos 
    136      1.1  christos 
    137      1.1  christos { DecompressBuf decompresses data, buffer to buffer, in one call.
    138      1.1  christos    In: InBuf = ptr to compressed data
    139      1.1  christos        InBytes = number of bytes in InBuf
    140      1.1  christos        OutEstimate = zero, or est. size of the decompressed data
    141      1.1  christos   Out: OutBuf = ptr to newly allocated buffer containing decompressed data
    142      1.1  christos        OutBytes = number of bytes in OutBuf   }
    143      1.1  christos procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer;
    144      1.1  christos  OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer);
    145      1.1  christos 
    146      1.1  christos { DecompressToUserBuf decompresses data, buffer to buffer, in one call.
    147      1.1  christos    In: InBuf = ptr to compressed data
    148      1.1  christos        InBytes = number of bytes in InBuf
    149      1.1  christos   Out: OutBuf = ptr to user-allocated buffer to contain decompressed data
    150      1.1  christos        BufSize = number of bytes in OutBuf   }
    151      1.1  christos procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer;
    152      1.1  christos   const OutBuf: Pointer; BufSize: Integer);
    153      1.1  christos 
    154      1.1  christos const
    155  1.1.1.4  christos   zlib_version = '1.3.1';
    156      1.1  christos 
    157      1.1  christos type
    158      1.1  christos   EZlibError = class(Exception);
    159      1.1  christos   ECompressionError = class(EZlibError);
    160      1.1  christos   EDecompressionError = class(EZlibError);
    161      1.1  christos 
    162      1.1  christos implementation
    163      1.1  christos 
    164      1.1  christos uses ZLibConst;
    165      1.1  christos 
    166      1.1  christos const
    167      1.1  christos   Z_NO_FLUSH      = 0;
    168      1.1  christos   Z_PARTIAL_FLUSH = 1;
    169      1.1  christos   Z_SYNC_FLUSH    = 2;
    170      1.1  christos   Z_FULL_FLUSH    = 3;
    171      1.1  christos   Z_FINISH        = 4;
    172      1.1  christos 
    173      1.1  christos   Z_OK            = 0;
    174      1.1  christos   Z_STREAM_END    = 1;
    175      1.1  christos   Z_NEED_DICT     = 2;
    176      1.1  christos   Z_ERRNO         = (-1);
    177      1.1  christos   Z_STREAM_ERROR  = (-2);
    178      1.1  christos   Z_DATA_ERROR    = (-3);
    179      1.1  christos   Z_MEM_ERROR     = (-4);
    180      1.1  christos   Z_BUF_ERROR     = (-5);
    181      1.1  christos   Z_VERSION_ERROR = (-6);
    182      1.1  christos 
    183      1.1  christos   Z_NO_COMPRESSION       =   0;
    184      1.1  christos   Z_BEST_SPEED           =   1;
    185      1.1  christos   Z_BEST_COMPRESSION     =   9;
    186      1.1  christos   Z_DEFAULT_COMPRESSION  = (-1);
    187      1.1  christos 
    188      1.1  christos   Z_FILTERED            = 1;
    189      1.1  christos   Z_HUFFMAN_ONLY        = 2;
    190      1.1  christos   Z_RLE                 = 3;
    191      1.1  christos   Z_DEFAULT_STRATEGY    = 0;
    192      1.1  christos 
    193      1.1  christos   Z_BINARY   = 0;
    194      1.1  christos   Z_ASCII    = 1;
    195      1.1  christos   Z_UNKNOWN  = 2;
    196      1.1  christos 
    197      1.1  christos   Z_DEFLATED = 8;
    198      1.1  christos 
    199      1.1  christos 
    200      1.1  christos {$L adler32.obj}
    201      1.1  christos {$L compress.obj}
    202      1.1  christos {$L crc32.obj}
    203      1.1  christos {$L deflate.obj}
    204      1.1  christos {$L infback.obj}
    205      1.1  christos {$L inffast.obj}
    206      1.1  christos {$L inflate.obj}
    207      1.1  christos {$L inftrees.obj}
    208      1.1  christos {$L trees.obj}
    209      1.1  christos {$L uncompr.obj}
    210      1.1  christos {$L zutil.obj}
    211      1.1  christos 
    212      1.1  christos procedure adler32; external;
    213      1.1  christos procedure compressBound; external;
    214      1.1  christos procedure crc32; external;
    215      1.1  christos procedure deflateInit2_; external;
    216      1.1  christos procedure deflateParams; external;
    217      1.1  christos 
    218      1.1  christos function _malloc(Size: Integer): Pointer; cdecl;
    219      1.1  christos begin
    220      1.1  christos   Result := AllocMem(Size);
    221      1.1  christos end;
    222      1.1  christos 
    223      1.1  christos procedure _free(Block: Pointer); cdecl;
    224      1.1  christos begin
    225      1.1  christos   FreeMem(Block);
    226      1.1  christos end;
    227      1.1  christos 
    228      1.1  christos procedure _memset(P: Pointer; B: Byte; count: Integer); cdecl;
    229      1.1  christos begin
    230      1.1  christos   FillChar(P^, count, B);
    231      1.1  christos end;
    232      1.1  christos 
    233      1.1  christos procedure _memcpy(dest, source: Pointer; count: Integer); cdecl;
    234      1.1  christos begin
    235      1.1  christos   Move(source^, dest^, count);
    236      1.1  christos end;
    237      1.1  christos 
    238      1.1  christos 
    239      1.1  christos 
    240      1.1  christos // deflate compresses data
    241      1.1  christos function deflateInit_(var strm: TZStreamRec; level: Integer; version: PChar;
    242      1.1  christos   recsize: Integer): Integer; external;
    243      1.1  christos function deflate(var strm: TZStreamRec; flush: Integer): Integer; external;
    244      1.1  christos function deflateEnd(var strm: TZStreamRec): Integer; external;
    245      1.1  christos 
    246      1.1  christos // inflate decompresses data
    247      1.1  christos function inflateInit_(var strm: TZStreamRec; version: PChar;
    248      1.1  christos   recsize: Integer): Integer; external;
    249      1.1  christos function inflate(var strm: TZStreamRec; flush: Integer): Integer; external;
    250      1.1  christos function inflateEnd(var strm: TZStreamRec): Integer; external;
    251      1.1  christos function inflateReset(var strm: TZStreamRec): Integer; external;
    252      1.1  christos 
    253      1.1  christos 
    254      1.1  christos function zlibAllocMem(AppData: Pointer; Items, Size: Integer): Pointer; cdecl;
    255      1.1  christos begin
    256      1.1  christos //  GetMem(Result, Items*Size);
    257      1.1  christos   Result := AllocMem(Items * Size);
    258      1.1  christos end;
    259      1.1  christos 
    260      1.1  christos procedure zlibFreeMem(AppData, Block: Pointer); cdecl;
    261      1.1  christos begin
    262      1.1  christos   FreeMem(Block);
    263      1.1  christos end;
    264      1.1  christos 
    265      1.1  christos {function zlibCheck(code: Integer): Integer;
    266      1.1  christos begin
    267      1.1  christos   Result := code;
    268      1.1  christos   if code < 0 then
    269      1.1  christos     raise EZlibError.Create('error');    //!!
    270      1.1  christos end;}
    271      1.1  christos 
    272      1.1  christos function CCheck(code: Integer): Integer;
    273      1.1  christos begin
    274      1.1  christos   Result := code;
    275      1.1  christos   if code < 0 then
    276      1.1  christos     raise ECompressionError.Create('error'); //!!
    277      1.1  christos end;
    278      1.1  christos 
    279      1.1  christos function DCheck(code: Integer): Integer;
    280      1.1  christos begin
    281      1.1  christos   Result := code;
    282      1.1  christos   if code < 0 then
    283      1.1  christos     raise EDecompressionError.Create('error');  //!!
    284      1.1  christos end;
    285      1.1  christos 
    286      1.1  christos procedure CompressBuf(const InBuf: Pointer; InBytes: Integer;
    287      1.1  christos                       out OutBuf: Pointer; out OutBytes: Integer);
    288      1.1  christos var
    289      1.1  christos   strm: TZStreamRec;
    290      1.1  christos   P: Pointer;
    291      1.1  christos begin
    292      1.1  christos   FillChar(strm, sizeof(strm), 0);
    293      1.1  christos   strm.zalloc := zlibAllocMem;
    294      1.1  christos   strm.zfree := zlibFreeMem;
    295      1.1  christos   OutBytes := ((InBytes + (InBytes div 10) + 12) + 255) and not 255;
    296      1.1  christos   GetMem(OutBuf, OutBytes);
    297      1.1  christos   try
    298      1.1  christos     strm.next_in := InBuf;
    299      1.1  christos     strm.avail_in := InBytes;
    300      1.1  christos     strm.next_out := OutBuf;
    301      1.1  christos     strm.avail_out := OutBytes;
    302      1.1  christos     CCheck(deflateInit_(strm, Z_BEST_COMPRESSION, zlib_version, sizeof(strm)));
    303      1.1  christos     try
    304      1.1  christos       while CCheck(deflate(strm, Z_FINISH)) <> Z_STREAM_END do
    305      1.1  christos       begin
    306      1.1  christos         P := OutBuf;
    307      1.1  christos         Inc(OutBytes, 256);
    308      1.1  christos         ReallocMem(OutBuf, OutBytes);
    309      1.1  christos         strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P)));
    310      1.1  christos         strm.avail_out := 256;
    311      1.1  christos       end;
    312      1.1  christos     finally
    313      1.1  christos       CCheck(deflateEnd(strm));
    314      1.1  christos     end;
    315      1.1  christos     ReallocMem(OutBuf, strm.total_out);
    316      1.1  christos     OutBytes := strm.total_out;
    317      1.1  christos   except
    318      1.1  christos     FreeMem(OutBuf);
    319      1.1  christos     raise
    320      1.1  christos   end;
    321      1.1  christos end;
    322      1.1  christos 
    323      1.1  christos 
    324      1.1  christos procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer;
    325      1.1  christos   OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer);
    326      1.1  christos var
    327      1.1  christos   strm: TZStreamRec;
    328      1.1  christos   P: Pointer;
    329      1.1  christos   BufInc: Integer;
    330      1.1  christos begin
    331      1.1  christos   FillChar(strm, sizeof(strm), 0);
    332      1.1  christos   strm.zalloc := zlibAllocMem;
    333      1.1  christos   strm.zfree := zlibFreeMem;
    334      1.1  christos   BufInc := (InBytes + 255) and not 255;
    335      1.1  christos   if OutEstimate = 0 then
    336      1.1  christos     OutBytes := BufInc
    337      1.1  christos   else
    338      1.1  christos     OutBytes := OutEstimate;
    339      1.1  christos   GetMem(OutBuf, OutBytes);
    340      1.1  christos   try
    341      1.1  christos     strm.next_in := InBuf;
    342      1.1  christos     strm.avail_in := InBytes;
    343      1.1  christos     strm.next_out := OutBuf;
    344      1.1  christos     strm.avail_out := OutBytes;
    345      1.1  christos     DCheck(inflateInit_(strm, zlib_version, sizeof(strm)));
    346      1.1  christos     try
    347      1.1  christos       while DCheck(inflate(strm, Z_NO_FLUSH)) <> Z_STREAM_END do
    348      1.1  christos       begin
    349      1.1  christos         P := OutBuf;
    350      1.1  christos         Inc(OutBytes, BufInc);
    351      1.1  christos         ReallocMem(OutBuf, OutBytes);
    352      1.1  christos         strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P)));
    353      1.1  christos         strm.avail_out := BufInc;
    354      1.1  christos       end;
    355      1.1  christos     finally
    356      1.1  christos       DCheck(inflateEnd(strm));
    357      1.1  christos     end;
    358      1.1  christos     ReallocMem(OutBuf, strm.total_out);
    359      1.1  christos     OutBytes := strm.total_out;
    360      1.1  christos   except
    361      1.1  christos     FreeMem(OutBuf);
    362      1.1  christos     raise
    363      1.1  christos   end;
    364      1.1  christos end;
    365      1.1  christos 
    366      1.1  christos procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer;
    367      1.1  christos   const OutBuf: Pointer; BufSize: Integer);
    368      1.1  christos var
    369      1.1  christos   strm: TZStreamRec;
    370      1.1  christos begin
    371      1.1  christos   FillChar(strm, sizeof(strm), 0);
    372      1.1  christos   strm.zalloc := zlibAllocMem;
    373      1.1  christos   strm.zfree := zlibFreeMem;
    374      1.1  christos   strm.next_in := InBuf;
    375      1.1  christos   strm.avail_in := InBytes;
    376      1.1  christos   strm.next_out := OutBuf;
    377      1.1  christos   strm.avail_out := BufSize;
    378      1.1  christos   DCheck(inflateInit_(strm, zlib_version, sizeof(strm)));
    379      1.1  christos   try
    380      1.1  christos     if DCheck(inflate(strm, Z_FINISH)) <> Z_STREAM_END then
    381      1.1  christos       raise EZlibError.CreateRes(@sTargetBufferTooSmall);
    382      1.1  christos   finally
    383      1.1  christos     DCheck(inflateEnd(strm));
    384      1.1  christos   end;
    385      1.1  christos end;
    386      1.1  christos 
    387      1.1  christos // TCustomZlibStream
    388      1.1  christos 
    389      1.1  christos constructor TCustomZLibStream.Create(Strm: TStream);
    390      1.1  christos begin
    391      1.1  christos   inherited Create;
    392      1.1  christos   FStrm := Strm;
    393      1.1  christos   FStrmPos := Strm.Position;
    394      1.1  christos   FZRec.zalloc := zlibAllocMem;
    395      1.1  christos   FZRec.zfree := zlibFreeMem;
    396      1.1  christos end;
    397      1.1  christos 
    398      1.1  christos procedure TCustomZLibStream.Progress(Sender: TObject);
    399      1.1  christos begin
    400      1.1  christos   if Assigned(FOnProgress) then FOnProgress(Sender);
    401      1.1  christos end;
    402      1.1  christos 
    403      1.1  christos 
    404      1.1  christos // TCompressionStream
    405      1.1  christos 
    406      1.1  christos constructor TCompressionStream.Create(CompressionLevel: TCompressionLevel;
    407      1.1  christos   Dest: TStream);
    408      1.1  christos const
    409      1.1  christos   Levels: array [TCompressionLevel] of ShortInt =
    410      1.1  christos     (Z_NO_COMPRESSION, Z_BEST_SPEED, Z_DEFAULT_COMPRESSION, Z_BEST_COMPRESSION);
    411      1.1  christos begin
    412      1.1  christos   inherited Create(Dest);
    413      1.1  christos   FZRec.next_out := FBuffer;
    414      1.1  christos   FZRec.avail_out := sizeof(FBuffer);
    415      1.1  christos   CCheck(deflateInit_(FZRec, Levels[CompressionLevel], zlib_version, sizeof(FZRec)));
    416      1.1  christos end;
    417      1.1  christos 
    418      1.1  christos destructor TCompressionStream.Destroy;
    419      1.1  christos begin
    420      1.1  christos   FZRec.next_in := nil;
    421      1.1  christos   FZRec.avail_in := 0;
    422      1.1  christos   try
    423      1.1  christos     if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
    424      1.1  christos     while (CCheck(deflate(FZRec, Z_FINISH)) <> Z_STREAM_END)
    425      1.1  christos       and (FZRec.avail_out = 0) do
    426      1.1  christos     begin
    427      1.1  christos       FStrm.WriteBuffer(FBuffer, sizeof(FBuffer));
    428      1.1  christos       FZRec.next_out := FBuffer;
    429      1.1  christos       FZRec.avail_out := sizeof(FBuffer);
    430      1.1  christos     end;
    431      1.1  christos     if FZRec.avail_out < sizeof(FBuffer) then
    432      1.1  christos       FStrm.WriteBuffer(FBuffer, sizeof(FBuffer) - FZRec.avail_out);
    433      1.1  christos   finally
    434      1.1  christos     deflateEnd(FZRec);
    435      1.1  christos   end;
    436      1.1  christos   inherited Destroy;
    437      1.1  christos end;
    438      1.1  christos 
    439      1.1  christos function TCompressionStream.Read(var Buffer; Count: Longint): Longint;
    440      1.1  christos begin
    441      1.1  christos   raise ECompressionError.CreateRes(@sInvalidStreamOp);
    442      1.1  christos end;
    443      1.1  christos 
    444      1.1  christos function TCompressionStream.Write(const Buffer; Count: Longint): Longint;
    445      1.1  christos begin
    446      1.1  christos   FZRec.next_in := @Buffer;
    447      1.1  christos   FZRec.avail_in := Count;
    448      1.1  christos   if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
    449      1.1  christos   while (FZRec.avail_in > 0) do
    450      1.1  christos   begin
    451      1.1  christos     CCheck(deflate(FZRec, 0));
    452      1.1  christos     if FZRec.avail_out = 0 then
    453      1.1  christos     begin
    454      1.1  christos       FStrm.WriteBuffer(FBuffer, sizeof(FBuffer));
    455      1.1  christos       FZRec.next_out := FBuffer;
    456      1.1  christos       FZRec.avail_out := sizeof(FBuffer);
    457      1.1  christos       FStrmPos := FStrm.Position;
    458      1.1  christos       Progress(Self);
    459      1.1  christos     end;
    460      1.1  christos   end;
    461      1.1  christos   Result := Count;
    462      1.1  christos end;
    463      1.1  christos 
    464      1.1  christos function TCompressionStream.Seek(Offset: Longint; Origin: Word): Longint;
    465      1.1  christos begin
    466      1.1  christos   if (Offset = 0) and (Origin = soFromCurrent) then
    467      1.1  christos     Result := FZRec.total_in
    468      1.1  christos   else
    469      1.1  christos     raise ECompressionError.CreateRes(@sInvalidStreamOp);
    470      1.1  christos end;
    471      1.1  christos 
    472      1.1  christos function TCompressionStream.GetCompressionRate: Single;
    473      1.1  christos begin
    474      1.1  christos   if FZRec.total_in = 0 then
    475      1.1  christos     Result := 0
    476      1.1  christos   else
    477      1.1  christos     Result := (1.0 - (FZRec.total_out / FZRec.total_in)) * 100.0;
    478      1.1  christos end;
    479      1.1  christos 
    480      1.1  christos 
    481      1.1  christos // TDecompressionStream
    482      1.1  christos 
    483      1.1  christos constructor TDecompressionStream.Create(Source: TStream);
    484      1.1  christos begin
    485      1.1  christos   inherited Create(Source);
    486      1.1  christos   FZRec.next_in := FBuffer;
    487      1.1  christos   FZRec.avail_in := 0;
    488      1.1  christos   DCheck(inflateInit_(FZRec, zlib_version, sizeof(FZRec)));
    489      1.1  christos end;
    490      1.1  christos 
    491      1.1  christos destructor TDecompressionStream.Destroy;
    492      1.1  christos begin
    493      1.1  christos   FStrm.Seek(-FZRec.avail_in, 1);
    494      1.1  christos   inflateEnd(FZRec);
    495      1.1  christos   inherited Destroy;
    496      1.1  christos end;
    497      1.1  christos 
    498      1.1  christos function TDecompressionStream.Read(var Buffer; Count: Longint): Longint;
    499      1.1  christos begin
    500      1.1  christos   FZRec.next_out := @Buffer;
    501      1.1  christos   FZRec.avail_out := Count;
    502      1.1  christos   if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
    503      1.1  christos   while (FZRec.avail_out > 0) do
    504      1.1  christos   begin
    505      1.1  christos     if FZRec.avail_in = 0 then
    506      1.1  christos     begin
    507      1.1  christos       FZRec.avail_in := FStrm.Read(FBuffer, sizeof(FBuffer));
    508      1.1  christos       if FZRec.avail_in = 0 then
    509      1.1  christos       begin
    510      1.1  christos         Result := Count - FZRec.avail_out;
    511      1.1  christos         Exit;
    512      1.1  christos       end;
    513      1.1  christos       FZRec.next_in := FBuffer;
    514      1.1  christos       FStrmPos := FStrm.Position;
    515      1.1  christos       Progress(Self);
    516      1.1  christos     end;
    517      1.1  christos     CCheck(inflate(FZRec, 0));
    518      1.1  christos   end;
    519      1.1  christos   Result := Count;
    520      1.1  christos end;
    521      1.1  christos 
    522      1.1  christos function TDecompressionStream.Write(const Buffer; Count: Longint): Longint;
    523      1.1  christos begin
    524      1.1  christos   raise EDecompressionError.CreateRes(@sInvalidStreamOp);
    525      1.1  christos end;
    526      1.1  christos 
    527      1.1  christos function TDecompressionStream.Seek(Offset: Longint; Origin: Word): Longint;
    528      1.1  christos var
    529      1.1  christos   I: Integer;
    530      1.1  christos   Buf: array [0..4095] of Char;
    531      1.1  christos begin
    532      1.1  christos   if (Offset = 0) and (Origin = soFromBeginning) then
    533      1.1  christos   begin
    534      1.1  christos     DCheck(inflateReset(FZRec));
    535      1.1  christos     FZRec.next_in := FBuffer;
    536      1.1  christos     FZRec.avail_in := 0;
    537      1.1  christos     FStrm.Position := 0;
    538      1.1  christos     FStrmPos := 0;
    539      1.1  christos   end
    540      1.1  christos   else if ( (Offset >= 0) and (Origin = soFromCurrent)) or
    541      1.1  christos           ( ((Offset - FZRec.total_out) > 0) and (Origin = soFromBeginning)) then
    542      1.1  christos   begin
    543      1.1  christos     if Origin = soFromBeginning then Dec(Offset, FZRec.total_out);
    544      1.1  christos     if Offset > 0 then
    545      1.1  christos     begin
    546      1.1  christos       for I := 1 to Offset div sizeof(Buf) do
    547      1.1  christos         ReadBuffer(Buf, sizeof(Buf));
    548      1.1  christos       ReadBuffer(Buf, Offset mod sizeof(Buf));
    549      1.1  christos     end;
    550      1.1  christos   end
    551      1.1  christos   else
    552      1.1  christos     raise EDecompressionError.CreateRes(@sInvalidStreamOp);
    553      1.1  christos   Result := FZRec.total_out;
    554      1.1  christos end;
    555      1.1  christos 
    556      1.1  christos 
    557      1.1  christos end.
    558