1938 lines
64 KiB
ObjectPascal
1938 lines
64 KiB
ObjectPascal
//{$DEFINE USE_EXCEPTIONS}
|
|
{*****************************************************************************
|
|
* unit based on *
|
|
* ZLibEx.pas (zlib 1.2.1) *
|
|
* Edition 2003.12.18 *
|
|
* *
|
|
* copyright (c) 2002-2003 Roberto Della Pasqua (www.dellapasqua.com) *
|
|
* copyright (c) 2000-2002 base2 technologies (www.base2ti.com) *
|
|
* copyright (c) 1997 Borland International (www.borland.com) *
|
|
* *
|
|
* and *
|
|
* *
|
|
* BZip2 unit by Edison Mera (www.geocities.com/efmera/) *
|
|
* Version 1.02 *
|
|
* Edition 21-11-2002 *
|
|
* *
|
|
* Changes made by GMax: *
|
|
* *
|
|
* units joined. gzip support functions added. *
|
|
* compression/decompression streams classes excluded, *
|
|
* compression/decompression stream2stream functions added *
|
|
* *
|
|
* procedures converted to functions to add "no exceptions" functionality *
|
|
* return values actual ONLY in this case (no exceptions) *
|
|
* error occured while value<0 *
|
|
* *
|
|
* function names for Z(De)Compress changed to Z(De)CompressBuf *
|
|
* *
|
|
* (C) GMax 2004. email: gmax@loving.ru *
|
|
*****************************************************************************}
|
|
|
|
unit KolZLibBzip;
|
|
|
|
interface
|
|
|
|
uses
|
|
KOL{$IFDEF USE_EXCEPTIONS}, ERR{$ENDIF};
|
|
|
|
const
|
|
ZLIB_VERSION = '1.2.1';
|
|
BZIP_VERSION = '1.0.2';
|
|
|
|
type
|
|
TAlloc = function(opaque: Pointer; Items, Size: Integer): Pointer; cdecl;
|
|
TFree = procedure(opaque, Block: Pointer); cdecl;
|
|
|
|
TZCompressionLevel = (zcNone, zcFastest, zcDefault, zcMax);
|
|
TZCompressionStrategy = (zcsDefault, zcsFiltered, zcsHuffmanOnly);
|
|
{** TZStreamRec ***********************************************************}
|
|
|
|
TZStreamRec = packed record
|
|
next_in: PChar; // next input byte
|
|
avail_in: Longint; // number of bytes available at next_in
|
|
total_in: Longint; // total nb of input bytes read so far
|
|
|
|
next_out: PChar; // next output byte should be put here
|
|
avail_out: Longint; // remaining free space at next_out
|
|
total_out: Longint; // total nb of bytes output so far
|
|
|
|
msg: PChar; // last error message, NULL if no error
|
|
state: Pointer; // not visible by applications
|
|
|
|
zalloc: TAlloc; // used to allocate the internal state
|
|
zfree: TFree; // used to free the internal state
|
|
opaque: Pointer; // private data object passed to zalloc and zfree
|
|
|
|
data_type: Integer; // best guess about the data type: ascii or binary
|
|
adler: Longint; // adler32 value of the uncompressed data
|
|
reserved: Longint; // reserved for future use
|
|
end;
|
|
|
|
{** zlib public routines ****************************************************}
|
|
|
|
{*****************************************************************************
|
|
* ZCompressBuf *
|
|
* *
|
|
* pre-conditions *
|
|
* inBuffer = pointer to uncompressed data *
|
|
* inSize = size of inBuffer (bytes) *
|
|
* outBuffer = pointer (unallocated) *
|
|
* level = compression level *
|
|
* *
|
|
* post-conditions *
|
|
* outBuffer = pointer to compressed data (allocated) *
|
|
* outSize = size of outBuffer (bytes) *
|
|
*****************************************************************************}
|
|
|
|
function ZCompressBuf(const inBuffer: Pointer; inSize: Integer;
|
|
out outBuffer: Pointer; out outSize: Integer;
|
|
level: TZCompressionLevel = zcDefault): Integer;
|
|
|
|
{*****************************************************************************
|
|
* ZDecompressBuf *
|
|
* *
|
|
* pre-conditions *
|
|
* inBuffer = pointer to compressed data *
|
|
* inSize = size of inBuffer (bytes) *
|
|
* outBuffer = pointer (unallocated) *
|
|
* outEstimate = estimated size of uncompressed data (bytes) *
|
|
* *
|
|
* post-conditions *
|
|
* outBuffer = pointer to decompressed data (allocated) *
|
|
* outSize = size of outBuffer (bytes) *
|
|
*****************************************************************************}
|
|
|
|
function ZDecompressBuf(const inBuffer: Pointer; inSize: Integer;
|
|
out outBuffer: Pointer; out outSize: Integer; outEstimate: Integer = 0): Integer;
|
|
|
|
{** string routines *********************************************************}
|
|
|
|
function ZCompressStr(const s: string; level: TZCompressionLevel = zcDefault): string;
|
|
|
|
function ZDecompressStr(const s: string): string;
|
|
|
|
{** stream routines *********************************************************}
|
|
|
|
function ZCompressStream(inStream, outStream: PStream;
|
|
level: TZCompressionLevel = zcDefault): Integer;
|
|
|
|
function ZDecompressStream(inStream, outStream: PStream): Integer;
|
|
|
|
{** utility routines ********************************************************}
|
|
|
|
function adler32(adler: LongInt; const buf: PChar; len: Integer): LongInt;
|
|
function CRC32(CRC: Cardinal; const Data: PChar; cbData: Cardinal): Cardinal;
|
|
function compressBound(sourceLen: LongInt): LongInt;
|
|
|
|
{****************************************************************************}
|
|
|
|
procedure MoveI32(const Source; var Dest; Count: Integer);
|
|
procedure ZFastCompressString(var s: string; level: TZCompressionLevel);
|
|
procedure ZFastDecompressString(var s: string);
|
|
procedure ZSendToBrowser(var s: string);
|
|
|
|
type
|
|
TgzipHeader = packed record
|
|
FileName: string;
|
|
Comment: string;
|
|
FileTime: TDateTime;
|
|
Extra: string;
|
|
end;
|
|
|
|
function gZipCompressStream(inStream, outStream: PStream; var gzHdr: TgzipHeader; level: TZCompressionLevel = zcDefault; strategy: TZCompressionStrategy = zcsDefault): Integer; overload;
|
|
function gZipCompressStream(inStream, outStream: PStream; level: TZCompressionLevel = zcDefault; strategy: TZCompressionStrategy = zcsDefault): Integer; overload;
|
|
function gZipDecompressStreamHeader(inStream: PStream; var gzHdr: TgzipHeader): Integer;
|
|
function gZipDecompressStreamBody(inStream, outStream: PStream): Integer;
|
|
function gZipDecompressStream(inStream, outStream: PStream; var gzHdr: TgzipHeader): Integer;
|
|
function gZipDecompressString(const S: String): String;
|
|
|
|
{*******************************************************}
|
|
{ }
|
|
{ BZIP2 Data Compression Interface Unit }
|
|
{ }
|
|
{*******************************************************}
|
|
type
|
|
// Internal structure.
|
|
TBZStreamRec = packed record
|
|
next_in: PChar; // next input byte
|
|
avail_in: Integer; // number of bytes available at next_in
|
|
total_in_lo32: Integer; // total nb of input bytes read so far
|
|
total_in_hi32: Integer;
|
|
|
|
next_out: PChar; // next output byte should be put here
|
|
avail_out: Integer; // remaining free space at next_out
|
|
total_out_lo32: Integer; // total nb of bytes output so far
|
|
total_out_hi32: Integer;
|
|
|
|
state: Pointer;
|
|
|
|
bzalloc: TAlloc; // used to allocate the internal state
|
|
bzfree: TFree; // used to free the internal state
|
|
opaque: Pointer;
|
|
end;
|
|
TBlockSize100k = 1..9;
|
|
{ CompressBuf compresses data, buffer to buffer, in one call.
|
|
In: InBuf = ptr to compressed data
|
|
InBytes = number of bytes in InBuf
|
|
Out: OutBuf = ptr to newly allocated buffer containing decompressed data
|
|
OutBytes = number of bytes in OutBuf }
|
|
function BZCompressBuf(const InBuf: Pointer; InBytes: Integer;
|
|
out OutBuf: Pointer; out OutBytes: Integer): Integer;
|
|
|
|
{ DecompressBuf decompresses data, buffer to buffer, in one call.
|
|
In: InBuf = ptr to compressed data
|
|
InBytes = number of bytes in InBuf
|
|
OutEstimate = zero, or est. size of the decompressed data
|
|
Out: OutBuf = ptr to newly allocated buffer containing decompressed data
|
|
OutBytes = number of bytes in OutBuf }
|
|
function BZDecompressBuf(const InBuf: Pointer; InBytes: Integer;
|
|
OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer): Integer;
|
|
|
|
function BZCompressStream(inStream, outStream: PStream; BlockSize100k: TBlockSize100k = 5): Integer;
|
|
function BZDecompressStream(inStream, outStream: PStream): Integer;
|
|
|
|
|
|
{** deflate routines ********************************************************}
|
|
|
|
function deflateInit_(var strm: TZStreamRec; level: Integer; version: PChar;
|
|
recsize: Integer): Integer; external;
|
|
|
|
function DeflateInit2_(var strm: TZStreamRec; level: integer; method: integer; windowBits: integer;
|
|
memLevel: integer; strategy: integer; version: PChar; recsize: integer): integer; external;
|
|
|
|
function deflate(var strm: TZStreamRec; flush: Integer): Integer;
|
|
external;
|
|
|
|
function deflateEnd(var strm: TZStreamRec): Integer; external;
|
|
|
|
{** inflate routines ********************************************************}
|
|
|
|
function inflateInit_(var strm: TZStreamRec; version: PChar;
|
|
recsize: Integer): Integer; external;
|
|
|
|
function inflateInit2_(var strm: TZStreamRec; windowBits: integer;
|
|
version: PChar; recsize: integer): integer; external;
|
|
|
|
function inflate(var strm: TZStreamRec; flush: Integer): Integer;
|
|
external;
|
|
|
|
function inflateEnd(var strm: TZStreamRec): Integer; external;
|
|
|
|
function inflateReset(var strm: TZStreamRec): Integer; external;
|
|
|
|
const
|
|
gzBufferSize = 16384;
|
|
gz_magic : array[0..1] of Byte = ($1F, $8B);
|
|
{ gzip flag byte }
|
|
|
|
GZF_ASCII_FLAG = $01; { bit 0 set: file probably ascii text }
|
|
GZF_HEAD_CRC = $02; { bit 1 set: header CRC present }
|
|
GZF_EXTRA_FIELD = $04; { bit 2 set: extra field present }
|
|
GZF_ORIG_NAME = $08; { bit 3 set: original file name present }
|
|
GZF_COMMENT = $10; { bit 4 set: file comment present }
|
|
GZF_RESERVED = $E0; { bits 5..7: reserved }
|
|
Z_EOF = -1;
|
|
|
|
const
|
|
{ ** Maximum value for windowBits in deflateInit2 and inflateInit2 }
|
|
MAX_WBITS = 15;
|
|
{ ** Maximum value for memLevel in deflateInit2 }
|
|
const
|
|
MAX_MEM_LEVEL = 9;
|
|
DEF_MEM_LEVEL = 8;
|
|
|
|
{** link zlib 1.2.1 *********************************************************}
|
|
{** bcc32 flags: -c -6 -O2 -Ve -X- -pr -a8 -b -d -k- -vi -tWM -r -RT- }
|
|
|
|
{$L zlib/adler32.obj}
|
|
{$L zlib/compress.obj}
|
|
{.$L zlib/crc32.obj}
|
|
{$L zlib/deflate.obj}
|
|
{$L zlib/infback.obj}
|
|
{$L zlib/inffast.obj}
|
|
{$L zlib/inflate.obj}
|
|
{$L zlib/inftrees.obj}
|
|
{$L zlib/trees.obj}
|
|
{$L zlib/uncompr.obj}
|
|
|
|
{*****************************************************************************
|
|
* note: do not reorder the above -- doing so will result in external *
|
|
* functions being undefined *
|
|
*****************************************************************************}
|
|
|
|
const
|
|
{** flush constants *******************************************************}
|
|
|
|
Z_NO_FLUSH = 0;
|
|
Z_PARTIAL_FLUSH = 1;
|
|
Z_SYNC_FLUSH = 2;
|
|
Z_FULL_FLUSH = 3;
|
|
Z_FINISH = 4;
|
|
|
|
{** return codes **********************************************************}
|
|
|
|
Z_OK = 0;
|
|
Z_STREAM_END = 1;
|
|
Z_NEED_DICT = 2;
|
|
Z_ERRNO = (-1);
|
|
Z_STREAM_ERROR = (-2);
|
|
Z_DATA_ERROR = (-3);
|
|
Z_MEM_ERROR = (-4);
|
|
Z_BUF_ERROR = (-5);
|
|
Z_VERSION_ERROR = (-6);
|
|
Z_WRITE_ERROR = (-10);
|
|
Z_CRC_ERROR = (-11);
|
|
Z_SIZE_ERROR = (-12);
|
|
|
|
{** compression levels ****************************************************}
|
|
|
|
Z_NO_COMPRESSION = 0;
|
|
Z_BEST_SPEED = 1;
|
|
Z_BEST_COMPRESSION = 9;
|
|
Z_DEFAULT_COMPRESSION = (-1);
|
|
|
|
{** compression strategies ************************************************}
|
|
|
|
Z_FILTERED = 1;
|
|
Z_HUFFMAN_ONLY = 2;
|
|
Z_DEFAULT_STRATEGY = 0;
|
|
|
|
{** data types ************************************************************}
|
|
|
|
Z_BINARY = 0;
|
|
Z_ASCII = 1;
|
|
Z_UNKNOWN = 2;
|
|
|
|
{** compression methods ***************************************************}
|
|
|
|
Z_DEFLATED = 8;
|
|
|
|
Z_NULL = nil; { for initializing zalloc, zfree, opaque }
|
|
|
|
{** return code messages **************************************************}
|
|
|
|
_z_errmsg : array[0..14] of PChar = (
|
|
'need dictionary', // Z_NEED_DICT (2)
|
|
'stream end', // Z_STREAM_END (1)
|
|
'', // Z_OK (0)
|
|
'file error', // Z_ERRNO (-1)
|
|
'stream error', // Z_STREAM_ERROR (-2)
|
|
'data error', // Z_DATA_ERROR (-3)
|
|
'insufficient memory', // Z_MEM_ERROR (-4)
|
|
'buffer error', // Z_BUF_ERROR (-5)
|
|
'incompatible version', // Z_VERSION_ERROR (-6)
|
|
'', '', '',
|
|
'stream write error', // Z_WRITE_ERROR = (-10);
|
|
'crc error', // Z_CRC_ERROR = (-11);
|
|
'size mismarch' // Z_SIZE_ERROR = (-12);
|
|
);
|
|
|
|
ZLevels : array[TZCompressionLevel] of Shortint = (
|
|
Z_NO_COMPRESSION,
|
|
Z_BEST_SPEED,
|
|
Z_DEFAULT_COMPRESSION,
|
|
Z_BEST_COMPRESSION
|
|
);
|
|
ZStrategy : array[TZCompressionStrategy] of Shortint = (
|
|
Z_DEFAULT_STRATEGY,
|
|
Z_FILTERED,
|
|
Z_HUFFMAN_ONLY
|
|
);
|
|
|
|
{************** BZip constants **********************************************}
|
|
{$L bz2/blocks~1.obj} //blocksort
|
|
{$L bz2/huffman.obj}
|
|
{$L bz2/compress.obj}
|
|
{$L bz2/decomp~1.obj} //decompress
|
|
{$L bz2/bzlib.obj}
|
|
{ $L bz2/crctable.obj}
|
|
{ $L bz2/randtable.obj}
|
|
|
|
procedure _BZ2_hbMakeCodeLengths; external;
|
|
procedure _BZ2_blockSort; external;
|
|
procedure _BZ2_hbCreateDecodeTables; external;
|
|
procedure _BZ2_hbAssignCodes; external;
|
|
procedure _BZ2_compressBlock; external;
|
|
procedure _BZ2_decompress; external;
|
|
|
|
const
|
|
bzBufferSize = 32768;
|
|
|
|
BZ_RUN = 0;
|
|
BZ_FLUSH = 1;
|
|
BZ_FINISH = 2;
|
|
BZ_OK = 0;
|
|
BZ_RUN_OK = 1;
|
|
BZ_FLUSH_OK = 2;
|
|
BZ_FINISH_OK = 3;
|
|
BZ_STREAM_END = 4;
|
|
BZ_SEQUENCE_ERROR = (-1);
|
|
BZ_PARAM_ERROR = (-2);
|
|
BZ_MEM_ERROR = (-3);
|
|
BZ_DATA_ERROR = (-4);
|
|
BZ_DATA_ERROR_MAGIC = (-5);
|
|
BZ_IO_ERROR = (-6);
|
|
BZ_UNEXPECTED_EOF = (-7);
|
|
BZ_OUTBUFF_FULL = (-8);
|
|
|
|
BZ_Error_Msg : array[1..8] of PChar = (
|
|
'BZ_SEQUENCE_ERROR',
|
|
'BZ_PARAM_ERROR',
|
|
'BZ_MEM_ERROR',
|
|
'BZ_DATA_ERROR',
|
|
'BZ_DATA_ERROR_MAGIC',
|
|
'BZ_IO_ERROR',
|
|
'BZ_UNEXPECTED_EOF',
|
|
'BZ_OUTBUFF_FULL'
|
|
);
|
|
|
|
BZ_BLOCK_SIZE_100K = 9;
|
|
|
|
_BZ2_rNums : array[0..511] of Longint = (
|
|
619, 720, 127, 481, 931, 816, 813, 233, 566, 247,
|
|
985, 724, 205, 454, 863, 491, 741, 242, 949, 214,
|
|
733, 859, 335, 708, 621, 574, 73, 654, 730, 472,
|
|
419, 436, 278, 496, 867, 210, 399, 680, 480, 51,
|
|
878, 465, 811, 169, 869, 675, 611, 697, 867, 561,
|
|
862, 687, 507, 283, 482, 129, 807, 591, 733, 623,
|
|
150, 238, 59, 379, 684, 877, 625, 169, 643, 105,
|
|
170, 607, 520, 932, 727, 476, 693, 425, 174, 647,
|
|
73, 122, 335, 530, 442, 853, 695, 249, 445, 515,
|
|
909, 545, 703, 919, 874, 474, 882, 500, 594, 612,
|
|
641, 801, 220, 162, 819, 984, 589, 513, 495, 799,
|
|
161, 604, 958, 533, 221, 400, 386, 867, 600, 782,
|
|
382, 596, 414, 171, 516, 375, 682, 485, 911, 276,
|
|
98, 553, 163, 354, 666, 933, 424, 341, 533, 870,
|
|
227, 730, 475, 186, 263, 647, 537, 686, 600, 224,
|
|
469, 68, 770, 919, 190, 373, 294, 822, 808, 206,
|
|
184, 943, 795, 384, 383, 461, 404, 758, 839, 887,
|
|
715, 67, 618, 276, 204, 918, 873, 777, 604, 560,
|
|
951, 160, 578, 722, 79, 804, 96, 409, 713, 940,
|
|
652, 934, 970, 447, 318, 353, 859, 672, 112, 785,
|
|
645, 863, 803, 350, 139, 93, 354, 99, 820, 908,
|
|
609, 772, 154, 274, 580, 184, 79, 626, 630, 742,
|
|
653, 282, 762, 623, 680, 81, 927, 626, 789, 125,
|
|
411, 521, 938, 300, 821, 78, 343, 175, 128, 250,
|
|
170, 774, 972, 275, 999, 639, 495, 78, 352, 126,
|
|
857, 956, 358, 619, 580, 124, 737, 594, 701, 612,
|
|
669, 112, 134, 694, 363, 992, 809, 743, 168, 974,
|
|
944, 375, 748, 52, 600, 747, 642, 182, 862, 81,
|
|
344, 805, 988, 739, 511, 655, 814, 334, 249, 515,
|
|
897, 955, 664, 981, 649, 113, 974, 459, 893, 228,
|
|
433, 837, 553, 268, 926, 240, 102, 654, 459, 51,
|
|
686, 754, 806, 760, 493, 403, 415, 394, 687, 700,
|
|
946, 670, 656, 610, 738, 392, 760, 799, 887, 653,
|
|
978, 321, 576, 617, 626, 502, 894, 679, 243, 440,
|
|
680, 879, 194, 572, 640, 724, 926, 56, 204, 700,
|
|
707, 151, 457, 449, 797, 195, 791, 558, 945, 679,
|
|
297, 59, 87, 824, 713, 663, 412, 693, 342, 606,
|
|
134, 108, 571, 364, 631, 212, 174, 643, 304, 329,
|
|
343, 97, 430, 751, 497, 314, 983, 374, 822, 928,
|
|
140, 206, 73, 263, 980, 736, 876, 478, 430, 305,
|
|
170, 514, 364, 692, 829, 82, 855, 953, 676, 246,
|
|
369, 970, 294, 750, 807, 827, 150, 790, 288, 923,
|
|
804, 378, 215, 828, 592, 281, 565, 555, 710, 82,
|
|
896, 831, 547, 261, 524, 462, 293, 465, 502, 56,
|
|
661, 821, 976, 991, 658, 869, 905, 758, 745, 193,
|
|
768, 550, 608, 933, 378, 286, 215, 979, 792, 961,
|
|
61, 688, 793, 644, 986, 403, 106, 366, 905, 644,
|
|
372, 567, 466, 434, 645, 210, 389, 550, 919, 135,
|
|
780, 773, 635, 389, 707, 100, 626, 958, 165, 504,
|
|
920, 176, 193, 713, 857, 265, 203, 50, 668, 108,
|
|
645, 990, 626, 197, 510, 357, 358, 850, 858, 364,
|
|
936, 638
|
|
);
|
|
|
|
_BZ2_crc32Table : array[0..255] of Longint = (
|
|
$00000000, $04C11DB7, $09823B6E, $0D4326D9,
|
|
$130476DC, $17C56B6B, $1A864DB2, $1E475005,
|
|
$2608EDB8, $22C9F00F, $2F8AD6D6, $2B4BCB61,
|
|
$350C9B64, $31CD86D3, $3C8EA00A, $384FBDBD,
|
|
$4C11DB70, $48D0C6C7, $4593E01E, $4152FDA9,
|
|
$5F15ADAC, $5BD4B01B, $569796C2, $52568B75,
|
|
$6A1936C8, $6ED82B7F, $639B0DA6, $675A1011,
|
|
$791D4014, $7DDC5DA3, $709F7B7A, $745E66CD,
|
|
-$67DC4920, -$631D54A9, -$6E5E7272, -$6A9F6FC7,
|
|
-$74D83FC4, -$70192275, -$7D5A04AE, -$799B191B,
|
|
-$41D4A4A8, -$4515B911, -$48569FCA, -$4C97827F,
|
|
-$52D0D27C, -$5611CFCD, -$5B52E916, -$5F93F4A3,
|
|
-$2BCD9270, -$2F0C8FD9, -$224FA902, -$268EB4B7,
|
|
-$38C9E4B4, -$3C08F905, -$314BDFDE, -$358AC26B,
|
|
-$0DC57FD8, -$09046261, -$044744BA, -$0086590F,
|
|
-$1EC1090C, -$1A0014BD, -$17433266, -$13822FD3,
|
|
$34867077, $30476DC0, $3D044B19, $39C556AE,
|
|
$278206AB, $23431B1C, $2E003DC5, $2AC12072,
|
|
$128E9DCF, $164F8078, $1B0CA6A1, $1FCDBB16,
|
|
$018AEB13, $054BF6A4, $0808D07D, $0CC9CDCA,
|
|
$7897AB07, $7C56B6B0, $71159069, $75D48DDE,
|
|
$6B93DDDB, $6F52C06C, $6211E6B5, $66D0FB02,
|
|
$5E9F46BF, $5A5E5B08, $571D7DD1, $53DC6066,
|
|
$4D9B3063, $495A2DD4, $44190B0D, $40D816BA,
|
|
-$535A3969, -$579B24E0, -$5AD80207, -$5E191FB2,
|
|
-$405E4FB5, -$449F5204, -$49DC74DB, -$4D1D696E,
|
|
-$7552D4D1, -$7193C968, -$7CD0EFBF, -$7811F20A,
|
|
-$6656A20D, -$6297BFBC, -$6FD49963, -$6B1584D6,
|
|
-$1F4BE219, -$1B8AFFB0, -$16C9D977, -$1208C4C2,
|
|
-$0C4F94C5, -$088E8974, -$05CDAFAB, -$010CB21E,
|
|
-$39430FA1, -$3D821218, -$30C134CF, -$3400297A,
|
|
-$2A47797D, -$2E8664CC, -$23C54213, -$27045FA6,
|
|
$690CE0EE, $6DCDFD59, $608EDB80, $644FC637,
|
|
$7A089632, $7EC98B85, $738AAD5C, $774BB0EB,
|
|
$4F040D56, $4BC510E1, $46863638, $42472B8F,
|
|
$5C007B8A, $58C1663D, $558240E4, $51435D53,
|
|
$251D3B9E, $21DC2629, $2C9F00F0, $285E1D47,
|
|
$36194D42, $32D850F5, $3F9B762C, $3B5A6B9B,
|
|
$0315D626, $07D4CB91, $0A97ED48, $0E56F0FF,
|
|
$1011A0FA, $14D0BD4D, $19939B94, $1D528623,
|
|
-$0ED0A9F2, -$0A11B447, -$075292A0, -$03938F29,
|
|
-$1DD4DF2E, -$1915C29B, -$1456E444, -$1097F9F5,
|
|
-$28D8444A, -$2C1959FF, -$215A7F28, -$259B6291,
|
|
-$3BDC3296, -$3F1D2F23, -$325E09FC, -$369F144D,
|
|
-$42C17282, -$46006F37, -$4B4349F0, -$4F825459,
|
|
-$51C5045E, -$550419EB, -$58473F34, -$5C862285,
|
|
-$64C99F3A, -$6008828F, -$6D4BA458, -$698AB9E1,
|
|
-$77CDE9E6, -$730CF453, -$7E4FD28C, -$7A8ECF3D,
|
|
$5D8A9099, $594B8D2E, $5408ABF7, $50C9B640,
|
|
$4E8EE645, $4A4FFBF2, $470CDD2B, $43CDC09C,
|
|
$7B827D21, $7F436096, $7200464F, $76C15BF8,
|
|
$68860BFD, $6C47164A, $61043093, $65C52D24,
|
|
$119B4BE9, $155A565E, $18197087, $1CD86D30,
|
|
$029F3D35, $065E2082, $0B1D065B, $0FDC1BEC,
|
|
$3793A651, $3352BBE6, $3E119D3F, $3AD08088,
|
|
$2497D08D, $2056CD3A, $2D15EBE3, $29D4F654,
|
|
-$3A56D987, -$3E97C432, -$33D4E2E9, -$3715FF60,
|
|
-$2952AF5B, -$2D93B2EE, -$20D09435, -$24118984,
|
|
-$1C5E343F, -$189F298A, -$15DC0F51, -$111D12E8,
|
|
-$0F5A42E3, -$0B9B5F56, -$06D8798D, -$0219643C,
|
|
-$764702F7, -$72861F42, -$7FC53999, -$7B042430,
|
|
-$6543742B, -$6182699E, -$6CC14F45, -$680052F4,
|
|
-$504FEF4F, -$548EF2FA, -$59CDD421, -$5D0CC998,
|
|
-$434B9993, -$478A8426, -$4AC9A2FD, -$4E08BF4C
|
|
);
|
|
|
|
// deflate compresses data
|
|
|
|
function BZ2_bzCompressInit(var strm: TBZStreamRec; blockSize100k: Integer;
|
|
verbosity: Integer; workFactor: Integer): Integer; stdcall; external;
|
|
|
|
function BZ2_bzCompress(var strm: TBZStreamRec; action: Integer): Integer; stdcall; external;
|
|
|
|
function BZ2_bzCompressEnd(var strm: TBZStreamRec): Integer; stdcall; external;
|
|
|
|
function BZ2_bzBuffToBuffCompress(dest: Pointer; var destLen: Integer; source: Pointer;
|
|
sourceLen, blockSize100k, verbosity, workFactor: Integer): Integer; stdcall; external;
|
|
|
|
// inflate decompresses data
|
|
|
|
function BZ2_bzDecompressInit(var strm: TBZStreamRec; verbosity: Integer;
|
|
small: Integer): Integer; stdcall; external;
|
|
|
|
function BZ2_bzDecompress(var strm: TBZStreamRec): Integer; stdcall; external;
|
|
|
|
function BZ2_bzDecompressEnd(var strm: TBZStreamRec): Integer; stdcall; external;
|
|
|
|
function BZ2_bzBuffToBuffDecompress(dest: Pointer; var destLen: Integer; source: Pointer;
|
|
sourceLen, small, verbosity: Integer): Integer; stdcall; external;
|
|
|
|
{** utility routines *******************************************************}
|
|
|
|
function adler32; external;
|
|
function compressBound; external;
|
|
|
|
implementation
|
|
|
|
procedure _bz_internal_error(errcode: Integer); cdecl;
|
|
begin
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
//raise EBZip2Error.CreateFmt('Compression Error %d', [errcode]);
|
|
raise Exception.CreateFMT(e_Convert, 'Compression Error %d', [errcode]);
|
|
// I don't know, what make in {$ELSE} :(
|
|
{$ENDIF}
|
|
end;
|
|
|
|
function _malloc(size: Integer): Pointer; cdecl;
|
|
begin
|
|
GetMem(Result, Size);
|
|
end;
|
|
|
|
procedure _free(block: Pointer); cdecl;
|
|
begin
|
|
FreeMem(block);
|
|
end;
|
|
|
|
function bzip2AllocMem(AppData: Pointer; Items, Size: Integer): Pointer; cdecl;
|
|
begin
|
|
GetMem(Result, Items * Size);
|
|
end;
|
|
|
|
procedure bzip2FreeMem(AppData, Block: Pointer); cdecl;
|
|
begin
|
|
FreeMem(Block);
|
|
end;
|
|
|
|
{*********************** Peter Morris not aligned move **********************}
|
|
|
|
procedure MoveI32(const Source; var Dest; Count: Integer); register;
|
|
asm
|
|
cmp ECX,0
|
|
Je @JustQuit
|
|
push ESI
|
|
push EDI
|
|
mov ESI, EAX
|
|
mov EDI, EDX
|
|
@Loop:
|
|
Mov AL, [ESI]
|
|
Inc ESI
|
|
mov [EDI], AL
|
|
Inc EDI
|
|
Dec ECX
|
|
Jnz @Loop
|
|
pop EDI
|
|
pop ESI
|
|
@JustQuit:
|
|
end;
|
|
{****************************************************************************}
|
|
|
|
{** utility routines *******************************************************}
|
|
|
|
//function crc32; external;
|
|
function CRC32(CRC: Cardinal; const Data: PChar; cbData: Cardinal): Cardinal; assembler;
|
|
asm
|
|
or edx, edx
|
|
je @@exi
|
|
jecxz @@exi
|
|
xor eax,0FFFFFFFFh
|
|
push ebx
|
|
@@upd:
|
|
movzx ebx, al
|
|
xor bl, [ edx ]
|
|
shr eax, 8
|
|
and eax, 00FFFFFFh
|
|
xor eax, cs:[ebx*4 + offset @@c32tt ]//OFFSET @@C32TT ]
|
|
inc edx
|
|
loop @@upd
|
|
pop ebx
|
|
xor eax,0FFFFFFFFh
|
|
@@exi:
|
|
ret
|
|
|
|
@@C32TT:
|
|
|
|
DD 000000000h, 077073096h, 0ee0e612ch, 0990951bah
|
|
DD 0076dc419h, 0706af48fh, 0e963a535h, 09e6495a3h
|
|
DD 00edb8832h, 079dcb8a4h, 0e0d5e91eh, 097d2d988h
|
|
DD 009b64c2bh, 07eb17cbdh, 0e7b82d07h, 090bf1d91h
|
|
DD 01db71064h, 06ab020f2h, 0f3b97148h, 084be41deh
|
|
DD 01adad47dh, 06ddde4ebh, 0f4d4b551h, 083d385c7h
|
|
DD 0136c9856h, 0646ba8c0h, 0fd62f97ah, 08a65c9ech
|
|
DD 014015c4fh, 063066cd9h, 0fa0f3d63h, 08d080df5h
|
|
DD 03b6e20c8h, 04c69105eh, 0d56041e4h, 0a2677172h
|
|
DD 03c03e4d1h, 04b04d447h, 0d20d85fdh, 0a50ab56bh
|
|
DD 035b5a8fah, 042b2986ch, 0dbbbc9d6h, 0acbcf940h
|
|
DD 032d86ce3h, 045df5c75h, 0dcd60dcfh, 0abd13d59h
|
|
DD 026d930ach, 051de003ah, 0c8d75180h, 0bfd06116h
|
|
DD 021b4f4b5h, 056b3c423h, 0cfba9599h, 0b8bda50fh
|
|
DD 02802b89eh, 05f058808h, 0c60cd9b2h, 0b10be924h
|
|
DD 02f6f7c87h, 058684c11h, 0c1611dabh, 0b6662d3dh
|
|
DD 076dc4190h, 001db7106h, 098d220bch, 0efd5102ah
|
|
DD 071b18589h, 006b6b51fh, 09fbfe4a5h, 0e8b8d433h
|
|
DD 07807c9a2h, 00f00f934h, 09609a88eh, 0e10e9818h
|
|
DD 07f6a0dbbh, 0086d3d2dh, 091646c97h, 0e6635c01h
|
|
DD 06b6b51f4h, 01c6c6162h, 0856530d8h, 0f262004eh
|
|
DD 06c0695edh, 01b01a57bh, 08208f4c1h, 0f50fc457h
|
|
DD 065b0d9c6h, 012b7e950h, 08bbeb8eah, 0fcb9887ch
|
|
DD 062dd1ddfh, 015da2d49h, 08cd37cf3h, 0fbd44c65h
|
|
DD 04db26158h, 03ab551ceh, 0a3bc0074h, 0d4bb30e2h
|
|
DD 04adfa541h, 03dd895d7h, 0a4d1c46dh, 0d3d6f4fbh
|
|
DD 04369e96ah, 0346ed9fch, 0ad678846h, 0da60b8d0h
|
|
DD 044042d73h, 033031de5h, 0aa0a4c5fh, 0dd0d7cc9h
|
|
DD 05005713ch, 0270241aah, 0be0b1010h, 0c90c2086h
|
|
DD 05768b525h, 0206f85b3h, 0b966d409h, 0ce61e49fh
|
|
DD 05edef90eh, 029d9c998h, 0b0d09822h, 0c7d7a8b4h
|
|
DD 059b33d17h, 02eb40d81h, 0b7bd5c3bh, 0c0ba6cadh
|
|
DD 0edb88320h, 09abfb3b6h, 003b6e20ch, 074b1d29ah
|
|
DD 0ead54739h, 09dd277afh, 004db2615h, 073dc1683h
|
|
DD 0e3630b12h, 094643b84h, 00d6d6a3eh, 07a6a5aa8h
|
|
DD 0e40ecf0bh, 09309ff9dh, 00a00ae27h, 07d079eb1h
|
|
DD 0f00f9344h, 08708a3d2h, 01e01f268h, 06906c2feh
|
|
DD 0f762575dh, 0806567cbh, 0196c3671h, 06e6b06e7h
|
|
DD 0fed41b76h, 089d32be0h, 010da7a5ah, 067dd4acch
|
|
DD 0f9b9df6fh, 08ebeeff9h, 017b7be43h, 060b08ed5h
|
|
DD 0d6d6a3e8h, 0a1d1937eh, 038d8c2c4h, 04fdff252h
|
|
DD 0d1bb67f1h, 0a6bc5767h, 03fb506ddh, 048b2364bh
|
|
DD 0d80d2bdah, 0af0a1b4ch, 036034af6h, 041047a60h
|
|
DD 0df60efc3h, 0a867df55h, 0316e8eefh, 04669be79h
|
|
DD 0cb61b38ch, 0bc66831ah, 0256fd2a0h, 05268e236h
|
|
DD 0cc0c7795h, 0bb0b4703h, 0220216b9h, 05505262fh
|
|
DD 0c5ba3bbeh, 0b2bd0b28h, 02bb45a92h, 05cb36a04h
|
|
DD 0c2d7ffa7h, 0b5d0cf31h, 02cd99e8bh, 05bdeae1dh
|
|
DD 09b64c2b0h, 0ec63f226h, 0756aa39ch, 0026d930ah
|
|
DD 09c0906a9h, 0eb0e363fh, 072076785h, 005005713h
|
|
DD 095bf4a82h, 0e2b87a14h, 07bb12baeh, 00cb61b38h
|
|
DD 092d28e9bh, 0e5d5be0dh, 07cdcefb7h, 00bdbdf21h
|
|
DD 086d3d2d4h, 0f1d4e242h, 068ddb3f8h, 01fda836eh
|
|
DD 081be16cdh, 0f6b9265bh, 06fb077e1h, 018b74777h
|
|
DD 088085ae6h, 0ff0f6a70h, 066063bcah, 011010b5ch
|
|
DD 08f659effh, 0f862ae69h, 0616bffd3h, 0166ccf45h
|
|
DD 0a00ae278h, 0d70dd2eeh, 04e048354h, 03903b3c2h
|
|
DD 0a7672661h, 0d06016f7h, 04969474dh, 03e6e77dbh
|
|
DD 0aed16a4ah, 0d9d65adch, 040df0b66h, 037d83bf0h
|
|
DD 0a9bcae53h, 0debb9ec5h, 047b2cf7fh, 030b5ffe9h
|
|
DD 0bdbdf21ch, 0cabac28ah, 053b39330h, 024b4a3a6h
|
|
DD 0bad03605h, 0cdd70693h, 054de5729h, 023d967bfh
|
|
DD 0b3667a2eh, 0c4614ab8h, 05d681b02h, 02a6f2b94h
|
|
DD 0b40bbe37h, 0c30c8ea1h, 05a05df1bh, 02d02ef8dh
|
|
|
|
end;
|
|
|
|
{** zlib function implementations *******************************************}
|
|
|
|
function zcalloc(opaque: Pointer; items, size: Integer): Pointer;
|
|
begin
|
|
GetMem(result, items * size);
|
|
end;
|
|
|
|
procedure zcfree(opaque, block: Pointer);
|
|
begin
|
|
FreeMem(block);
|
|
end;
|
|
|
|
{** c function implementations **********************************************}
|
|
|
|
procedure _memset(p: Pointer; b: Byte; count: Integer); cdecl;
|
|
begin
|
|
FillChar(p^, count, b);
|
|
end;
|
|
|
|
procedure _memcpy(dest, source: Pointer; count: Integer); cdecl;
|
|
begin
|
|
Move(source^, dest^, count);
|
|
end;
|
|
|
|
{** custom zlib routines ****************************************************}
|
|
|
|
function DeflateInit(var stream: TZStreamRec; level: Integer): Integer;
|
|
begin
|
|
result := DeflateInit_(stream, level, ZLIB_VERSION, SizeOf(TZStreamRec));
|
|
end;
|
|
|
|
function DeflateInit2(var stream: TZStreamRec; level, method, windowBits, memLevel, strategy: Integer): Integer;
|
|
begin
|
|
result := DeflateInit2_(stream, level, method, windowBits, memLevel,
|
|
strategy, ZLIB_VERSION, SizeOf(TZStreamRec));
|
|
end;
|
|
|
|
function InflateInit(var stream: TZStreamRec): Integer;
|
|
begin
|
|
result := InflateInit_(stream, ZLIB_VERSION, SizeOf(TZStreamRec));
|
|
end;
|
|
|
|
function InflateInit2(var stream: TZStreamRec; windowBits: Integer): Integer;
|
|
begin
|
|
result := InflateInit2_(stream, windowBits, ZLIB_VERSION, SizeOf(TZStreamRec));
|
|
end;
|
|
|
|
{****************************************************************************}
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
|
|
function ZCompressCheck(code: Integer): Integer;
|
|
begin
|
|
result := code;
|
|
|
|
if code < 0 then begin
|
|
raise Exception.CreateFMT(e_Convert, 'Compression Error %d - %s', [code, _z_errmsg[2 - code]]);
|
|
end;
|
|
end;
|
|
|
|
function ZDecompressCheck(code: Integer): Integer;
|
|
begin
|
|
Result := code;
|
|
|
|
if code < 0 then begin
|
|
raise Exception.CreateFMT(e_Convert, 'Decompression Error %d - %s', [code, _z_errmsg[2 - code]]);
|
|
end;
|
|
end;
|
|
{$ENDIF}
|
|
|
|
{****************************************************************************}
|
|
{****************************************************************************}
|
|
{****************************************************************************}
|
|
{**** implementation itself *************************************************}
|
|
{****************************************************************************}
|
|
{****************************************************************************}
|
|
{****************************************************************************}
|
|
|
|
function ZCompressBuf(const inBuffer: Pointer; inSize: Integer; out outBuffer: Pointer; out outSize: Integer; level: TZCompressionLevel): Integer;
|
|
const
|
|
delta = 256;
|
|
var
|
|
zstream : TZStreamRec;
|
|
begin
|
|
FillChar(zstream, SizeOf(TZStreamRec), 0);
|
|
Result := Z_OK;
|
|
outSize := ((inSize + (inSize div 10) + 12) + 255) and not 255;
|
|
outBuffer := nil;
|
|
GetMem(outBuffer, outSize);
|
|
try
|
|
zstream.next_in := inBuffer;
|
|
zstream.avail_in := inSize;
|
|
zstream.next_out := outBuffer;
|
|
zstream.avail_out := outSize;
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
ZCompressCheck(DeflateInit(zstream, ZLevels[level]));
|
|
{$ELSE}
|
|
Result := DeflateInit(zstream, ZLevels[level]);
|
|
if Result < 0 then Exit;
|
|
{$ENDIF}
|
|
try
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
Result := ZCompressCheck(deflate(zstream, Z_FINISH));
|
|
{$ELSE}
|
|
Result := deflate(zstream, Z_FINISH);
|
|
if Result < 0 then Exit;
|
|
{$ENDIF}
|
|
while Result <> Z_STREAM_END do begin
|
|
Inc(outSize, delta);
|
|
ReallocMem(outBuffer, outSize);
|
|
|
|
zstream.next_out := PChar(Integer(outBuffer) + zstream.total_out);
|
|
zstream.avail_out := delta;
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
Result := ZCompressCheck(deflate(zstream, Z_FINISH));
|
|
{$ELSE}
|
|
Result := deflate(zstream, Z_FINISH);
|
|
if Result < 0 then Exit;
|
|
{$ENDIF}
|
|
end; // while
|
|
finally
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
ZCompressCheck(deflateEnd(zstream));
|
|
{$ELSE}
|
|
deflateEnd(zstream);
|
|
{$ENDIF}
|
|
end;
|
|
|
|
ReallocMem(outBuffer, zstream.total_out);
|
|
outSize := zstream.total_out;
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
except
|
|
FreeMem(outBuffer);
|
|
raise;
|
|
{$ELSE}
|
|
finally
|
|
if Result < 0 then FreeMem(outBuffer);
|
|
{$ENDIF}
|
|
end;
|
|
end;
|
|
|
|
function ZCompressBuf2(const inBuffer: Pointer; inSize: Integer; out outBuffer: Pointer; out outSize: Integer): Integer;
|
|
const
|
|
delta = 256;
|
|
var
|
|
zstream : TZStreamRec;
|
|
begin
|
|
FillChar(zstream, SizeOf(TZStreamRec), 0);
|
|
|
|
outSize := ((inSize + (inSize div 10) + 12) + 255) and not 255;
|
|
GetMem(outBuffer, outSize);
|
|
Result := Z_OK;
|
|
try
|
|
zstream.next_in := inBuffer;
|
|
zstream.avail_in := inSize;
|
|
zstream.next_out := outBuffer;
|
|
zstream.avail_out := outSize;
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
ZCompressCheck(DeflateInit2(zstream, 1, 8, -15, 9, 0));
|
|
{$ELSE}
|
|
Result := DeflateInit2(zstream, 1, 8, -15, 9, 0);
|
|
if Result < 0 then Exit;
|
|
{$ENDIF}
|
|
|
|
try
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
Result := ZCompressCheck(deflate(zstream, Z_FINISH));
|
|
{$ELSE}
|
|
Result := deflate(zstream, Z_FINISH);
|
|
if Result < 0 then Exit;
|
|
{$ENDIF}
|
|
while Result <> Z_STREAM_END do begin
|
|
Inc(outSize, delta);
|
|
ReallocMem(outBuffer, outSize);
|
|
|
|
zstream.next_out := PChar(Integer(outBuffer) + zstream.total_out);
|
|
zstream.avail_out := delta;
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
Result := ZCompressCheck(deflate(zstream, Z_FINISH));
|
|
{$ELSE}
|
|
Result := deflate(zstream, Z_FINISH);
|
|
if Result < 0 then Exit;
|
|
{$ENDIF}
|
|
end; // while
|
|
finally
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
ZCompressCheck(deflateEnd(zstream));
|
|
{$ELSE}
|
|
deflateEnd(zstream);
|
|
{$ENDIF}
|
|
end;
|
|
|
|
ReallocMem(outBuffer, zstream.total_out);
|
|
outSize := zstream.total_out;
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
except
|
|
FreeMem(outBuffer);
|
|
raise;
|
|
{$ELSE}
|
|
finally
|
|
if Result < 0 then FreeMem(outBuffer);
|
|
{$ENDIF}
|
|
end;
|
|
end;
|
|
|
|
function ZDecompressBuf(const inBuffer: Pointer; inSize: Integer; out outBuffer: Pointer; out outSize: Integer; outEstimate: Integer): Integer;
|
|
var
|
|
zstream : TZStreamRec;
|
|
delta : Integer;
|
|
begin
|
|
FillChar(zstream, SizeOf(TZStreamRec), 0);
|
|
|
|
delta := (inSize + 255) and not 255;
|
|
|
|
if outEstimate = 0 then outSize := delta
|
|
else outSize := outEstimate;
|
|
Result := Z_OK;
|
|
GetMem(outBuffer, outSize);
|
|
try
|
|
zstream.next_in := inBuffer;
|
|
zstream.avail_in := inSize;
|
|
zstream.next_out := outBuffer;
|
|
zstream.avail_out := outSize;
|
|
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
ZDecompressCheck(InflateInit(zstream));
|
|
{$ELSE}
|
|
Result := InflateInit(zstream);
|
|
if Result < 0 then Exit;
|
|
{$ENDIF}
|
|
|
|
try
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
Result := ZDecompressCheck(inflate(zstream, Z_NO_FLUSH));
|
|
{$ELSE}
|
|
Result := inflate(zstream, Z_NO_FLUSH);
|
|
if Result < 0 then Exit;
|
|
{$ENDIF}
|
|
while (Result <> Z_STREAM_END) do begin
|
|
Inc(outSize, delta);
|
|
ReallocMem(outBuffer, outSize);
|
|
|
|
zstream.next_out := PChar(Integer(outBuffer) + zstream.total_out);
|
|
zstream.avail_out := delta;
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
Result := ZDecompressCheck(inflate(zstream, Z_NO_FLUSH));
|
|
{$ELSE}
|
|
Result := inflate(zstream, Z_NO_FLUSH);
|
|
if Result < 0 then Exit;
|
|
{$ENDIF}
|
|
end;
|
|
finally
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
ZDecompressCheck(inflateEnd(zstream));
|
|
{$ELSE}
|
|
inflateEnd(zstream);
|
|
{$ENDIF}
|
|
end;
|
|
|
|
ReallocMem(outBuffer, zstream.total_out);
|
|
outSize := zstream.total_out;
|
|
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
except
|
|
FreeMem(outBuffer);
|
|
raise;
|
|
{$ELSE}
|
|
finally
|
|
if Result < 0 then FreeMem(outBuffer);
|
|
{$ENDIF}
|
|
end;
|
|
end;
|
|
|
|
{** string routines *********************************************************}
|
|
|
|
function ZCompressStr(const s: string; level: TZCompressionLevel): string;
|
|
var
|
|
buffer : Pointer;
|
|
size : Integer;
|
|
begin
|
|
ZCompressBuf(PChar(s), Length(s), buffer, size, level);
|
|
SetLength(result, size);
|
|
Move(buffer^, pointer(result)^, size);
|
|
FreeMem(buffer);
|
|
end;
|
|
|
|
procedure ZFastCompressString(var s: string; level: TZCompressionLevel);
|
|
var
|
|
outBuf : Pointer;
|
|
outBytes : Integer;
|
|
begin
|
|
ZCompressBuf(pointer(s), length(s), outBuf, outBytes, level);
|
|
SetLength(s, outBytes);
|
|
MoveI32(pointer(outBuf)^, pointer(s)^, outBytes);
|
|
FreeMem(outBuf);
|
|
end;
|
|
|
|
procedure ZFastDecompressString(var s: string);
|
|
var
|
|
outBuf : Pointer;
|
|
outBytes : Integer;
|
|
begin
|
|
ZDecompressBuf(pointer(s), Length(s), outBuf, outBytes);
|
|
SetLength(s, outBytes);
|
|
MoveI32(pointer(outBuf)^, pointer(s)^, outBytes);
|
|
FreeMem(outBuf);
|
|
end;
|
|
|
|
procedure ZSendToBrowser(var s: string);
|
|
var
|
|
outBuf : Pointer;
|
|
outBytes : Integer;
|
|
begin
|
|
ZCompressBuf2(pointer(s), length(s), outBuf, outBytes);
|
|
SetLength(s, outBytes);
|
|
Move(pointer(outBuf)^, pointer(s)^, outBytes);
|
|
FreeMem(outBuf);
|
|
end;
|
|
|
|
function ZDecompressStr(const s: string): string;
|
|
var
|
|
buffer : Pointer;
|
|
size : Integer;
|
|
begin
|
|
ZDecompressBuf(PChar(s), Length(s), buffer, size);
|
|
SetLength(result, size);
|
|
Move(buffer^, pointer(result)^, size);
|
|
FreeMem(buffer);
|
|
end;
|
|
|
|
{** stream routines *********************************************************}
|
|
|
|
function ZCompressStream(inStream, outStream: PStream; level: TZCompressionLevel): Integer;
|
|
const
|
|
bufferSize = 32768;
|
|
var
|
|
zstream : TZStreamRec;
|
|
inBuffer : array[0..bufferSize - 1] of Char;
|
|
outBuffer : array[0..bufferSize - 1] of Char;
|
|
inSize : Integer;
|
|
outSize : Integer;
|
|
begin
|
|
FillChar(zstream, SizeOf(TZStreamRec), 0);
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
Result := Z_OK;
|
|
ZCompressCheck(DeflateInit(zstream, ZLevels[level]));
|
|
{$ELSE}
|
|
Result := DeflateInit(zstream, ZLevels[level]);
|
|
if Result < 0 then Exit;
|
|
{$ENDIF}
|
|
try
|
|
inSize := inStream.Read(inBuffer, bufferSize);
|
|
|
|
while inSize > 0 do begin
|
|
zstream.next_in := inBuffer;
|
|
zstream.avail_in := inSize;
|
|
|
|
repeat
|
|
zstream.next_out := outBuffer;
|
|
zstream.avail_out := bufferSize;
|
|
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
ZCompressCheck(deflate(zstream, Z_NO_FLUSH));
|
|
{$ELSE}
|
|
Result := deflate(zstream, Z_NO_FLUSH);
|
|
if Result < 0 then Exit;
|
|
{$ENDIF}
|
|
|
|
// outSize := zstream.next_out - outBuffer;
|
|
outSize := bufferSize - zstream.avail_out;
|
|
|
|
outStream.Write(outBuffer, outSize);
|
|
until (zstream.avail_in = 0) and (zstream.avail_out > 0);
|
|
|
|
inSize := inStream.Read(inBuffer, bufferSize);
|
|
end;
|
|
|
|
repeat
|
|
zstream.next_out := outBuffer;
|
|
zstream.avail_out := bufferSize;
|
|
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
Result := ZCompressCheck(deflate(zstream, Z_FINISH));
|
|
{$ELSE}
|
|
Result := deflate(zstream, Z_FINISH);
|
|
if Result < 0 then Break;
|
|
{$ENDIF}
|
|
|
|
// outSize := zstream.next_out - outBuffer;
|
|
outSize := bufferSize - zstream.avail_out;
|
|
|
|
outStream.Write(outBuffer, outSize);
|
|
until (Result = Z_STREAM_END) and (zstream.avail_out > 0);
|
|
finally
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
ZCompressCheck(deflateEnd(zstream));
|
|
{$ELSE}
|
|
deflateEnd(zstream);
|
|
{$ENDIF}
|
|
end;
|
|
end;
|
|
|
|
function ZDecompressStream(inStream, outStream: PStream): Integer;
|
|
const
|
|
bufferSize = 32768;
|
|
var
|
|
zstream : TZStreamRec;
|
|
inBuffer : array[0..bufferSize - 1] of Char;
|
|
outBuffer : array[0..bufferSize - 1] of Char;
|
|
inSize : Integer;
|
|
outSize : Integer;
|
|
begin
|
|
FillChar(zstream, SizeOf(TZStreamRec), 0);
|
|
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
Result := ZCompressCheck(InflateInit(zstream));
|
|
{$ELSE}
|
|
Result := InflateInit(zstream);
|
|
if Result < 0 then Exit;
|
|
{$ENDIF}
|
|
try
|
|
inSize := inStream.Read(inBuffer, bufferSize);
|
|
|
|
while inSize > 0 do begin
|
|
zstream.next_in := inBuffer;
|
|
zstream.avail_in := inSize;
|
|
|
|
repeat
|
|
zstream.next_out := outBuffer;
|
|
zstream.avail_out := bufferSize;
|
|
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
ZCompressCheck(inflate(zstream, Z_NO_FLUSH));
|
|
{$ELSE}
|
|
Result := inflate(zstream, Z_NO_FLUSH);
|
|
if Result < 0 then Exit;
|
|
{$ENDIF}
|
|
|
|
// outSize := zstream.next_out - outBuffer;
|
|
outSize := bufferSize - zstream.avail_out;
|
|
|
|
outStream.Write(outBuffer, outSize);
|
|
until (zstream.avail_in = 0) and (zstream.avail_out > 0);
|
|
|
|
inSize := inStream.Read(inBuffer, bufferSize);
|
|
end;
|
|
|
|
repeat
|
|
zstream.next_out := outBuffer;
|
|
zstream.avail_out := bufferSize;
|
|
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
Result := ZCompressCheck(inflate(zstream, Z_FINISH));
|
|
{$ELSE}
|
|
Result := inflate(zstream, Z_FINISH);
|
|
if Result < 0 then Break;
|
|
{$ENDIF}
|
|
|
|
// outSize := zstream.next_out - outBuffer;
|
|
outSize := bufferSize - zstream.avail_out;
|
|
|
|
outStream.Write(outBuffer, outSize);
|
|
until (Result = Z_STREAM_END) and (zstream.avail_out > 0);
|
|
finally
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
ZCompressCheck(inflateEnd(zstream));
|
|
{$ELSE}
|
|
inflateEnd(zstream);
|
|
{$ENDIF}
|
|
end;
|
|
end;
|
|
|
|
{** gzip Stream routines ******************************************************}
|
|
const
|
|
UnixDateDelta = 25569;
|
|
|
|
function DateTimeToUnix(ConvDate: TDateTime): Longint;
|
|
begin
|
|
//example: DateTimeToUnix(now);
|
|
Result := Round((ConvDate - UnixDateDelta) * 86400);
|
|
end;
|
|
|
|
function UnixToDateTime(USec: Longint): TDateTime;
|
|
begin
|
|
//Example: UnixToDateTime(1003187418);
|
|
Result := (Usec / 86400) + UnixDateDelta;
|
|
end;
|
|
|
|
function gZipCompressStream(inStream, outStream: PStream; var gzHdr: TgzipHeader; level: TZCompressionLevel = zcDefault; strategy: TZCompressionStrategy = zcsDefault): Integer;
|
|
var
|
|
rSize,
|
|
wSize,
|
|
zResult : LongInt;
|
|
done : Boolean;
|
|
iBuffer,
|
|
oBuffer : PChar; //Array [0..gzBufferSize-1] of Char;
|
|
fCrc : Cardinal;
|
|
zStream : TZStreamRec;
|
|
stamp : Integer;
|
|
|
|
begin
|
|
iBuffer := nil;
|
|
oBuffer := nil;
|
|
Result := Z_MEM_ERROR;
|
|
try
|
|
GetMem(iBuffer, gzBufferSize);
|
|
GetMem(oBuffer, gzBufferSize);
|
|
|
|
fCrc := 0;
|
|
FillChar(zStream, SizeOf(zStream), 0);
|
|
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
ZCompressCheck(DeflateInit2(zStream, ZLevels[level], Z_DEFLATED, -MAX_WBITS,
|
|
DEF_MEM_LEVEL, ZStrategy[strategy]));
|
|
{$ELSE}
|
|
Result := DeflateInit2(zStream, ZLevels[level], Z_DEFLATED, -MAX_WBITS,
|
|
DEF_MEM_LEVEL, ZStrategy[strategy]);
|
|
if Result < 0 then Exit;
|
|
{$ENDIF}
|
|
{ windowBits is passed < 0 to suppress zlib header }
|
|
oBuffer[0] := Char(gz_magic[0]);
|
|
oBuffer[1] := Char(gz_magic[1]); // gz Magic
|
|
oBuffer[2] := #08; // gz Compression method
|
|
oBuffer[3] := #0;
|
|
// set mtime
|
|
{
|
|
Inc(gzHdr.TimeStamp,gzTimeStampCorrection);
|
|
oBuffer[4]:=Lo(gzHdr.TimeStamp and $FFFF); oBuffer[5]:=Hi(gzHdr.TimeStamp and $FFFF);
|
|
oBuffer[6]:=Lo(gzHdr.TimeStamp shr 16); oBuffer[7]:=Hi(gzHdr.TimeStamp shr 16);
|
|
Dec(gzHdr.TimeStamp,gzTimeStampCorrection);
|
|
}
|
|
stamp := DateTimeToUnix(gzHdr.FileTime);
|
|
oBuffer[4] := Char(Lo(stamp and $FFFF));
|
|
oBuffer[5] := Char(Hi(stamp and $FFFF));
|
|
oBuffer[6] := Char(Lo(stamp shr 16));
|
|
oBuffer[7] := Char(Hi(stamp shr 16));
|
|
|
|
// xfl, os code sets to 0
|
|
oBuffer[8] := #0;
|
|
oBuffer[9] := #0;
|
|
|
|
if gzHdr.FileName <> '' then begin
|
|
oBuffer[3] := Char(Byte(oBuffer[3]) or GZF_ORIG_NAME);
|
|
end;
|
|
if gzHdr.Comment <> '' then begin
|
|
oBuffer[3] := Char(Byte(oBuffer[3]) or GZF_COMMENT);
|
|
end;
|
|
if gzHdr.Extra <> '' then begin
|
|
oBuffer[3] := Char(Byte(oBuffer[3]) or GZF_EXTRA_FIELD);
|
|
end;
|
|
wSize := outStream.Write(oBuffer^, 10);
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
if wSize <> 10 then ZCompressCheck(Z_WRITE_ERROR);
|
|
{$ELSE}
|
|
if wSize <> 10 then begin
|
|
Result := Z_WRITE_ERROR;
|
|
Exit;
|
|
end;
|
|
{$ENDIF}
|
|
|
|
// extra
|
|
if (byte(oBuffer[3]) and GZF_EXTRA_FIELD) <> 0 then begin
|
|
rSize := Length(gzHdr.Extra);
|
|
Move(gzHdr.Extra[1], iBuffer^, rSize);
|
|
iBuffer[rSize] := #0;
|
|
Inc(rSize);
|
|
wSize := outStream.Write(iBuffer^, rSize);
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
if wSize <> rSize then ZCompressCheck(Z_WRITE_ERROR);
|
|
{$ELSE}
|
|
if wSize <> rSize then begin
|
|
Result := Z_WRITE_ERROR;
|
|
Exit;
|
|
end;
|
|
{$ENDIF}
|
|
end;
|
|
// filename
|
|
if (byte(oBuffer[3]) and GZF_ORIG_NAME) <> 0 then begin
|
|
rSize := Length(gzHdr.FileName);
|
|
Move(gzHdr.FileName[1], iBuffer^, rSize);
|
|
iBuffer[rSize] := #0;
|
|
Inc(rSize);
|
|
wSize := outStream.Write(iBuffer^, rSize);
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
if wSize <> rSize then ZCompressCheck(Z_WRITE_ERROR);
|
|
{$ELSE}
|
|
if wSize <> rSize then begin
|
|
Result := Z_WRITE_ERROR;
|
|
Exit;
|
|
end;
|
|
{$ENDIF}
|
|
end;
|
|
// comment
|
|
if (byte(oBuffer[3]) and GZF_COMMENT) <> 0 then begin
|
|
rSize := Length(gzHdr.Comment);
|
|
Move(gzHdr.Comment[1], iBuffer^, rSize);
|
|
iBuffer[rSize] := #0;
|
|
Inc(rSize);
|
|
wSize := outStream.Write(iBuffer^, rSize);
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
if wSize <> rSize then ZCompressCheck(Z_WRITE_ERROR);
|
|
{$ELSE}
|
|
if wSize <> rSize then begin
|
|
Result := Z_WRITE_ERROR;
|
|
Exit;
|
|
end;
|
|
{$ENDIF}
|
|
end;
|
|
// hcrc
|
|
|
|
rSize := inStream.Read(iBuffer^, gzBufferSize);
|
|
zStream.next_out := PChar(oBuffer);
|
|
zStream.avail_out := gzBufferSize;
|
|
repeat
|
|
//DoProgressEvent;
|
|
zStream.next_in := PChar(iBuffer);
|
|
zStream.avail_in := rSize;
|
|
while (zStream.avail_in <> 0) do begin
|
|
if (zStream.avail_out = 0) then begin
|
|
zStream.next_out := PChar(oBuffer);
|
|
wSize := outStream.Write(oBuffer^, gzBufferSize);
|
|
if (wSize <> gzBufferSize) then begin
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
ZCompressCheck(Z_WRITE_ERROR);
|
|
{$ELSE}
|
|
Result := Z_WRITE_ERROR;
|
|
Exit;
|
|
{$ENDIF}
|
|
end;
|
|
zStream.avail_out := gzBufferSize;
|
|
end;
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
ZCompressCheck(deflate(zStream, Z_NO_FLUSH));
|
|
{$ELSE}
|
|
Result := deflate(zStream, Z_NO_FLUSH);
|
|
if Result < 0 then Exit;
|
|
{$ENDIF}
|
|
end; // while
|
|
fCrc := Crc32(fCrc, PChar(iBuffer), rSize);
|
|
rSize := inStream.Read(iBuffer^, gzBufferSize);
|
|
until rSize = 0;
|
|
{ flush buffers }
|
|
zStream.avail_in := 0; { should be zero already anyway }
|
|
done := False;
|
|
|
|
repeat
|
|
rSize := gzBufferSize - zStream.avail_out;
|
|
if (rSize <> 0) then begin
|
|
wSize := outStream.Write(oBuffer^, rSize);
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
if (wSize <> rSize) then ZCompressCheck(Z_WRITE_ERROR);
|
|
{$ELSE}
|
|
if (wSize <> rSize) then begin
|
|
Result := Z_WRITE_ERROR;
|
|
Exit;
|
|
end;
|
|
{$ENDIF}
|
|
zStream.next_out := PChar(oBuffer);
|
|
zStream.avail_out := gzBufferSize;
|
|
end;
|
|
if done then Break;
|
|
zResult := deflate(zStream, Z_FINISH);
|
|
if (rSize = 0) and (zResult = Z_BUF_ERROR) then
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
else ZCompressCheck(zResult);
|
|
{$ELSE}
|
|
else begin
|
|
Result := zResult;
|
|
if Result < 0 then Exit;
|
|
end;
|
|
{$ENDIF}
|
|
{ deflate has finished flushing only when it hasn't used up
|
|
all the available space in the output buffer: }
|
|
done := (zStream.avail_out <> 0) or (zResult = Z_STREAM_END);
|
|
until False;
|
|
wSize := outStream.Write(fCrc, 4);
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
if wSize <> 4 then ZCompressCheck(Z_WRITE_ERROR);
|
|
{$ELSE}
|
|
if wSize <> 4 then begin
|
|
Result := Z_WRITE_ERROR;
|
|
Exit;
|
|
end;
|
|
{$ENDIF}
|
|
rSize := inStream.Size;
|
|
wSize := outStream.Write(rSize, 4);
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
if wSize <> 4 then ZCompressCheck(Z_WRITE_ERROR);
|
|
{$ELSE}
|
|
if wSize <> 4 then begin
|
|
Result := Z_WRITE_ERROR;
|
|
Exit;
|
|
end;
|
|
{$ENDIF}
|
|
Result := Z_OK;
|
|
finally
|
|
deflateEnd(zStream);
|
|
if Assigned(iBuffer) then FreeMem(iBuffer);
|
|
if Assigned(oBuffer) then FreeMem(oBuffer);
|
|
end;
|
|
end;
|
|
|
|
function gZipCompressStream(inStream, outStream: PStream; level: TZCompressionLevel = zcDefault; strategy: TZCompressionStrategy = zcsDefault): Integer; overload;
|
|
var
|
|
gzHdr : TgzipHeader;
|
|
begin
|
|
FillChar(gzHdr, SizeOf(gzHdr), 0);
|
|
gzHdr.FileTime := Date;
|
|
Result := gZipCompressStream(inStream, outStream, gzHdr, level, strategy);
|
|
end;
|
|
|
|
function gZipDecompressStreamHeader(inStream: PStream; var gzHdr: TgzipHeader): Integer;
|
|
var
|
|
i, c, flg : LongInt;
|
|
fEOF : Boolean;
|
|
|
|
function gz_getbyte: Integer;
|
|
var
|
|
b, c : Integer;
|
|
begin
|
|
b := 0;
|
|
c := inStream.Read(b, 1);
|
|
if c = 0 then begin
|
|
fEOF := True;
|
|
Result := Z_EOF;
|
|
end
|
|
else Result := b;
|
|
end;
|
|
|
|
function gz_getlong: Integer;
|
|
var
|
|
b, c : Integer;
|
|
begin
|
|
b := 0;
|
|
c := inStream.Read(b, 4);
|
|
if c < 4 then begin
|
|
fEOF := True;
|
|
Result := Z_EOF;
|
|
end
|
|
else Result := b;
|
|
end;
|
|
begin
|
|
// fTransparent := False;
|
|
Result := Z_OK;
|
|
fEOF := False;
|
|
gzHdr.FileName := '';
|
|
gzHdr.Comment := '';
|
|
gzHdr.Extra := '';
|
|
try
|
|
for i := 0 to 1 do begin
|
|
flg := gz_getbyte;
|
|
if (flg <> gz_magic[i]) then begin
|
|
fEOF := True;
|
|
exit;
|
|
end;
|
|
end;
|
|
c := gz_getbyte; // method
|
|
flg := gz_getbyte; // flags
|
|
if (c <> Z_DEFLATED) or ((flg and GZF_RESERVED) <> 0) then begin
|
|
fEOF := True;
|
|
exit;
|
|
end;
|
|
|
|
gzHdr.FileTime := UnixToDateTime(gz_getLong);
|
|
gz_getbyte;
|
|
gz_getbyte; { skip xflags and OS code }
|
|
|
|
if (flg and GZF_EXTRA_FIELD) <> 0 then begin // skip extra fields
|
|
i := gz_getbyte + (gz_getbyte shl 8); // length of extra
|
|
SetLength(gzHdr.Extra, i);
|
|
c := inStream.Read(gzHdr.Extra, i);
|
|
if c <> i then begin
|
|
fEOF := True;
|
|
Exit;
|
|
end;
|
|
end;
|
|
if (flg and GZF_ORIG_NAME) <> 0 then begin // extract File Name
|
|
repeat
|
|
c := gz_getbyte;
|
|
if (c <> 0) and (c <> Z_EOF) then gzHdr.FileName := gzHdr.FileName + char(c);
|
|
until (c = 0) or (c = Z_EOF);
|
|
end;
|
|
if (flg and GZF_COMMENT) <> 0 then begin // extract Comment
|
|
repeat
|
|
c := gz_getbyte;
|
|
if (c <> 0) and (c <> Z_EOF) then gzHdr.Comment := gzHdr.Comment + char(c);
|
|
until (c = 0) or (c = Z_EOF);
|
|
end;
|
|
if (flg and GZF_HEAD_CRC) <> 0 then begin // skip head crc
|
|
gz_getbyte;
|
|
gz_getbyte;
|
|
end;
|
|
finally
|
|
if fEOF then Result := Z_DATA_ERROR
|
|
else Result := Z_OK;
|
|
end;
|
|
end;
|
|
|
|
function gZipDecompressStreamBody(inStream, outStream: PStream): Integer;
|
|
var
|
|
iBuffer,
|
|
oBuffer : PChar; //Array [0..gzBufferSize-1] of Char;
|
|
fCrc : Cardinal;
|
|
zStream : TZStreamRec;
|
|
rSize,
|
|
wSize : LongInt;
|
|
startCRC : PChar;
|
|
fileCRC,
|
|
fileSize : Cardinal;
|
|
fEOF : Boolean;
|
|
|
|
function gz_getbyte: Integer;
|
|
begin
|
|
// if (eof) then result:=-1;
|
|
if (zStream.avail_in = 0) then begin
|
|
zStream.avail_in := inStream.Read(iBuffer^, gzBufferSize);
|
|
if (zStream.avail_in = 0) then begin
|
|
Result := Z_EOF;
|
|
fEOF := True;
|
|
exit;
|
|
end
|
|
else zStream.next_in := PChar(iBuffer);
|
|
end;
|
|
Dec(zStream.avail_in);
|
|
Result := Byte(zStream.next_in[0]);
|
|
Inc(zStream.next_in);
|
|
end;
|
|
|
|
function gz_getLong: Cardinal;
|
|
var
|
|
c : Integer;
|
|
begin
|
|
c := gz_getbyte;
|
|
c := c + gz_getbyte shl 8;
|
|
c := c + gz_getbyte shl 16;
|
|
c := c + gz_getbyte shl 24;
|
|
Result := Cardinal(c);
|
|
end;
|
|
begin
|
|
iBuffer := nil;
|
|
oBuffer := nil;
|
|
Result := Z_MEM_ERROR;
|
|
try
|
|
GetMem(iBuffer, gzBufferSize);
|
|
GetMem(oBuffer, gzBufferSize);
|
|
fEOF := False;
|
|
{Check the gzip header of a gz_stream opened for reading.
|
|
Set the stream mode to transparent if the gzip magic header is not present.}
|
|
|
|
FillChar(zStream, SizeOf(zStream), 0);
|
|
zStream.next_in := pChar(iBuffer);
|
|
fCRC := 0;
|
|
{ windowBits is passed < 0 to tell that there is no zlib header }
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
ZDecompressCheck(InflateInit2(zStream, -MAX_WBITS));
|
|
{$ELSE}
|
|
Result := InflateInit2(zStream, -MAX_WBITS);
|
|
if Result < 0 then Exit;
|
|
{$ENDIF}
|
|
while not fEOF do begin
|
|
// gzread()
|
|
// DoProgressEvent;
|
|
startCRC := PChar(oBuffer);
|
|
zStream.next_out := PChar(oBuffer);
|
|
zStream.avail_out := gzBufferSize;
|
|
// rSize := 0;
|
|
Result := Z_OK;
|
|
while zStream.avail_out <> 0 do begin
|
|
// not transparent
|
|
if (zStream.avail_in = 0) and (not fEOF) then begin
|
|
zStream.avail_in := inStream.Read(iBuffer^, gzBufferSize);
|
|
if (zStream.avail_in = 0) then fEOF := True;
|
|
zStream.next_in := PChar(iBuffer);
|
|
end;
|
|
Result := inflate(zStream, Z_NO_FLUSH);
|
|
if (Result = Z_STREAM_END) then begin
|
|
{ Check CRC and original size }
|
|
fCrc := crc32(fCrc, PChar(StartCRC), (zStream.next_out - startCRC));
|
|
startCRC := zStream.next_out;
|
|
|
|
fileCRC := gz_getLong;
|
|
fileSize := gz_getLong;
|
|
if (fCrc <> fileCRC) then
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
ZDecompressCheck(Z_CRC_ERROR)
|
|
{$ELSE}
|
|
Result := Z_CRC_ERROR
|
|
{$ENDIF}
|
|
else
|
|
if (Cardinal(zStream.total_out) <> fileSize) then
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
ZDecompressCheck(Z_SIZE_ERROR)
|
|
{$ELSE}
|
|
Result := Z_SIZE_ERROR
|
|
{$ENDIF}
|
|
else begin
|
|
if zStream.avail_in > 0 then inStream.Seek(-zStream.avail_in, spCurrent);
|
|
fEOF := True;
|
|
end;
|
|
end;
|
|
if (Result <> Z_OK) or (fEOF) then break;
|
|
end; // while zStream.avail_out<>0
|
|
// end of gzread()
|
|
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
ZDecompressCheck(Result);
|
|
{$ELSE}
|
|
if Result < 0 then Exit;
|
|
{$ENDIF}
|
|
fCrc := crc32(fCrc, PChar(oBuffer), (zStream.next_out - startCRC));
|
|
rSize := gzBufferSize - zStream.avail_out;
|
|
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
if rSize < 0 then ZDecompressCheck(rSize);
|
|
{$ELSE}
|
|
if rSize <= 0 then break;
|
|
{$ENDIF}
|
|
wSize := outStream.Write(oBuffer^, rSize);
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
if (rSize <> wSize) then ZDecompressCheck(Z_WRITE_ERROR);
|
|
{$ELSE}
|
|
if (rSize <> wSize) then begin
|
|
Result := Z_WRITE_ERROR;
|
|
Exit;
|
|
end;
|
|
{$ENDIF}
|
|
end;
|
|
if Result = Z_STREAM_END then Result := Z_OK;
|
|
finally
|
|
inflateEnd(zStream);
|
|
if Assigned(iBuffer) then FreeMem(iBuffer);
|
|
if Assigned(oBuffer) then FreeMem(oBuffer);
|
|
end;
|
|
end;
|
|
|
|
function gZipDecompressStream(inStream, outStream: PStream; var gzHdr: TgzipHeader): Integer;
|
|
begin
|
|
Result := gZipDecompressStreamHeader(inStream, gzHdr);
|
|
if (Result >= 0) then
|
|
Result := gZipDecompressStreamBody(inStream, outStream);
|
|
end;
|
|
|
|
function gZipDecompressString(const S: String): String;
|
|
var
|
|
Rslt: Integer;
|
|
gzHdr: TgzipHeader;
|
|
inStream: PStream;
|
|
outStream: PStream;
|
|
begin
|
|
Result := '';
|
|
inStream := NewExMemoryStream(@S[1], Length(S));
|
|
Rslt := gZipDecompressStreamHeader(inStream, gzHdr);
|
|
if (Rslt >= 0) then begin
|
|
outStream := NewMemoryStream;
|
|
Rslt := gZipDecompressStreamBody(inStream, outStream);
|
|
if (Rslt >= 0) then begin
|
|
outStream.Position := 0;
|
|
Result := outStream.ReadStrLen(outStream.Size);
|
|
end;
|
|
outStream.Free;
|
|
end;
|
|
inStream.Free;
|
|
end;
|
|
|
|
{****************************************************************************}
|
|
{** BZip implementation *****************************************************}
|
|
{****************************************************************************}
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
|
|
function CCheck(code: Integer): Integer;
|
|
begin
|
|
Result := code;
|
|
if code < 0 then
|
|
raise Exception.CreateFMT(e_Convert, 'Compression Error %d - %s', [code, BZ_Error_Msg[-code]]);
|
|
end;
|
|
|
|
function DCheck(code: Integer): Integer;
|
|
begin
|
|
Result := code;
|
|
if code < 0 then
|
|
raise Exception.CreateFMT(e_Convert, 'Decompression Error %d - %s', [code, BZ_Error_Msg[-code]]);
|
|
end;
|
|
{$ENDIF}
|
|
|
|
function BZCompressBuf(const InBuf: Pointer; InBytes: Integer; out OutBuf: Pointer; out OutBytes: Integer): Integer;
|
|
var
|
|
strm : TBZStreamRec;
|
|
P : Pointer;
|
|
begin
|
|
FillChar(strm, sizeof(strm), 0);
|
|
strm.bzalloc := bzip2AllocMem;
|
|
strm.bzfree := bzip2FreeMem;
|
|
OutBytes := ((InBytes + (InBytes div 10) + 12) + 255) and not 255;
|
|
GetMem(OutBuf, OutBytes);
|
|
Result := BZ_OK;
|
|
try
|
|
strm.next_in := InBuf;
|
|
strm.avail_in := InBytes;
|
|
strm.next_out := OutBuf;
|
|
strm.avail_out := OutBytes;
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
CCheck(BZ2_bzCompressInit(strm, 9, 0, 0));
|
|
{$ELSE}
|
|
Result := BZ2_bzCompressInit(strm, 9, 0, 0);
|
|
if Result < 0 then Exit;
|
|
{$ENDIF}
|
|
try
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
Result := CCheck(BZ2_bzCompress(strm, BZ_FINISH));
|
|
{$ELSE}
|
|
Result := BZ2_bzCompress(strm, BZ_FINISH);
|
|
if Result < 0 then Exit;
|
|
{$ENDIF}
|
|
while Result <> BZ_STREAM_END do begin
|
|
P := OutBuf;
|
|
Inc(OutBytes, 256);
|
|
ReallocMem(OutBuf, OutBytes);
|
|
strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P)));
|
|
strm.avail_out := 256;
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
Result := CCheck(BZ2_bzCompress(strm, BZ_FINISH));
|
|
{$ELSE}
|
|
Result := BZ2_bzCompress(strm, BZ_FINISH);
|
|
if Result < 0 then Exit;
|
|
{$ENDIF}
|
|
end;
|
|
finally
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
CCheck(BZ2_bzCompressEnd(strm));
|
|
{$ELSE}
|
|
BZ2_bzCompressEnd(strm);
|
|
{$ENDIF}
|
|
end;
|
|
ReallocMem(OutBuf, strm.total_out_lo32);
|
|
OutBytes := strm.total_out_lo32;
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
except
|
|
FreeMem(outBuf);
|
|
raise;
|
|
{$ELSE}
|
|
finally
|
|
if Result < 0 then FreeMem(outBuf);
|
|
{$ENDIF}
|
|
end;
|
|
end;
|
|
|
|
function BZDecompressBuf(const InBuf: Pointer; InBytes: Integer; OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer): Integer;
|
|
var
|
|
strm : TBZStreamRec;
|
|
P : Pointer;
|
|
BufInc : Integer;
|
|
begin
|
|
FillChar(strm, sizeof(strm), 0);
|
|
strm.bzalloc := bzip2AllocMem;
|
|
strm.bzfree := bzip2FreeMem;
|
|
BufInc := (InBytes + 255) and not 255;
|
|
Result := BZ_OK;
|
|
if OutEstimate = 0 then
|
|
OutBytes := BufInc
|
|
else
|
|
OutBytes := OutEstimate;
|
|
GetMem(OutBuf, OutBytes);
|
|
try
|
|
strm.next_in := InBuf;
|
|
strm.avail_in := InBytes;
|
|
strm.next_out := OutBuf;
|
|
strm.avail_out := OutBytes;
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
DCheck(BZ2_bzDecompressInit(strm, 0, 0));
|
|
{$ELSE}
|
|
Result := BZ2_bzDecompressInit(strm, 0, 0);
|
|
if Result < 0 then Exit;
|
|
{$ENDIF}
|
|
try
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
Result := DCheck(BZ2_bzDecompress(strm));
|
|
{$ELSE}
|
|
Result := BZ2_bzDecompress(strm);
|
|
if Result < 0 then Exit;
|
|
{$ENDIF}
|
|
while Result <> BZ_STREAM_END do begin
|
|
P := OutBuf;
|
|
Inc(OutBytes, BufInc);
|
|
ReallocMem(OutBuf, OutBytes);
|
|
strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P)));
|
|
strm.avail_out := BufInc;
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
Result := DCheck(BZ2_bzDecompress(strm));
|
|
{$ELSE}
|
|
Result := BZ2_bzDecompress(strm);
|
|
if Result < 0 then Exit;
|
|
{$ENDIF}
|
|
end;
|
|
finally
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
DCheck(BZ2_bzDecompressEnd(strm));
|
|
{$ELSE}
|
|
BZ2_bzDecompressEnd(strm);
|
|
{$ENDIF}
|
|
end;
|
|
ReallocMem(OutBuf, strm.total_out_lo32);
|
|
OutBytes := strm.total_out_lo32;
|
|
except
|
|
FreeMem(OutBuf);
|
|
raise
|
|
end;
|
|
end;
|
|
|
|
function BZCompressStream(inStream, outStream: PStream; BlockSize100k: TBlockSize100k = 5): Integer;
|
|
var
|
|
FBZRec : TBZStreamRec;
|
|
iBuffer,
|
|
oBuffer : PChar;
|
|
wSize,
|
|
rSize : Integer;
|
|
begin
|
|
Result := BZ_MEM_ERROR;
|
|
iBuffer := nil;
|
|
oBuffer := nil;
|
|
FillChar(FBZRec, SizeOf(FBZRec), 0);
|
|
// FBZRec.bzalloc := bzip2AllocMem;
|
|
// FBZRec.bzfree := bzip2FreeMem;
|
|
try
|
|
GetMem(iBuffer, bzBufferSize);
|
|
GetMem(oBuffer, bzBufferSize);
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
CCheck(BZ2_bzCompressInit(FBZRec, BlockSize100k, 0, 0));
|
|
{$ELSE}
|
|
Result := BZ2_bzCompressInit(FBZRec, BlockSize100k, 0, 0);
|
|
if Result < 0 then Exit;
|
|
{$ENDIF}
|
|
FBZRec.next_out := PChar(oBuffer);
|
|
FBZRec.avail_out := bzBufferSize;
|
|
rSize := inStream.Read(iBuffer^, bzBufferSize);
|
|
repeat
|
|
//DoProgressEvent;
|
|
FBZRec.next_in := PChar(iBuffer);
|
|
FBZRec.avail_in := rSize;
|
|
while (FBZRec.avail_in > 0) do begin
|
|
if (FBZRec.avail_out = 0) then begin
|
|
wSize := outStream.Write(oBuffer^, bzBufferSize);
|
|
if (wSize <> bzBufferSize) then begin
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
CCheck(BZ_IO_ERROR);
|
|
{$ELSE}
|
|
Result := BZ_IO_ERROR;
|
|
Exit;
|
|
{$ENDIF}
|
|
end;
|
|
FBZRec.next_out := PChar(oBuffer);
|
|
FBZRec.avail_out := bzBufferSize;
|
|
end;
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
CCheck(BZ2_bzCompress(FBZRec, BZ_RUN));
|
|
{$ELSE}
|
|
Result := BZ2_bzCompress(FBZRec, BZ_RUN);
|
|
if Result < 0 then Exit;
|
|
{$ENDIF}
|
|
end; // while
|
|
rSize := inStream.Read(iBuffer^, bzBufferSize);
|
|
until rSize = 0;
|
|
{ flush buffers }
|
|
FBZRec.avail_in := 0; { should be zero already anyway }
|
|
repeat
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
Result := CCheck(BZ2_bzCompress(FBZRec, BZ_FINISH));
|
|
{$ELSE}
|
|
Result := BZ2_bzCompress(FBZRec, BZ_FINISH);
|
|
if Result < 0 then Break;
|
|
{$ENDIF}
|
|
rSize := bzBufferSize - FBZRec.avail_out;
|
|
wSize := outStream.Write(oBuffer^, rSize);
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
if (wSize <> rSize) then CCheck(BZ_IO_ERROR);
|
|
{$ELSE}
|
|
if (wSize <> rSize) then begin
|
|
Result := BZ_IO_ERROR;
|
|
break;
|
|
end;
|
|
{$ENDIF}
|
|
FBZRec.next_out := PChar(oBuffer);
|
|
FBZRec.avail_out := bzBufferSize;
|
|
until Result = BZ_STREAM_END;
|
|
finally
|
|
if Result = BZ_STREAM_END then Result := BZ_OK;
|
|
BZ2_bzCompressEnd(FBZRec);
|
|
if Assigned(iBuffer) then FreeMem(iBuffer);
|
|
if Assigned(oBuffer) then FreeMem(oBuffer);
|
|
end;
|
|
|
|
end;
|
|
|
|
function BZDecompressStream(inStream, outStream: PStream): Integer;
|
|
var
|
|
FBZRec : TBZStreamRec;
|
|
iBuffer,
|
|
oBuffer : PChar;
|
|
wSize,
|
|
rSize : Integer;
|
|
begin
|
|
Result := BZ_MEM_ERROR;
|
|
iBuffer := nil;
|
|
oBuffer := nil;
|
|
FillChar(FBZRec, SizeOf(FBZRec), 0);
|
|
try
|
|
GetMem(iBuffer, bzBufferSize);
|
|
GetMem(oBuffer, bzBufferSize);
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
DCheck(BZ2_bzDecompressInit(FBZRec, 0, 0));
|
|
{$ELSE}
|
|
Result := BZ2_bzDecompressInit(FBZRec, 0, 0);
|
|
if Result < 0 then Exit;
|
|
{$ENDIF}
|
|
rSize := inStream.Read(iBuffer^, bzBufferSize);
|
|
FBZRec.next_in := PChar(iBuffer);
|
|
FBZRec.avail_in := rSize;
|
|
repeat
|
|
FBZRec.next_out := PChar(oBuffer);
|
|
FBZRec.avail_out := bzBufferSize;
|
|
Result := 0;
|
|
while (FBZRec.avail_out > 0) and (Result <> BZ_STREAM_END) do begin
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
Result := CCheck(BZ2_bzDecompress(FBZRec));
|
|
{$ELSE}
|
|
Result := BZ2_bzDecompress(FBZRec);
|
|
if Result < 0 then Break;
|
|
{$ENDIF}
|
|
if FBZRec.avail_in = 0 then begin
|
|
rSize := inStream.Read(iBuffer^, bzBufferSize);
|
|
FBZRec.next_in := PChar(iBuffer);
|
|
FBZRec.avail_in := rSize;
|
|
end;
|
|
end;
|
|
FBZRec.avail_out := bzBufferSize - FBZRec.avail_out;
|
|
wSize := outStream.Write(oBuffer^, FBZRec.avail_out);
|
|
{$IFDEF USE_EXCEPTIONS}
|
|
if FBZRec.avail_out <> wSize then CCheck(BZ_IO_ERROR);
|
|
{$ELSE}
|
|
if FBZRec.avail_out <> wSize then Result := BZ_IO_ERROR;
|
|
{$ENDIF}
|
|
until (rSize = 0) or (Result < 0);
|
|
finally
|
|
if Result = BZ_STREAM_END then Result := BZ_OK;
|
|
BZ2_bzDecompressEnd(FBZRec);
|
|
if Assigned(iBuffer) then FreeMem(iBuffer);
|
|
if Assigned(oBuffer) then FreeMem(oBuffer);
|
|
end;
|
|
end;
|
|
|
|
end.
|