//{$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\blocksort.obj} {$L bz2\huffman.obj} {$L bz2\compress.obj} {$L bz2\decompress.obj} {$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(adler: LongInt; const buf: PChar; len: Integer): LongInt; external; function compressBound(sourceLen: LongInt): LongInt; external; // function InflateInit(var stream: TZStreamRec): Integer; 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.