| @@ -0,0 +1,51 @@ | ||
| This is a patched version of zlib, modified to use | ||
| Pentium-Pro-optimized assembly code in the deflation algorithm. The | ||
| files changed/added by this patch are: | ||
|
|
||
| README.686 | ||
| match.S | ||
|
|
||
| The speedup that this patch provides varies, depending on whether the | ||
| compiler used to build the original version of zlib falls afoul of the | ||
| PPro's speed traps. My own tests show a speedup of around 10-20% at | ||
| the default compression level, and 20-30% using -9, against a version | ||
| compiled using gcc 2.7.2.3. Your mileage may vary. | ||
|
|
||
| Note that this code has been tailored for the PPro/PII in particular, | ||
| and will not perform particuarly well on a Pentium. | ||
|
|
||
| If you are using an assembler other than GNU as, you will have to | ||
| translate match.S to use your assembler's syntax. (Have fun.) | ||
|
|
||
| Brian Raiter | ||
| breadbox@muppetlabs.com | ||
| April, 1998 | ||
|
|
||
|
|
||
| Added for zlib 1.1.3: | ||
|
|
||
| The patches come from | ||
| http://www.muppetlabs.com/~breadbox/software/assembly.html | ||
|
|
||
| To compile zlib with this asm file, copy match.S to the zlib directory | ||
| then do: | ||
|
|
||
| CFLAGS="-O3 -DASMV" ./configure | ||
| make OBJA=match.o | ||
|
|
||
|
|
||
| Update: | ||
|
|
||
| I've been ignoring these assembly routines for years, believing that | ||
| gcc's generated code had caught up with it sometime around gcc 2.95 | ||
| and the major rearchitecting of the Pentium 4. However, I recently | ||
| learned that, despite what I believed, this code still has some life | ||
| in it. On the Pentium 4 and AMD64 chips, it continues to run about 8% | ||
| faster than the code produced by gcc 4.1. | ||
|
|
||
| In acknowledgement of its continuing usefulness, I've altered the | ||
| license to match that of the rest of zlib. Share and Enjoy! | ||
|
|
||
| Brian Raiter | ||
| breadbox@muppetlabs.com | ||
| April, 2007 |
| @@ -0,0 +1,357 @@ | ||
| /* match.S -- x86 assembly version of the zlib longest_match() function. | ||
| * Optimized for the Intel 686 chips (PPro and later). | ||
| * | ||
| * Copyright (C) 1998, 2007 Brian Raiter <breadbox@muppetlabs.com> | ||
| * | ||
| * This software is provided 'as-is', without any express or implied | ||
| * warranty. In no event will the author be held liable for any damages | ||
| * arising from the use of this software. | ||
| * | ||
| * Permission is granted to anyone to use this software for any purpose, | ||
| * including commercial applications, and to alter it and redistribute it | ||
| * freely, subject to the following restrictions: | ||
| * | ||
| * 1. The origin of this software must not be misrepresented; you must not | ||
| * claim that you wrote the original software. If you use this software | ||
| * in a product, an acknowledgment in the product documentation would be | ||
| * appreciated but is not required. | ||
| * 2. Altered source versions must be plainly marked as such, and must not be | ||
| * misrepresented as being the original software. | ||
| * 3. This notice may not be removed or altered from any source distribution. | ||
| */ | ||
|
|
||
| #ifndef NO_UNDERLINE | ||
| #define match_init _match_init | ||
| #define longest_match _longest_match | ||
| #endif | ||
|
|
||
| #define MAX_MATCH (258) | ||
| #define MIN_MATCH (3) | ||
| #define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1) | ||
| #define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7) | ||
|
|
||
| /* stack frame offsets */ | ||
|
|
||
| #define chainlenwmask 0 /* high word: current chain len */ | ||
| /* low word: s->wmask */ | ||
| #define window 4 /* local copy of s->window */ | ||
| #define windowbestlen 8 /* s->window + bestlen */ | ||
| #define scanstart 16 /* first two bytes of string */ | ||
| #define scanend 12 /* last two bytes of string */ | ||
| #define scanalign 20 /* dword-misalignment of string */ | ||
| #define nicematch 24 /* a good enough match size */ | ||
| #define bestlen 28 /* size of best match so far */ | ||
| #define scan 32 /* ptr to string wanting match */ | ||
|
|
||
| #define LocalVarsSize (36) | ||
| /* saved ebx 36 */ | ||
| /* saved edi 40 */ | ||
| /* saved esi 44 */ | ||
| /* saved ebp 48 */ | ||
| /* return address 52 */ | ||
| #define deflatestate 56 /* the function arguments */ | ||
| #define curmatch 60 | ||
|
|
||
| /* All the +zlib1222add offsets are due to the addition of fields | ||
| * in zlib in the deflate_state structure since the asm code was first written | ||
| * (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)"). | ||
| * (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0"). | ||
| * if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8"). | ||
| */ | ||
|
|
||
| #define zlib1222add (8) | ||
|
|
||
| #define dsWSize (36+zlib1222add) | ||
| #define dsWMask (44+zlib1222add) | ||
| #define dsWindow (48+zlib1222add) | ||
| #define dsPrev (56+zlib1222add) | ||
| #define dsMatchLen (88+zlib1222add) | ||
| #define dsPrevMatch (92+zlib1222add) | ||
| #define dsStrStart (100+zlib1222add) | ||
| #define dsMatchStart (104+zlib1222add) | ||
| #define dsLookahead (108+zlib1222add) | ||
| #define dsPrevLen (112+zlib1222add) | ||
| #define dsMaxChainLen (116+zlib1222add) | ||
| #define dsGoodMatch (132+zlib1222add) | ||
| #define dsNiceMatch (136+zlib1222add) | ||
|
|
||
|
|
||
| .file "match.S" | ||
|
|
||
| .globl match_init, longest_match | ||
|
|
||
| .text | ||
|
|
||
| /* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */ | ||
| .cfi_sections .debug_frame | ||
|
|
||
| longest_match: | ||
|
|
||
| .cfi_startproc | ||
| /* Save registers that the compiler may be using, and adjust %esp to */ | ||
| /* make room for our stack frame. */ | ||
|
|
||
| pushl %ebp | ||
| .cfi_def_cfa_offset 8 | ||
| .cfi_offset ebp, -8 | ||
| pushl %edi | ||
| .cfi_def_cfa_offset 12 | ||
| pushl %esi | ||
| .cfi_def_cfa_offset 16 | ||
| pushl %ebx | ||
| .cfi_def_cfa_offset 20 | ||
| subl $LocalVarsSize, %esp | ||
| .cfi_def_cfa_offset LocalVarsSize+20 | ||
|
|
||
| /* Retrieve the function arguments. %ecx will hold cur_match */ | ||
| /* throughout the entire function. %edx will hold the pointer to the */ | ||
| /* deflate_state structure during the function's setup (before */ | ||
| /* entering the main loop). */ | ||
|
|
||
| movl deflatestate(%esp), %edx | ||
| movl curmatch(%esp), %ecx | ||
|
|
||
| /* uInt wmask = s->w_mask; */ | ||
| /* unsigned chain_length = s->max_chain_length; */ | ||
| /* if (s->prev_length >= s->good_match) { */ | ||
| /* chain_length >>= 2; */ | ||
| /* } */ | ||
|
|
||
| movl dsPrevLen(%edx), %eax | ||
| movl dsGoodMatch(%edx), %ebx | ||
| cmpl %ebx, %eax | ||
| movl dsWMask(%edx), %eax | ||
| movl dsMaxChainLen(%edx), %ebx | ||
| jl LastMatchGood | ||
| shrl $2, %ebx | ||
| LastMatchGood: | ||
|
|
||
| /* chainlen is decremented once beforehand so that the function can */ | ||
| /* use the sign flag instead of the zero flag for the exit test. */ | ||
| /* It is then shifted into the high word, to make room for the wmask */ | ||
| /* value, which it will always accompany. */ | ||
|
|
||
| decl %ebx | ||
| shll $16, %ebx | ||
| orl %eax, %ebx | ||
| movl %ebx, chainlenwmask(%esp) | ||
|
|
||
| /* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */ | ||
|
|
||
| movl dsNiceMatch(%edx), %eax | ||
| movl dsLookahead(%edx), %ebx | ||
| cmpl %eax, %ebx | ||
| jl LookaheadLess | ||
| movl %eax, %ebx | ||
| LookaheadLess: movl %ebx, nicematch(%esp) | ||
|
|
||
| /* register Bytef *scan = s->window + s->strstart; */ | ||
|
|
||
| movl dsWindow(%edx), %esi | ||
| movl %esi, window(%esp) | ||
| movl dsStrStart(%edx), %ebp | ||
| lea (%esi,%ebp), %edi | ||
| movl %edi, scan(%esp) | ||
|
|
||
| /* Determine how many bytes the scan ptr is off from being */ | ||
| /* dword-aligned. */ | ||
|
|
||
| movl %edi, %eax | ||
| negl %eax | ||
| andl $3, %eax | ||
| movl %eax, scanalign(%esp) | ||
|
|
||
| /* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ | ||
| /* s->strstart - (IPos)MAX_DIST(s) : NIL; */ | ||
|
|
||
| movl dsWSize(%edx), %eax | ||
| subl $MIN_LOOKAHEAD, %eax | ||
| subl %eax, %ebp | ||
| jg LimitPositive | ||
| xorl %ebp, %ebp | ||
| LimitPositive: | ||
|
|
||
| /* int best_len = s->prev_length; */ | ||
|
|
||
| movl dsPrevLen(%edx), %eax | ||
| movl %eax, bestlen(%esp) | ||
|
|
||
| /* Store the sum of s->window + best_len in %esi locally, and in %esi. */ | ||
|
|
||
| addl %eax, %esi | ||
| movl %esi, windowbestlen(%esp) | ||
|
|
||
| /* register ush scan_start = *(ushf*)scan; */ | ||
| /* register ush scan_end = *(ushf*)(scan+best_len-1); */ | ||
| /* Posf *prev = s->prev; */ | ||
|
|
||
| movzwl (%edi), %ebx | ||
| movl %ebx, scanstart(%esp) | ||
| movzwl -1(%edi,%eax), %ebx | ||
| movl %ebx, scanend(%esp) | ||
| movl dsPrev(%edx), %edi | ||
|
|
||
| /* Jump into the main loop. */ | ||
|
|
||
| movl chainlenwmask(%esp), %edx | ||
| jmp LoopEntry | ||
|
|
||
| .balign 16 | ||
|
|
||
| /* do { | ||
| * match = s->window + cur_match; | ||
| * if (*(ushf*)(match+best_len-1) != scan_end || | ||
| * *(ushf*)match != scan_start) continue; | ||
| * [...] | ||
| * } while ((cur_match = prev[cur_match & wmask]) > limit | ||
| * && --chain_length != 0); | ||
| * | ||
| * Here is the inner loop of the function. The function will spend the | ||
| * majority of its time in this loop, and majority of that time will | ||
| * be spent in the first ten instructions. | ||
| * | ||
| * Within this loop: | ||
| * %ebx = scanend | ||
| * %ecx = curmatch | ||
| * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) | ||
| * %esi = windowbestlen - i.e., (window + bestlen) | ||
| * %edi = prev | ||
| * %ebp = limit | ||
| */ | ||
| LookupLoop: | ||
| andl %edx, %ecx | ||
| movzwl (%edi,%ecx,2), %ecx | ||
| cmpl %ebp, %ecx | ||
| jbe LeaveNow | ||
| subl $0x00010000, %edx | ||
| js LeaveNow | ||
| LoopEntry: movzwl -1(%esi,%ecx), %eax | ||
| cmpl %ebx, %eax | ||
| jnz LookupLoop | ||
| movl window(%esp), %eax | ||
| movzwl (%eax,%ecx), %eax | ||
| cmpl scanstart(%esp), %eax | ||
| jnz LookupLoop | ||
|
|
||
| /* Store the current value of chainlen. */ | ||
|
|
||
| movl %edx, chainlenwmask(%esp) | ||
|
|
||
| /* Point %edi to the string under scrutiny, and %esi to the string we */ | ||
| /* are hoping to match it up with. In actuality, %esi and %edi are */ | ||
| /* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */ | ||
| /* initialized to -(MAX_MATCH_8 - scanalign). */ | ||
|
|
||
| movl window(%esp), %esi | ||
| movl scan(%esp), %edi | ||
| addl %ecx, %esi | ||
| movl scanalign(%esp), %eax | ||
| movl $(-MAX_MATCH_8), %edx | ||
| lea MAX_MATCH_8(%edi,%eax), %edi | ||
| lea MAX_MATCH_8(%esi,%eax), %esi | ||
|
|
||
| /* Test the strings for equality, 8 bytes at a time. At the end, | ||
| * adjust %edx so that it is offset to the exact byte that mismatched. | ||
| * | ||
| * We already know at this point that the first three bytes of the | ||
| * strings match each other, and they can be safely passed over before | ||
| * starting the compare loop. So what this code does is skip over 0-3 | ||
| * bytes, as much as necessary in order to dword-align the %edi | ||
| * pointer. (%esi will still be misaligned three times out of four.) | ||
| * | ||
| * It should be confessed that this loop usually does not represent | ||
| * much of the total running time. Replacing it with a more | ||
| * straightforward "rep cmpsb" would not drastically degrade | ||
| * performance. | ||
| */ | ||
| LoopCmps: | ||
| movl (%esi,%edx), %eax | ||
| xorl (%edi,%edx), %eax | ||
| jnz LeaveLoopCmps | ||
| movl 4(%esi,%edx), %eax | ||
| xorl 4(%edi,%edx), %eax | ||
| jnz LeaveLoopCmps4 | ||
| addl $8, %edx | ||
| jnz LoopCmps | ||
| jmp LenMaximum | ||
| LeaveLoopCmps4: addl $4, %edx | ||
| LeaveLoopCmps: testl $0x0000FFFF, %eax | ||
| jnz LenLower | ||
| addl $2, %edx | ||
| shrl $16, %eax | ||
| LenLower: subb $1, %al | ||
| adcl $0, %edx | ||
|
|
||
| /* Calculate the length of the match. If it is longer than MAX_MATCH, */ | ||
| /* then automatically accept it as the best possible match and leave. */ | ||
|
|
||
| lea (%edi,%edx), %eax | ||
| movl scan(%esp), %edi | ||
| subl %edi, %eax | ||
| cmpl $MAX_MATCH, %eax | ||
| jge LenMaximum | ||
|
|
||
| /* If the length of the match is not longer than the best match we */ | ||
| /* have so far, then forget it and return to the lookup loop. */ | ||
|
|
||
| movl deflatestate(%esp), %edx | ||
| movl bestlen(%esp), %ebx | ||
| cmpl %ebx, %eax | ||
| jg LongerMatch | ||
| movl windowbestlen(%esp), %esi | ||
| movl dsPrev(%edx), %edi | ||
| movl scanend(%esp), %ebx | ||
| movl chainlenwmask(%esp), %edx | ||
| jmp LookupLoop | ||
|
|
||
| /* s->match_start = cur_match; */ | ||
| /* best_len = len; */ | ||
| /* if (len >= nice_match) break; */ | ||
| /* scan_end = *(ushf*)(scan+best_len-1); */ | ||
|
|
||
| LongerMatch: movl nicematch(%esp), %ebx | ||
| movl %eax, bestlen(%esp) | ||
| movl %ecx, dsMatchStart(%edx) | ||
| cmpl %ebx, %eax | ||
| jge LeaveNow | ||
| movl window(%esp), %esi | ||
| addl %eax, %esi | ||
| movl %esi, windowbestlen(%esp) | ||
| movzwl -1(%edi,%eax), %ebx | ||
| movl dsPrev(%edx), %edi | ||
| movl %ebx, scanend(%esp) | ||
| movl chainlenwmask(%esp), %edx | ||
| jmp LookupLoop | ||
|
|
||
| /* Accept the current string, with the maximum possible length. */ | ||
|
|
||
| LenMaximum: movl deflatestate(%esp), %edx | ||
| movl $MAX_MATCH, bestlen(%esp) | ||
| movl %ecx, dsMatchStart(%edx) | ||
|
|
||
| /* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ | ||
| /* return s->lookahead; */ | ||
|
|
||
| LeaveNow: | ||
| movl deflatestate(%esp), %edx | ||
| movl bestlen(%esp), %ebx | ||
| movl dsLookahead(%edx), %eax | ||
| cmpl %eax, %ebx | ||
| jg LookaheadRet | ||
| movl %ebx, %eax | ||
| LookaheadRet: | ||
|
|
||
| /* Restore the stack and return from whence we came. */ | ||
|
|
||
| addl $LocalVarsSize, %esp | ||
| .cfi_def_cfa_offset 20 | ||
| popl %ebx | ||
| .cfi_def_cfa_offset 16 | ||
| popl %esi | ||
| .cfi_def_cfa_offset 12 | ||
| popl %edi | ||
| .cfi_def_cfa_offset 8 | ||
| popl %ebp | ||
| .cfi_def_cfa_offset 4 | ||
| .cfi_endproc | ||
| match_init: ret |
| @@ -0,0 +1,8 @@ | ||
| blast: blast.c blast.h | ||
| cc -DTEST -o blast blast.c | ||
|
|
||
| test: blast | ||
| blast < test.pk | cmp - test.txt | ||
|
|
||
| clean: | ||
| rm -f blast blast.o |
| @@ -0,0 +1,4 @@ | ||
| Read blast.h for purpose and usage. | ||
|
|
||
| Mark Adler | ||
| madler@alumni.caltech.edu |
| @@ -0,0 +1,75 @@ | ||
| /* blast.h -- interface for blast.c | ||
| Copyright (C) 2003, 2012 Mark Adler | ||
| version 1.2, 24 Oct 2012 | ||
| This software is provided 'as-is', without any express or implied | ||
| warranty. In no event will the author be held liable for any damages | ||
| arising from the use of this software. | ||
| Permission is granted to anyone to use this software for any purpose, | ||
| including commercial applications, and to alter it and redistribute it | ||
| freely, subject to the following restrictions: | ||
| 1. The origin of this software must not be misrepresented; you must not | ||
| claim that you wrote the original software. If you use this software | ||
| in a product, an acknowledgment in the product documentation would be | ||
| appreciated but is not required. | ||
| 2. Altered source versions must be plainly marked as such, and must not be | ||
| misrepresented as being the original software. | ||
| 3. This notice may not be removed or altered from any source distribution. | ||
| Mark Adler madler@alumni.caltech.edu | ||
| */ | ||
|
|
||
|
|
||
| /* | ||
| * blast() decompresses the PKWare Data Compression Library (DCL) compressed | ||
| * format. It provides the same functionality as the explode() function in | ||
| * that library. (Note: PKWare overused the "implode" verb, and the format | ||
| * used by their library implode() function is completely different and | ||
| * incompatible with the implode compression method supported by PKZIP.) | ||
| * | ||
| * The binary mode for stdio functions should be used to assure that the | ||
| * compressed data is not corrupted when read or written. For example: | ||
| * fopen(..., "rb") and fopen(..., "wb"). | ||
| */ | ||
|
|
||
|
|
||
| typedef unsigned (*blast_in)(void *how, unsigned char **buf); | ||
| typedef int (*blast_out)(void *how, unsigned char *buf, unsigned len); | ||
| /* Definitions for input/output functions passed to blast(). See below for | ||
| * what the provided functions need to do. | ||
| */ | ||
|
|
||
|
|
||
| int blast(blast_in infun, void *inhow, blast_out outfun, void *outhow); | ||
| /* Decompress input to output using the provided infun() and outfun() calls. | ||
| * On success, the return value of blast() is zero. If there is an error in | ||
| * the source data, i.e. it is not in the proper format, then a negative value | ||
| * is returned. If there is not enough input available or there is not enough | ||
| * output space, then a positive error is returned. | ||
| * | ||
| * The input function is invoked: len = infun(how, &buf), where buf is set by | ||
| * infun() to point to the input buffer, and infun() returns the number of | ||
| * available bytes there. If infun() returns zero, then blast() returns with | ||
| * an input error. (blast() only asks for input if it needs it.) inhow is for | ||
| * use by the application to pass an input descriptor to infun(), if desired. | ||
| * | ||
| * The output function is invoked: err = outfun(how, buf, len), where the bytes | ||
| * to be written are buf[0..len-1]. If err is not zero, then blast() returns | ||
| * with an output error. outfun() is always called with len <= 4096. outhow | ||
| * is for use by the application to pass an output descriptor to outfun(), if | ||
| * desired. | ||
| * | ||
| * The return codes are: | ||
| * | ||
| * 2: ran out of input before completing decompression | ||
| * 1: output error before completing decompression | ||
| * 0: successful decompression | ||
| * -1: literal flag not zero or one | ||
| * -2: dictionary size not in 4..6 | ||
| * -3: distance is too far back | ||
| * | ||
| * At the bottom of blast.c is an example program that uses blast() that can be | ||
| * compiled to produce a command-line decompression filter by defining TEST. | ||
| */ |
| @@ -0,0 +1 @@ | ||
| AIAIAIAIAIAIA |
| @@ -0,0 +1,11 @@ | ||
| unit ZLibConst; | ||
|
|
||
| interface | ||
|
|
||
| resourcestring | ||
| sTargetBufferTooSmall = 'ZLib error: target buffer may be too small'; | ||
| sInvalidStreamOp = 'Invalid stream operation'; | ||
|
|
||
| implementation | ||
|
|
||
| end. |
| @@ -0,0 +1,76 @@ | ||
|
|
||
| Overview | ||
| ======== | ||
|
|
||
| This directory contains an update to the ZLib interface unit, | ||
| distributed by Borland as a Delphi supplemental component. | ||
|
|
||
| The original ZLib unit is Copyright (c) 1997,99 Borland Corp., | ||
| and is based on zlib version 1.0.4. There are a series of bugs | ||
| and security problems associated with that old zlib version, and | ||
| we recommend the users to update their ZLib unit. | ||
|
|
||
|
|
||
| Summary of modifications | ||
| ======================== | ||
|
|
||
| - Improved makefile, adapted to zlib version 1.2.1. | ||
|
|
||
| - Some field types from TZStreamRec are changed from Integer to | ||
| Longint, for consistency with the zlib.h header, and for 64-bit | ||
| readiness. | ||
|
|
||
| - The zlib_version constant is updated. | ||
|
|
||
| - The new Z_RLE strategy has its corresponding symbolic constant. | ||
|
|
||
| - The allocation and deallocation functions and function types | ||
| (TAlloc, TFree, zlibAllocMem and zlibFreeMem) are now cdecl, | ||
| and _malloc and _free are added as C RTL stubs. As a result, | ||
| the original C sources of zlib can be compiled out of the box, | ||
| and linked to the ZLib unit. | ||
|
|
||
|
|
||
| Suggestions for improvements | ||
| ============================ | ||
|
|
||
| Currently, the ZLib unit provides only a limited wrapper around | ||
| the zlib library, and much of the original zlib functionality is | ||
| missing. Handling compressed file formats like ZIP/GZIP or PNG | ||
| cannot be implemented without having this functionality. | ||
| Applications that handle these formats are either using their own, | ||
| duplicated code, or not using the ZLib unit at all. | ||
|
|
||
| Here are a few suggestions: | ||
|
|
||
| - Checksum class wrappers around adler32() and crc32(), similar | ||
| to the Java classes that implement the java.util.zip.Checksum | ||
| interface. | ||
|
|
||
| - The ability to read and write raw deflate streams, without the | ||
| zlib stream header and trailer. Raw deflate streams are used | ||
| in the ZIP file format. | ||
|
|
||
| - The ability to read and write gzip streams, used in the GZIP | ||
| file format, and normally produced by the gzip program. | ||
|
|
||
| - The ability to select a different compression strategy, useful | ||
| to PNG and MNG image compression, and to multimedia compression | ||
| in general. Besides the compression level | ||
|
|
||
| TCompressionLevel = (clNone, clFastest, clDefault, clMax); | ||
|
|
||
| which, in fact, could have used the 'z' prefix and avoided | ||
| TColor-like symbols | ||
|
|
||
| TCompressionLevel = (zcNone, zcFastest, zcDefault, zcMax); | ||
|
|
||
| there could be a compression strategy | ||
|
|
||
| TCompressionStrategy = (zsDefault, zsFiltered, zsHuffmanOnly, zsRle); | ||
|
|
||
| - ZIP and GZIP stream handling via TStreams. | ||
|
|
||
|
|
||
| -- | ||
| Cosmin Truta <cosmint@cs.ubbcluj.ro> |
| @@ -0,0 +1,99 @@ | ||
| # Makefile for zlib | ||
| # For use with Delphi and C++ Builder under Win32 | ||
| # Updated for zlib 1.2.x by Cosmin Truta | ||
|
|
||
| # ------------ Borland C++ ------------ | ||
|
|
||
| # This project uses the Delphi (fastcall/register) calling convention: | ||
| LOC = -DZEXPORT=__fastcall -DZEXPORTVA=__cdecl | ||
|
|
||
| CC = bcc32 | ||
| LD = bcc32 | ||
| AR = tlib | ||
| # do not use "-pr" in CFLAGS | ||
| CFLAGS = -a -d -k- -O2 $(LOC) | ||
| LDFLAGS = | ||
|
|
||
|
|
||
| # variables | ||
| ZLIB_LIB = zlib.lib | ||
|
|
||
| OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj | ||
| OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj | ||
| OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj | ||
| OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj | ||
|
|
||
|
|
||
| # targets | ||
| all: $(ZLIB_LIB) example.exe minigzip.exe | ||
|
|
||
| .c.obj: | ||
| $(CC) -c $(CFLAGS) $*.c | ||
|
|
||
| adler32.obj: adler32.c zlib.h zconf.h | ||
|
|
||
| compress.obj: compress.c zlib.h zconf.h | ||
|
|
||
| crc32.obj: crc32.c zlib.h zconf.h crc32.h | ||
|
|
||
| deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h | ||
|
|
||
| gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h | ||
|
|
||
| gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h | ||
|
|
||
| gzread.obj: gzread.c zlib.h zconf.h gzguts.h | ||
|
|
||
| gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h | ||
|
|
||
| infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ | ||
| inffast.h inffixed.h | ||
|
|
||
| inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ | ||
| inffast.h | ||
|
|
||
| inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ | ||
| inffast.h inffixed.h | ||
|
|
||
| inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h | ||
|
|
||
| trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h | ||
|
|
||
| uncompr.obj: uncompr.c zlib.h zconf.h | ||
|
|
||
| zutil.obj: zutil.c zutil.h zlib.h zconf.h | ||
|
|
||
| example.obj: test/example.c zlib.h zconf.h | ||
|
|
||
| minigzip.obj: test/minigzip.c zlib.h zconf.h | ||
|
|
||
|
|
||
| # For the sake of the old Borland make, | ||
| # the command line is cut to fit in the MS-DOS 128 byte limit: | ||
| $(ZLIB_LIB): $(OBJ1) $(OBJ2) | ||
| -del $(ZLIB_LIB) | ||
| $(AR) $(ZLIB_LIB) $(OBJP1) | ||
| $(AR) $(ZLIB_LIB) $(OBJP2) | ||
|
|
||
|
|
||
| # testing | ||
| test: example.exe minigzip.exe | ||
| example | ||
| echo hello world | minigzip | minigzip -d | ||
|
|
||
| example.exe: example.obj $(ZLIB_LIB) | ||
| $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB) | ||
|
|
||
| minigzip.exe: minigzip.obj $(ZLIB_LIB) | ||
| $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB) | ||
|
|
||
|
|
||
| # cleanup | ||
| clean: | ||
| -del *.obj | ||
| -del *.exe | ||
| -del *.lib | ||
| -del *.tds | ||
| -del zlib.bak | ||
| -del foo.gz | ||
|
|
| @@ -0,0 +1,33 @@ | ||
| <?xml version="1.0" encoding="utf-8" ?> | ||
| <project name="DotZLib" default="build" basedir="./DotZLib"> | ||
| <description>A .Net wrapper library around ZLib1.dll</description> | ||
|
|
||
| <property name="nunit.location" value="c:/program files/NUnit V2.1/bin" /> | ||
| <property name="build.root" value="bin" /> | ||
|
|
||
| <property name="debug" value="true" /> | ||
| <property name="nunit" value="true" /> | ||
|
|
||
| <property name="build.folder" value="${build.root}/debug/" if="${debug}" /> | ||
| <property name="build.folder" value="${build.root}/release/" unless="${debug}" /> | ||
|
|
||
| <target name="clean" description="Remove all generated files"> | ||
| <delete dir="${build.root}" failonerror="false" /> | ||
| </target> | ||
|
|
||
| <target name="build" description="compiles the source code"> | ||
|
|
||
| <mkdir dir="${build.folder}" /> | ||
| <csc target="library" output="${build.folder}DotZLib.dll" debug="${debug}"> | ||
| <references basedir="${nunit.location}"> | ||
| <includes if="${nunit}" name="nunit.framework.dll" /> | ||
| </references> | ||
| <sources> | ||
| <includes name="*.cs" /> | ||
| <excludes name="UnitTests.cs" unless="${nunit}" /> | ||
| </sources> | ||
| <arg value="/d:nunit" if="${nunit}" /> | ||
| </csc> | ||
| </target> | ||
|
|
||
| </project> |
| @@ -0,0 +1,58 @@ | ||
| using System.Reflection; | ||
| using System.Runtime.CompilerServices; | ||
|
|
||
| // | ||
| // General Information about an assembly is controlled through the following | ||
| // set of attributes. Change these attribute values to modify the information | ||
| // associated with an assembly. | ||
| // | ||
| [assembly: AssemblyTitle("DotZLib")] | ||
| [assembly: AssemblyDescription(".Net bindings for ZLib compression dll 1.2.x")] | ||
| [assembly: AssemblyConfiguration("")] | ||
| [assembly: AssemblyCompany("Henrik Ravn")] | ||
| [assembly: AssemblyProduct("")] | ||
| [assembly: AssemblyCopyright("(c) 2004 by Henrik Ravn")] | ||
| [assembly: AssemblyTrademark("")] | ||
| [assembly: AssemblyCulture("")] | ||
|
|
||
| // | ||
| // Version information for an assembly consists of the following four values: | ||
| // | ||
| // Major Version | ||
| // Minor Version | ||
| // Build Number | ||
| // Revision | ||
| // | ||
| // You can specify all the values or you can default the Revision and Build Numbers | ||
| // by using the '*' as shown below: | ||
|
|
||
| [assembly: AssemblyVersion("1.0.*")] | ||
|
|
||
| // | ||
| // In order to sign your assembly you must specify a key to use. Refer to the | ||
| // Microsoft .NET Framework documentation for more information on assembly signing. | ||
| // | ||
| // Use the attributes below to control which key is used for signing. | ||
| // | ||
| // Notes: | ||
| // (*) If no key is specified, the assembly is not signed. | ||
| // (*) KeyName refers to a key that has been installed in the Crypto Service | ||
| // Provider (CSP) on your machine. KeyFile refers to a file which contains | ||
| // a key. | ||
| // (*) If the KeyFile and the KeyName values are both specified, the | ||
| // following processing occurs: | ||
| // (1) If the KeyName can be found in the CSP, that key is used. | ||
| // (2) If the KeyName does not exist and the KeyFile does exist, the key | ||
| // in the KeyFile is installed into the CSP and used. | ||
| // (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. | ||
| // When specifying the KeyFile, the location of the KeyFile should be | ||
| // relative to the project output directory which is | ||
| // %Project Directory%\obj\<configuration>. For example, if your KeyFile is | ||
| // located in the project directory, you would specify the AssemblyKeyFile | ||
| // attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] | ||
| // (*) Delay Signing is an advanced option - see the Microsoft .NET Framework | ||
| // documentation for more information on this. | ||
| // | ||
| [assembly: AssemblyDelaySign(false)] | ||
| [assembly: AssemblyKeyFile("")] | ||
| [assembly: AssemblyKeyName("")] |
| @@ -0,0 +1,202 @@ | ||
| // | ||
| // © Copyright Henrik Ravn 2004 | ||
| // | ||
| // Use, modification and distribution are subject to the Boost Software License, Version 1.0. | ||
| // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
| // | ||
|
|
||
| using System; | ||
| using System.Runtime.InteropServices; | ||
| using System.Text; | ||
|
|
||
|
|
||
| namespace DotZLib | ||
| { | ||
| #region ChecksumGeneratorBase | ||
| /// <summary> | ||
| /// Implements the common functionality needed for all <see cref="ChecksumGenerator"/>s | ||
| /// </summary> | ||
| /// <example></example> | ||
| public abstract class ChecksumGeneratorBase : ChecksumGenerator | ||
| { | ||
| /// <summary> | ||
| /// The value of the current checksum | ||
| /// </summary> | ||
| protected uint _current; | ||
|
|
||
| /// <summary> | ||
| /// Initializes a new instance of the checksum generator base - the current checksum is | ||
| /// set to zero | ||
| /// </summary> | ||
| public ChecksumGeneratorBase() | ||
| { | ||
| _current = 0; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Initializes a new instance of the checksum generator basewith a specified value | ||
| /// </summary> | ||
| /// <param name="initialValue">The value to set the current checksum to</param> | ||
| public ChecksumGeneratorBase(uint initialValue) | ||
| { | ||
| _current = initialValue; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Resets the current checksum to zero | ||
| /// </summary> | ||
| public void Reset() { _current = 0; } | ||
|
|
||
| /// <summary> | ||
| /// Gets the current checksum value | ||
| /// </summary> | ||
| public uint Value { get { return _current; } } | ||
|
|
||
| /// <summary> | ||
| /// Updates the current checksum with part of an array of bytes | ||
| /// </summary> | ||
| /// <param name="data">The data to update the checksum with</param> | ||
| /// <param name="offset">Where in <c>data</c> to start updating</param> | ||
| /// <param name="count">The number of bytes from <c>data</c> to use</param> | ||
| /// <exception cref="ArgumentException">The sum of offset and count is larger than the length of <c>data</c></exception> | ||
| /// <exception cref="NullReferenceException"><c>data</c> is a null reference</exception> | ||
| /// <exception cref="ArgumentOutOfRangeException">Offset or count is negative.</exception> | ||
| /// <remarks>All the other <c>Update</c> methods are implmeneted in terms of this one. | ||
| /// This is therefore the only method a derived class has to implement</remarks> | ||
| public abstract void Update(byte[] data, int offset, int count); | ||
|
|
||
| /// <summary> | ||
| /// Updates the current checksum with an array of bytes. | ||
| /// </summary> | ||
| /// <param name="data">The data to update the checksum with</param> | ||
| public void Update(byte[] data) | ||
| { | ||
| Update(data, 0, data.Length); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Updates the current checksum with the data from a string | ||
| /// </summary> | ||
| /// <param name="data">The string to update the checksum with</param> | ||
| /// <remarks>The characters in the string are converted by the UTF-8 encoding</remarks> | ||
| public void Update(string data) | ||
| { | ||
| Update(Encoding.UTF8.GetBytes(data)); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Updates the current checksum with the data from a string, using a specific encoding | ||
| /// </summary> | ||
| /// <param name="data">The string to update the checksum with</param> | ||
| /// <param name="encoding">The encoding to use</param> | ||
| public void Update(string data, Encoding encoding) | ||
| { | ||
| Update(encoding.GetBytes(data)); | ||
| } | ||
|
|
||
| } | ||
| #endregion | ||
|
|
||
| #region CRC32 | ||
| /// <summary> | ||
| /// Implements a CRC32 checksum generator | ||
| /// </summary> | ||
| public sealed class CRC32Checksum : ChecksumGeneratorBase | ||
| { | ||
| #region DLL imports | ||
|
|
||
| [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] | ||
| private static extern uint crc32(uint crc, int data, uint length); | ||
|
|
||
| #endregion | ||
|
|
||
| /// <summary> | ||
| /// Initializes a new instance of the CRC32 checksum generator | ||
| /// </summary> | ||
| public CRC32Checksum() : base() {} | ||
|
|
||
| /// <summary> | ||
| /// Initializes a new instance of the CRC32 checksum generator with a specified value | ||
| /// </summary> | ||
| /// <param name="initialValue">The value to set the current checksum to</param> | ||
| public CRC32Checksum(uint initialValue) : base(initialValue) {} | ||
|
|
||
| /// <summary> | ||
| /// Updates the current checksum with part of an array of bytes | ||
| /// </summary> | ||
| /// <param name="data">The data to update the checksum with</param> | ||
| /// <param name="offset">Where in <c>data</c> to start updating</param> | ||
| /// <param name="count">The number of bytes from <c>data</c> to use</param> | ||
| /// <exception cref="ArgumentException">The sum of offset and count is larger than the length of <c>data</c></exception> | ||
| /// <exception cref="NullReferenceException"><c>data</c> is a null reference</exception> | ||
| /// <exception cref="ArgumentOutOfRangeException">Offset or count is negative.</exception> | ||
| public override void Update(byte[] data, int offset, int count) | ||
| { | ||
| if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); | ||
| if ((offset+count) > data.Length) throw new ArgumentException(); | ||
| GCHandle hData = GCHandle.Alloc(data, GCHandleType.Pinned); | ||
| try | ||
| { | ||
| _current = crc32(_current, hData.AddrOfPinnedObject().ToInt32()+offset, (uint)count); | ||
| } | ||
| finally | ||
| { | ||
| hData.Free(); | ||
| } | ||
| } | ||
|
|
||
| } | ||
| #endregion | ||
|
|
||
| #region Adler | ||
| /// <summary> | ||
| /// Implements a checksum generator that computes the Adler checksum on data | ||
| /// </summary> | ||
| public sealed class AdlerChecksum : ChecksumGeneratorBase | ||
| { | ||
| #region DLL imports | ||
|
|
||
| [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] | ||
| private static extern uint adler32(uint adler, int data, uint length); | ||
|
|
||
| #endregion | ||
|
|
||
| /// <summary> | ||
| /// Initializes a new instance of the Adler checksum generator | ||
| /// </summary> | ||
| public AdlerChecksum() : base() {} | ||
|
|
||
| /// <summary> | ||
| /// Initializes a new instance of the Adler checksum generator with a specified value | ||
| /// </summary> | ||
| /// <param name="initialValue">The value to set the current checksum to</param> | ||
| public AdlerChecksum(uint initialValue) : base(initialValue) {} | ||
|
|
||
| /// <summary> | ||
| /// Updates the current checksum with part of an array of bytes | ||
| /// </summary> | ||
| /// <param name="data">The data to update the checksum with</param> | ||
| /// <param name="offset">Where in <c>data</c> to start updating</param> | ||
| /// <param name="count">The number of bytes from <c>data</c> to use</param> | ||
| /// <exception cref="ArgumentException">The sum of offset and count is larger than the length of <c>data</c></exception> | ||
| /// <exception cref="NullReferenceException"><c>data</c> is a null reference</exception> | ||
| /// <exception cref="ArgumentOutOfRangeException">Offset or count is negative.</exception> | ||
| public override void Update(byte[] data, int offset, int count) | ||
| { | ||
| if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); | ||
| if ((offset+count) > data.Length) throw new ArgumentException(); | ||
| GCHandle hData = GCHandle.Alloc(data, GCHandleType.Pinned); | ||
| try | ||
| { | ||
| _current = adler32(_current, hData.AddrOfPinnedObject().ToInt32()+offset, (uint)count); | ||
| } | ||
| finally | ||
| { | ||
| hData.Free(); | ||
| } | ||
| } | ||
|
|
||
| } | ||
| #endregion | ||
|
|
||
| } |
| @@ -0,0 +1,83 @@ | ||
| // | ||
| // © Copyright Henrik Ravn 2004 | ||
| // | ||
| // Use, modification and distribution are subject to the Boost Software License, Version 1.0. | ||
| // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
| // | ||
|
|
||
| using System; | ||
| using System.Diagnostics; | ||
|
|
||
| namespace DotZLib | ||
| { | ||
|
|
||
| /// <summary> | ||
| /// This class implements a circular buffer | ||
| /// </summary> | ||
| internal class CircularBuffer | ||
| { | ||
| #region Private data | ||
| private int _capacity; | ||
| private int _head; | ||
| private int _tail; | ||
| private int _size; | ||
| private byte[] _buffer; | ||
| #endregion | ||
|
|
||
| public CircularBuffer(int capacity) | ||
| { | ||
| Debug.Assert( capacity > 0 ); | ||
| _buffer = new byte[capacity]; | ||
| _capacity = capacity; | ||
| _head = 0; | ||
| _tail = 0; | ||
| _size = 0; | ||
| } | ||
|
|
||
| public int Size { get { return _size; } } | ||
|
|
||
| public int Put(byte[] source, int offset, int count) | ||
| { | ||
| Debug.Assert( count > 0 ); | ||
| int trueCount = Math.Min(count, _capacity - Size); | ||
| for (int i = 0; i < trueCount; ++i) | ||
| _buffer[(_tail+i) % _capacity] = source[offset+i]; | ||
| _tail += trueCount; | ||
| _tail %= _capacity; | ||
| _size += trueCount; | ||
| return trueCount; | ||
| } | ||
|
|
||
| public bool Put(byte b) | ||
| { | ||
| if (Size == _capacity) // no room | ||
| return false; | ||
| _buffer[_tail++] = b; | ||
| _tail %= _capacity; | ||
| ++_size; | ||
| return true; | ||
| } | ||
|
|
||
| public int Get(byte[] destination, int offset, int count) | ||
| { | ||
| int trueCount = Math.Min(count,Size); | ||
| for (int i = 0; i < trueCount; ++i) | ||
| destination[offset + i] = _buffer[(_head+i) % _capacity]; | ||
| _head += trueCount; | ||
| _head %= _capacity; | ||
| _size -= trueCount; | ||
| return trueCount; | ||
| } | ||
|
|
||
| public int Get() | ||
| { | ||
| if (Size == 0) | ||
| return -1; | ||
|
|
||
| int result = (int)_buffer[_head++ % _capacity]; | ||
| --_size; | ||
| return result; | ||
| } | ||
|
|
||
| } | ||
| } |
| @@ -0,0 +1,198 @@ | ||
| // | ||
| // © Copyright Henrik Ravn 2004 | ||
| // | ||
| // Use, modification and distribution are subject to the Boost Software License, Version 1.0. | ||
| // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
| // | ||
|
|
||
| using System; | ||
| using System.Runtime.InteropServices; | ||
|
|
||
| namespace DotZLib | ||
| { | ||
| /// <summary> | ||
| /// Implements the common functionality needed for all <see cref="Codec"/>s | ||
| /// </summary> | ||
| public abstract class CodecBase : Codec, IDisposable | ||
| { | ||
|
|
||
| #region Data members | ||
|
|
||
| /// <summary> | ||
| /// Instance of the internal zlib buffer structure that is | ||
| /// passed to all functions in the zlib dll | ||
| /// </summary> | ||
| internal ZStream _ztream = new ZStream(); | ||
|
|
||
| /// <summary> | ||
| /// True if the object instance has been disposed, false otherwise | ||
| /// </summary> | ||
| protected bool _isDisposed = false; | ||
|
|
||
| /// <summary> | ||
| /// The size of the internal buffers | ||
| /// </summary> | ||
| protected const int kBufferSize = 16384; | ||
|
|
||
| private byte[] _outBuffer = new byte[kBufferSize]; | ||
| private byte[] _inBuffer = new byte[kBufferSize]; | ||
|
|
||
| private GCHandle _hInput; | ||
| private GCHandle _hOutput; | ||
|
|
||
| private uint _checksum = 0; | ||
|
|
||
| #endregion | ||
|
|
||
| /// <summary> | ||
| /// Initializes a new instance of the <c>CodeBase</c> class. | ||
| /// </summary> | ||
| public CodecBase() | ||
| { | ||
| try | ||
| { | ||
| _hInput = GCHandle.Alloc(_inBuffer, GCHandleType.Pinned); | ||
| _hOutput = GCHandle.Alloc(_outBuffer, GCHandleType.Pinned); | ||
| } | ||
| catch (Exception) | ||
| { | ||
| CleanUp(false); | ||
| throw; | ||
| } | ||
| } | ||
|
|
||
|
|
||
| #region Codec Members | ||
|
|
||
| /// <summary> | ||
| /// Occurs when more processed data are available. | ||
| /// </summary> | ||
| public event DataAvailableHandler DataAvailable; | ||
|
|
||
| /// <summary> | ||
| /// Fires the <see cref="DataAvailable"/> event | ||
| /// </summary> | ||
| protected void OnDataAvailable() | ||
| { | ||
| if (_ztream.total_out > 0) | ||
| { | ||
| if (DataAvailable != null) | ||
| DataAvailable( _outBuffer, 0, (int)_ztream.total_out); | ||
| resetOutput(); | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Adds more data to the codec to be processed. | ||
| /// </summary> | ||
| /// <param name="data">Byte array containing the data to be added to the codec</param> | ||
| /// <remarks>Adding data may, or may not, raise the <c>DataAvailable</c> event</remarks> | ||
| public void Add(byte[] data) | ||
| { | ||
| Add(data,0,data.Length); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Adds more data to the codec to be processed. | ||
| /// </summary> | ||
| /// <param name="data">Byte array containing the data to be added to the codec</param> | ||
| /// <param name="offset">The index of the first byte to add from <c>data</c></param> | ||
| /// <param name="count">The number of bytes to add</param> | ||
| /// <remarks>Adding data may, or may not, raise the <c>DataAvailable</c> event</remarks> | ||
| /// <remarks>This must be implemented by a derived class</remarks> | ||
| public abstract void Add(byte[] data, int offset, int count); | ||
|
|
||
| /// <summary> | ||
| /// Finishes up any pending data that needs to be processed and handled. | ||
| /// </summary> | ||
| /// <remarks>This must be implemented by a derived class</remarks> | ||
| public abstract void Finish(); | ||
|
|
||
| /// <summary> | ||
| /// Gets the checksum of the data that has been added so far | ||
| /// </summary> | ||
| public uint Checksum { get { return _checksum; } } | ||
|
|
||
| #endregion | ||
|
|
||
| #region Destructor & IDisposable stuff | ||
|
|
||
| /// <summary> | ||
| /// Destroys this instance | ||
| /// </summary> | ||
| ~CodecBase() | ||
| { | ||
| CleanUp(false); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Releases any unmanaged resources and calls the <see cref="CleanUp()"/> method of the derived class | ||
| /// </summary> | ||
| public void Dispose() | ||
| { | ||
| CleanUp(true); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Performs any codec specific cleanup | ||
| /// </summary> | ||
| /// <remarks>This must be implemented by a derived class</remarks> | ||
| protected abstract void CleanUp(); | ||
|
|
||
| // performs the release of the handles and calls the dereived CleanUp() | ||
| private void CleanUp(bool isDisposing) | ||
| { | ||
| if (!_isDisposed) | ||
| { | ||
| CleanUp(); | ||
| if (_hInput.IsAllocated) | ||
| _hInput.Free(); | ||
| if (_hOutput.IsAllocated) | ||
| _hOutput.Free(); | ||
|
|
||
| _isDisposed = true; | ||
| } | ||
| } | ||
|
|
||
|
|
||
| #endregion | ||
|
|
||
| #region Helper methods | ||
|
|
||
| /// <summary> | ||
| /// Copies a number of bytes to the internal codec buffer - ready for proccesing | ||
| /// </summary> | ||
| /// <param name="data">The byte array that contains the data to copy</param> | ||
| /// <param name="startIndex">The index of the first byte to copy</param> | ||
| /// <param name="count">The number of bytes to copy from <c>data</c></param> | ||
| protected void copyInput(byte[] data, int startIndex, int count) | ||
| { | ||
| Array.Copy(data, startIndex, _inBuffer,0, count); | ||
| _ztream.next_in = _hInput.AddrOfPinnedObject(); | ||
| _ztream.total_in = 0; | ||
| _ztream.avail_in = (uint)count; | ||
|
|
||
| } | ||
|
|
||
| /// <summary> | ||
| /// Resets the internal output buffers to a known state - ready for processing | ||
| /// </summary> | ||
| protected void resetOutput() | ||
| { | ||
| _ztream.total_out = 0; | ||
| _ztream.avail_out = kBufferSize; | ||
| _ztream.next_out = _hOutput.AddrOfPinnedObject(); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Updates the running checksum property | ||
| /// </summary> | ||
| /// <param name="newSum">The new checksum value</param> | ||
| protected void setChecksum(uint newSum) | ||
| { | ||
| _checksum = newSum; | ||
| } | ||
| #endregion | ||
|
|
||
| } | ||
| } |
| @@ -0,0 +1,106 @@ | ||
| // | ||
| // © Copyright Henrik Ravn 2004 | ||
| // | ||
| // Use, modification and distribution are subject to the Boost Software License, Version 1.0. | ||
| // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
| // | ||
|
|
||
| using System; | ||
| using System.Diagnostics; | ||
| using System.Runtime.InteropServices; | ||
|
|
||
| namespace DotZLib | ||
| { | ||
|
|
||
| /// <summary> | ||
| /// Implements a data compressor, using the deflate algorithm in the ZLib dll | ||
| /// </summary> | ||
| public sealed class Deflater : CodecBase | ||
| { | ||
| #region Dll imports | ||
| [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)] | ||
| private static extern int deflateInit_(ref ZStream sz, int level, string vs, int size); | ||
|
|
||
| [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] | ||
| private static extern int deflate(ref ZStream sz, int flush); | ||
|
|
||
| [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] | ||
| private static extern int deflateReset(ref ZStream sz); | ||
|
|
||
| [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] | ||
| private static extern int deflateEnd(ref ZStream sz); | ||
| #endregion | ||
|
|
||
| /// <summary> | ||
| /// Constructs an new instance of the <c>Deflater</c> | ||
| /// </summary> | ||
| /// <param name="level">The compression level to use for this <c>Deflater</c></param> | ||
| public Deflater(CompressLevel level) : base() | ||
| { | ||
| int retval = deflateInit_(ref _ztream, (int)level, Info.Version, Marshal.SizeOf(_ztream)); | ||
| if (retval != 0) | ||
| throw new ZLibException(retval, "Could not initialize deflater"); | ||
|
|
||
| resetOutput(); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Adds more data to the codec to be processed. | ||
| /// </summary> | ||
| /// <param name="data">Byte array containing the data to be added to the codec</param> | ||
| /// <param name="offset">The index of the first byte to add from <c>data</c></param> | ||
| /// <param name="count">The number of bytes to add</param> | ||
| /// <remarks>Adding data may, or may not, raise the <c>DataAvailable</c> event</remarks> | ||
| public override void Add(byte[] data, int offset, int count) | ||
| { | ||
| if (data == null) throw new ArgumentNullException(); | ||
| if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); | ||
| if ((offset+count) > data.Length) throw new ArgumentException(); | ||
|
|
||
| int total = count; | ||
| int inputIndex = offset; | ||
| int err = 0; | ||
|
|
||
| while (err >= 0 && inputIndex < total) | ||
| { | ||
| copyInput(data, inputIndex, Math.Min(total - inputIndex, kBufferSize)); | ||
| while (err >= 0 && _ztream.avail_in > 0) | ||
| { | ||
| err = deflate(ref _ztream, (int)FlushTypes.None); | ||
| if (err == 0) | ||
| while (_ztream.avail_out == 0) | ||
| { | ||
| OnDataAvailable(); | ||
| err = deflate(ref _ztream, (int)FlushTypes.None); | ||
| } | ||
| inputIndex += (int)_ztream.total_in; | ||
| } | ||
| } | ||
| setChecksum( _ztream.adler ); | ||
| } | ||
|
|
||
|
|
||
| /// <summary> | ||
| /// Finishes up any pending data that needs to be processed and handled. | ||
| /// </summary> | ||
| public override void Finish() | ||
| { | ||
| int err; | ||
| do | ||
| { | ||
| err = deflate(ref _ztream, (int)FlushTypes.Finish); | ||
| OnDataAvailable(); | ||
| } | ||
| while (err == 0); | ||
| setChecksum( _ztream.adler ); | ||
| deflateReset(ref _ztream); | ||
| resetOutput(); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Closes the internal zlib deflate stream | ||
| /// </summary> | ||
| protected override void CleanUp() { deflateEnd(ref _ztream); } | ||
|
|
||
| } | ||
| } |
| @@ -0,0 +1,288 @@ | ||
| // | ||
| // © Copyright Henrik Ravn 2004 | ||
| // | ||
| // Use, modification and distribution are subject to the Boost Software License, Version 1.0. | ||
| // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
| // | ||
|
|
||
| using System; | ||
| using System.IO; | ||
| using System.Runtime.InteropServices; | ||
| using System.Text; | ||
|
|
||
|
|
||
| namespace DotZLib | ||
| { | ||
|
|
||
| #region Internal types | ||
|
|
||
| /// <summary> | ||
| /// Defines constants for the various flush types used with zlib | ||
| /// </summary> | ||
| internal enum FlushTypes | ||
| { | ||
| None, Partial, Sync, Full, Finish, Block | ||
| } | ||
|
|
||
| #region ZStream structure | ||
| // internal mapping of the zlib zstream structure for marshalling | ||
| [StructLayoutAttribute(LayoutKind.Sequential, Pack=4, Size=0, CharSet=CharSet.Ansi)] | ||
| internal struct ZStream | ||
| { | ||
| public IntPtr next_in; | ||
| public uint avail_in; | ||
| public uint total_in; | ||
|
|
||
| public IntPtr next_out; | ||
| public uint avail_out; | ||
| public uint total_out; | ||
|
|
||
| [MarshalAs(UnmanagedType.LPStr)] | ||
| string msg; | ||
| uint state; | ||
|
|
||
| uint zalloc; | ||
| uint zfree; | ||
| uint opaque; | ||
|
|
||
| int data_type; | ||
| public uint adler; | ||
| uint reserved; | ||
| } | ||
|
|
||
| #endregion | ||
|
|
||
| #endregion | ||
|
|
||
| #region Public enums | ||
| /// <summary> | ||
| /// Defines constants for the available compression levels in zlib | ||
| /// </summary> | ||
| public enum CompressLevel : int | ||
| { | ||
| /// <summary> | ||
| /// The default compression level with a reasonable compromise between compression and speed | ||
| /// </summary> | ||
| Default = -1, | ||
| /// <summary> | ||
| /// No compression at all. The data are passed straight through. | ||
| /// </summary> | ||
| None = 0, | ||
| /// <summary> | ||
| /// The maximum compression rate available. | ||
| /// </summary> | ||
| Best = 9, | ||
| /// <summary> | ||
| /// The fastest available compression level. | ||
| /// </summary> | ||
| Fastest = 1 | ||
| } | ||
| #endregion | ||
|
|
||
| #region Exception classes | ||
| /// <summary> | ||
| /// The exception that is thrown when an error occurs on the zlib dll | ||
| /// </summary> | ||
| public class ZLibException : ApplicationException | ||
| { | ||
| /// <summary> | ||
| /// Initializes a new instance of the <see cref="ZLibException"/> class with a specified | ||
| /// error message and error code | ||
| /// </summary> | ||
| /// <param name="errorCode">The zlib error code that caused the exception</param> | ||
| /// <param name="msg">A message that (hopefully) describes the error</param> | ||
| public ZLibException(int errorCode, string msg) : base(String.Format("ZLib error {0} {1}", errorCode, msg)) | ||
| { | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Initializes a new instance of the <see cref="ZLibException"/> class with a specified | ||
| /// error code | ||
| /// </summary> | ||
| /// <param name="errorCode">The zlib error code that caused the exception</param> | ||
| public ZLibException(int errorCode) : base(String.Format("ZLib error {0}", errorCode)) | ||
| { | ||
| } | ||
| } | ||
| #endregion | ||
|
|
||
| #region Interfaces | ||
|
|
||
| /// <summary> | ||
| /// Declares methods and properties that enables a running checksum to be calculated | ||
| /// </summary> | ||
| public interface ChecksumGenerator | ||
| { | ||
| /// <summary> | ||
| /// Gets the current value of the checksum | ||
| /// </summary> | ||
| uint Value { get; } | ||
|
|
||
| /// <summary> | ||
| /// Clears the current checksum to 0 | ||
| /// </summary> | ||
| void Reset(); | ||
|
|
||
| /// <summary> | ||
| /// Updates the current checksum with an array of bytes | ||
| /// </summary> | ||
| /// <param name="data">The data to update the checksum with</param> | ||
| void Update(byte[] data); | ||
|
|
||
| /// <summary> | ||
| /// Updates the current checksum with part of an array of bytes | ||
| /// </summary> | ||
| /// <param name="data">The data to update the checksum with</param> | ||
| /// <param name="offset">Where in <c>data</c> to start updating</param> | ||
| /// <param name="count">The number of bytes from <c>data</c> to use</param> | ||
| /// <exception cref="ArgumentException">The sum of offset and count is larger than the length of <c>data</c></exception> | ||
| /// <exception cref="ArgumentNullException"><c>data</c> is a null reference</exception> | ||
| /// <exception cref="ArgumentOutOfRangeException">Offset or count is negative.</exception> | ||
| void Update(byte[] data, int offset, int count); | ||
|
|
||
| /// <summary> | ||
| /// Updates the current checksum with the data from a string | ||
| /// </summary> | ||
| /// <param name="data">The string to update the checksum with</param> | ||
| /// <remarks>The characters in the string are converted by the UTF-8 encoding</remarks> | ||
| void Update(string data); | ||
|
|
||
| /// <summary> | ||
| /// Updates the current checksum with the data from a string, using a specific encoding | ||
| /// </summary> | ||
| /// <param name="data">The string to update the checksum with</param> | ||
| /// <param name="encoding">The encoding to use</param> | ||
| void Update(string data, Encoding encoding); | ||
| } | ||
|
|
||
|
|
||
| /// <summary> | ||
| /// Represents the method that will be called from a codec when new data | ||
| /// are available. | ||
| /// </summary> | ||
| /// <paramref name="data">The byte array containing the processed data</paramref> | ||
| /// <paramref name="startIndex">The index of the first processed byte in <c>data</c></paramref> | ||
| /// <paramref name="count">The number of processed bytes available</paramref> | ||
| /// <remarks>On return from this method, the data may be overwritten, so grab it while you can. | ||
| /// You cannot assume that startIndex will be zero. | ||
| /// </remarks> | ||
| public delegate void DataAvailableHandler(byte[] data, int startIndex, int count); | ||
|
|
||
| /// <summary> | ||
| /// Declares methods and events for implementing compressors/decompressors | ||
| /// </summary> | ||
| public interface Codec | ||
| { | ||
| /// <summary> | ||
| /// Occurs when more processed data are available. | ||
| /// </summary> | ||
| event DataAvailableHandler DataAvailable; | ||
|
|
||
| /// <summary> | ||
| /// Adds more data to the codec to be processed. | ||
| /// </summary> | ||
| /// <param name="data">Byte array containing the data to be added to the codec</param> | ||
| /// <remarks>Adding data may, or may not, raise the <c>DataAvailable</c> event</remarks> | ||
| void Add(byte[] data); | ||
|
|
||
| /// <summary> | ||
| /// Adds more data to the codec to be processed. | ||
| /// </summary> | ||
| /// <param name="data">Byte array containing the data to be added to the codec</param> | ||
| /// <param name="offset">The index of the first byte to add from <c>data</c></param> | ||
| /// <param name="count">The number of bytes to add</param> | ||
| /// <remarks>Adding data may, or may not, raise the <c>DataAvailable</c> event</remarks> | ||
| void Add(byte[] data, int offset, int count); | ||
|
|
||
| /// <summary> | ||
| /// Finishes up any pending data that needs to be processed and handled. | ||
| /// </summary> | ||
| void Finish(); | ||
|
|
||
| /// <summary> | ||
| /// Gets the checksum of the data that has been added so far | ||
| /// </summary> | ||
| uint Checksum { get; } | ||
|
|
||
|
|
||
| } | ||
|
|
||
| #endregion | ||
|
|
||
| #region Classes | ||
| /// <summary> | ||
| /// Encapsulates general information about the ZLib library | ||
| /// </summary> | ||
| public class Info | ||
| { | ||
| #region DLL imports | ||
| [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] | ||
| private static extern uint zlibCompileFlags(); | ||
|
|
||
| [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] | ||
| private static extern string zlibVersion(); | ||
| #endregion | ||
|
|
||
| #region Private stuff | ||
| private uint _flags; | ||
|
|
||
| // helper function that unpacks a bitsize mask | ||
| private static int bitSize(uint bits) | ||
| { | ||
| switch (bits) | ||
| { | ||
| case 0: return 16; | ||
| case 1: return 32; | ||
| case 2: return 64; | ||
| } | ||
| return -1; | ||
| } | ||
| #endregion | ||
|
|
||
| /// <summary> | ||
| /// Constructs an instance of the <c>Info</c> class. | ||
| /// </summary> | ||
| public Info() | ||
| { | ||
| _flags = zlibCompileFlags(); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// True if the library is compiled with debug info | ||
| /// </summary> | ||
| public bool HasDebugInfo { get { return 0 != (_flags & 0x100); } } | ||
|
|
||
| /// <summary> | ||
| /// True if the library is compiled with assembly optimizations | ||
| /// </summary> | ||
| public bool UsesAssemblyCode { get { return 0 != (_flags & 0x200); } } | ||
|
|
||
| /// <summary> | ||
| /// Gets the size of the unsigned int that was compiled into Zlib | ||
| /// </summary> | ||
| public int SizeOfUInt { get { return bitSize(_flags & 3); } } | ||
|
|
||
| /// <summary> | ||
| /// Gets the size of the unsigned long that was compiled into Zlib | ||
| /// </summary> | ||
| public int SizeOfULong { get { return bitSize((_flags >> 2) & 3); } } | ||
|
|
||
| /// <summary> | ||
| /// Gets the size of the pointers that were compiled into Zlib | ||
| /// </summary> | ||
| public int SizeOfPointer { get { return bitSize((_flags >> 4) & 3); } } | ||
|
|
||
| /// <summary> | ||
| /// Gets the size of the z_off_t type that was compiled into Zlib | ||
| /// </summary> | ||
| public int SizeOfOffset { get { return bitSize((_flags >> 6) & 3); } } | ||
|
|
||
| /// <summary> | ||
| /// Gets the version of ZLib as a string, e.g. "1.2.1" | ||
| /// </summary> | ||
| public static string Version { get { return zlibVersion(); } } | ||
| } | ||
|
|
||
| #endregion | ||
|
|
||
| } |
| @@ -0,0 +1,141 @@ | ||
| <VisualStudioProject> | ||
| <CSHARP | ||
| ProjectType = "Local" | ||
| ProductVersion = "7.10.3077" | ||
| SchemaVersion = "2.0" | ||
| ProjectGuid = "{BB1EE0B1-1808-46CB-B786-949D91117FC5}" | ||
| > | ||
| <Build> | ||
| <Settings | ||
| ApplicationIcon = "" | ||
| AssemblyKeyContainerName = "" | ||
| AssemblyName = "DotZLib" | ||
| AssemblyOriginatorKeyFile = "" | ||
| DefaultClientScript = "JScript" | ||
| DefaultHTMLPageLayout = "Grid" | ||
| DefaultTargetSchema = "IE50" | ||
| DelaySign = "false" | ||
| OutputType = "Library" | ||
| PreBuildEvent = "" | ||
| PostBuildEvent = "" | ||
| RootNamespace = "DotZLib" | ||
| RunPostBuildEvent = "OnBuildSuccess" | ||
| StartupObject = "" | ||
| > | ||
| <Config | ||
| Name = "Debug" | ||
| AllowUnsafeBlocks = "false" | ||
| BaseAddress = "285212672" | ||
| CheckForOverflowUnderflow = "false" | ||
| ConfigurationOverrideFile = "" | ||
| DefineConstants = "DEBUG;TRACE" | ||
| DocumentationFile = "docs\DotZLib.xml" | ||
| DebugSymbols = "true" | ||
| FileAlignment = "4096" | ||
| IncrementalBuild = "false" | ||
| NoStdLib = "false" | ||
| NoWarn = "1591" | ||
| Optimize = "false" | ||
| OutputPath = "bin\Debug\" | ||
| RegisterForComInterop = "false" | ||
| RemoveIntegerChecks = "false" | ||
| TreatWarningsAsErrors = "false" | ||
| WarningLevel = "4" | ||
| /> | ||
| <Config | ||
| Name = "Release" | ||
| AllowUnsafeBlocks = "false" | ||
| BaseAddress = "285212672" | ||
| CheckForOverflowUnderflow = "false" | ||
| ConfigurationOverrideFile = "" | ||
| DefineConstants = "TRACE" | ||
| DocumentationFile = "docs\DotZLib.xml" | ||
| DebugSymbols = "false" | ||
| FileAlignment = "4096" | ||
| IncrementalBuild = "false" | ||
| NoStdLib = "false" | ||
| NoWarn = "" | ||
| Optimize = "true" | ||
| OutputPath = "bin\Release\" | ||
| RegisterForComInterop = "false" | ||
| RemoveIntegerChecks = "false" | ||
| TreatWarningsAsErrors = "false" | ||
| WarningLevel = "4" | ||
| /> | ||
| </Settings> | ||
| <References> | ||
| <Reference | ||
| Name = "System" | ||
| AssemblyName = "System" | ||
| HintPath = "C:\WINNT\Microsoft.NET\Framework\v1.1.4322\System.dll" | ||
| /> | ||
| <Reference | ||
| Name = "System.Data" | ||
| AssemblyName = "System.Data" | ||
| HintPath = "C:\WINNT\Microsoft.NET\Framework\v1.1.4322\System.Data.dll" | ||
| /> | ||
| <Reference | ||
| Name = "System.XML" | ||
| AssemblyName = "System.Xml" | ||
| HintPath = "C:\WINNT\Microsoft.NET\Framework\v1.1.4322\System.XML.dll" | ||
| /> | ||
| <Reference | ||
| Name = "nunit.framework" | ||
| AssemblyName = "nunit.framework" | ||
| HintPath = "E:\apps\NUnit V2.1\\bin\nunit.framework.dll" | ||
| AssemblyFolderKey = "hklm\dn\nunit.framework" | ||
| /> | ||
| </References> | ||
| </Build> | ||
| <Files> | ||
| <Include> | ||
| <File | ||
| RelPath = "AssemblyInfo.cs" | ||
| SubType = "Code" | ||
| BuildAction = "Compile" | ||
| /> | ||
| <File | ||
| RelPath = "ChecksumImpl.cs" | ||
| SubType = "Code" | ||
| BuildAction = "Compile" | ||
| /> | ||
| <File | ||
| RelPath = "CircularBuffer.cs" | ||
| SubType = "Code" | ||
| BuildAction = "Compile" | ||
| /> | ||
| <File | ||
| RelPath = "CodecBase.cs" | ||
| SubType = "Code" | ||
| BuildAction = "Compile" | ||
| /> | ||
| <File | ||
| RelPath = "Deflater.cs" | ||
| SubType = "Code" | ||
| BuildAction = "Compile" | ||
| /> | ||
| <File | ||
| RelPath = "DotZLib.cs" | ||
| SubType = "Code" | ||
| BuildAction = "Compile" | ||
| /> | ||
| <File | ||
| RelPath = "GZipStream.cs" | ||
| SubType = "Code" | ||
| BuildAction = "Compile" | ||
| /> | ||
| <File | ||
| RelPath = "Inflater.cs" | ||
| SubType = "Code" | ||
| BuildAction = "Compile" | ||
| /> | ||
| <File | ||
| RelPath = "UnitTests.cs" | ||
| SubType = "Code" | ||
| BuildAction = "Compile" | ||
| /> | ||
| </Include> | ||
| </Files> | ||
| </CSHARP> | ||
| </VisualStudioProject> | ||
|
|
| @@ -0,0 +1,301 @@ | ||
| // | ||
| // © Copyright Henrik Ravn 2004 | ||
| // | ||
| // Use, modification and distribution are subject to the Boost Software License, Version 1.0. | ||
| // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
| // | ||
|
|
||
| using System; | ||
| using System.IO; | ||
| using System.Runtime.InteropServices; | ||
|
|
||
| namespace DotZLib | ||
| { | ||
| /// <summary> | ||
| /// Implements a compressed <see cref="Stream"/>, in GZip (.gz) format. | ||
| /// </summary> | ||
| public class GZipStream : Stream, IDisposable | ||
| { | ||
| #region Dll Imports | ||
| [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)] | ||
| private static extern IntPtr gzopen(string name, string mode); | ||
|
|
||
| [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] | ||
| private static extern int gzclose(IntPtr gzFile); | ||
|
|
||
| [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] | ||
| private static extern int gzwrite(IntPtr gzFile, int data, int length); | ||
|
|
||
| [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] | ||
| private static extern int gzread(IntPtr gzFile, int data, int length); | ||
|
|
||
| [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] | ||
| private static extern int gzgetc(IntPtr gzFile); | ||
|
|
||
| [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] | ||
| private static extern int gzputc(IntPtr gzFile, int c); | ||
|
|
||
| #endregion | ||
|
|
||
| #region Private data | ||
| private IntPtr _gzFile; | ||
| private bool _isDisposed = false; | ||
| private bool _isWriting; | ||
| #endregion | ||
|
|
||
| #region Constructors | ||
| /// <summary> | ||
| /// Creates a new file as a writeable GZipStream | ||
| /// </summary> | ||
| /// <param name="fileName">The name of the compressed file to create</param> | ||
| /// <param name="level">The compression level to use when adding data</param> | ||
| /// <exception cref="ZLibException">If an error occurred in the internal zlib function</exception> | ||
| public GZipStream(string fileName, CompressLevel level) | ||
| { | ||
| _isWriting = true; | ||
| _gzFile = gzopen(fileName, String.Format("wb{0}", (int)level)); | ||
| if (_gzFile == IntPtr.Zero) | ||
| throw new ZLibException(-1, "Could not open " + fileName); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Opens an existing file as a readable GZipStream | ||
| /// </summary> | ||
| /// <param name="fileName">The name of the file to open</param> | ||
| /// <exception cref="ZLibException">If an error occurred in the internal zlib function</exception> | ||
| public GZipStream(string fileName) | ||
| { | ||
| _isWriting = false; | ||
| _gzFile = gzopen(fileName, "rb"); | ||
| if (_gzFile == IntPtr.Zero) | ||
| throw new ZLibException(-1, "Could not open " + fileName); | ||
|
|
||
| } | ||
| #endregion | ||
|
|
||
| #region Access properties | ||
| /// <summary> | ||
| /// Returns true of this stream can be read from, false otherwise | ||
| /// </summary> | ||
| public override bool CanRead | ||
| { | ||
| get | ||
| { | ||
| return !_isWriting; | ||
| } | ||
| } | ||
|
|
||
|
|
||
| /// <summary> | ||
| /// Returns false. | ||
| /// </summary> | ||
| public override bool CanSeek | ||
| { | ||
| get | ||
| { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Returns true if this tsream is writeable, false otherwise | ||
| /// </summary> | ||
| public override bool CanWrite | ||
| { | ||
| get | ||
| { | ||
| return _isWriting; | ||
| } | ||
| } | ||
| #endregion | ||
|
|
||
| #region Destructor & IDispose stuff | ||
|
|
||
| /// <summary> | ||
| /// Destroys this instance | ||
| /// </summary> | ||
| ~GZipStream() | ||
| { | ||
| cleanUp(false); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Closes the external file handle | ||
| /// </summary> | ||
| public void Dispose() | ||
| { | ||
| cleanUp(true); | ||
| } | ||
|
|
||
| // Does the actual closing of the file handle. | ||
| private void cleanUp(bool isDisposing) | ||
| { | ||
| if (!_isDisposed) | ||
| { | ||
| gzclose(_gzFile); | ||
| _isDisposed = true; | ||
| } | ||
| } | ||
| #endregion | ||
|
|
||
| #region Basic reading and writing | ||
| /// <summary> | ||
| /// Attempts to read a number of bytes from the stream. | ||
| /// </summary> | ||
| /// <param name="buffer">The destination data buffer</param> | ||
| /// <param name="offset">The index of the first destination byte in <c>buffer</c></param> | ||
| /// <param name="count">The number of bytes requested</param> | ||
| /// <returns>The number of bytes read</returns> | ||
| /// <exception cref="ArgumentNullException">If <c>buffer</c> is null</exception> | ||
| /// <exception cref="ArgumentOutOfRangeException">If <c>count</c> or <c>offset</c> are negative</exception> | ||
| /// <exception cref="ArgumentException">If <c>offset</c> + <c>count</c> is > buffer.Length</exception> | ||
| /// <exception cref="NotSupportedException">If this stream is not readable.</exception> | ||
| /// <exception cref="ObjectDisposedException">If this stream has been disposed.</exception> | ||
| public override int Read(byte[] buffer, int offset, int count) | ||
| { | ||
| if (!CanRead) throw new NotSupportedException(); | ||
| if (buffer == null) throw new ArgumentNullException(); | ||
| if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); | ||
| if ((offset+count) > buffer.Length) throw new ArgumentException(); | ||
| if (_isDisposed) throw new ObjectDisposedException("GZipStream"); | ||
|
|
||
| GCHandle h = GCHandle.Alloc(buffer, GCHandleType.Pinned); | ||
| int result; | ||
| try | ||
| { | ||
| result = gzread(_gzFile, h.AddrOfPinnedObject().ToInt32() + offset, count); | ||
| if (result < 0) | ||
| throw new IOException(); | ||
| } | ||
| finally | ||
| { | ||
| h.Free(); | ||
| } | ||
| return result; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Attempts to read a single byte from the stream. | ||
| /// </summary> | ||
| /// <returns>The byte that was read, or -1 in case of error or End-Of-File</returns> | ||
| public override int ReadByte() | ||
| { | ||
| if (!CanRead) throw new NotSupportedException(); | ||
| if (_isDisposed) throw new ObjectDisposedException("GZipStream"); | ||
| return gzgetc(_gzFile); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Writes a number of bytes to the stream | ||
| /// </summary> | ||
| /// <param name="buffer"></param> | ||
| /// <param name="offset"></param> | ||
| /// <param name="count"></param> | ||
| /// <exception cref="ArgumentNullException">If <c>buffer</c> is null</exception> | ||
| /// <exception cref="ArgumentOutOfRangeException">If <c>count</c> or <c>offset</c> are negative</exception> | ||
| /// <exception cref="ArgumentException">If <c>offset</c> + <c>count</c> is > buffer.Length</exception> | ||
| /// <exception cref="NotSupportedException">If this stream is not writeable.</exception> | ||
| /// <exception cref="ObjectDisposedException">If this stream has been disposed.</exception> | ||
| public override void Write(byte[] buffer, int offset, int count) | ||
| { | ||
| if (!CanWrite) throw new NotSupportedException(); | ||
| if (buffer == null) throw new ArgumentNullException(); | ||
| if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); | ||
| if ((offset+count) > buffer.Length) throw new ArgumentException(); | ||
| if (_isDisposed) throw new ObjectDisposedException("GZipStream"); | ||
|
|
||
| GCHandle h = GCHandle.Alloc(buffer, GCHandleType.Pinned); | ||
| try | ||
| { | ||
| int result = gzwrite(_gzFile, h.AddrOfPinnedObject().ToInt32() + offset, count); | ||
| if (result < 0) | ||
| throw new IOException(); | ||
| } | ||
| finally | ||
| { | ||
| h.Free(); | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Writes a single byte to the stream | ||
| /// </summary> | ||
| /// <param name="value">The byte to add to the stream.</param> | ||
| /// <exception cref="NotSupportedException">If this stream is not writeable.</exception> | ||
| /// <exception cref="ObjectDisposedException">If this stream has been disposed.</exception> | ||
| public override void WriteByte(byte value) | ||
| { | ||
| if (!CanWrite) throw new NotSupportedException(); | ||
| if (_isDisposed) throw new ObjectDisposedException("GZipStream"); | ||
|
|
||
| int result = gzputc(_gzFile, (int)value); | ||
| if (result < 0) | ||
| throw new IOException(); | ||
| } | ||
| #endregion | ||
|
|
||
| #region Position & length stuff | ||
| /// <summary> | ||
| /// Not supported. | ||
| /// </summary> | ||
| /// <param name="value"></param> | ||
| /// <exception cref="NotSupportedException">Always thrown</exception> | ||
| public override void SetLength(long value) | ||
| { | ||
| throw new NotSupportedException(); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Not suppported. | ||
| /// </summary> | ||
| /// <param name="offset"></param> | ||
| /// <param name="origin"></param> | ||
| /// <returns></returns> | ||
| /// <exception cref="NotSupportedException">Always thrown</exception> | ||
| public override long Seek(long offset, SeekOrigin origin) | ||
| { | ||
| throw new NotSupportedException(); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Flushes the <c>GZipStream</c>. | ||
| /// </summary> | ||
| /// <remarks>In this implementation, this method does nothing. This is because excessive | ||
| /// flushing may degrade the achievable compression rates.</remarks> | ||
| public override void Flush() | ||
| { | ||
| // left empty on purpose | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Gets/sets the current position in the <c>GZipStream</c>. Not suppported. | ||
| /// </summary> | ||
| /// <remarks>In this implementation this property is not supported</remarks> | ||
| /// <exception cref="NotSupportedException">Always thrown</exception> | ||
| public override long Position | ||
| { | ||
| get | ||
| { | ||
| throw new NotSupportedException(); | ||
| } | ||
| set | ||
| { | ||
| throw new NotSupportedException(); | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Gets the size of the stream. Not suppported. | ||
| /// </summary> | ||
| /// <remarks>In this implementation this property is not supported</remarks> | ||
| /// <exception cref="NotSupportedException">Always thrown</exception> | ||
| public override long Length | ||
| { | ||
| get | ||
| { | ||
| throw new NotSupportedException(); | ||
| } | ||
| } | ||
| #endregion | ||
| } | ||
| } |
| @@ -0,0 +1,105 @@ | ||
| // | ||
| // © Copyright Henrik Ravn 2004 | ||
| // | ||
| // Use, modification and distribution are subject to the Boost Software License, Version 1.0. | ||
| // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
| // | ||
|
|
||
| using System; | ||
| using System.Diagnostics; | ||
| using System.Runtime.InteropServices; | ||
|
|
||
| namespace DotZLib | ||
| { | ||
|
|
||
| /// <summary> | ||
| /// Implements a data decompressor, using the inflate algorithm in the ZLib dll | ||
| /// </summary> | ||
| public class Inflater : CodecBase | ||
| { | ||
| #region Dll imports | ||
| [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)] | ||
| private static extern int inflateInit_(ref ZStream sz, string vs, int size); | ||
|
|
||
| [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] | ||
| private static extern int inflate(ref ZStream sz, int flush); | ||
|
|
||
| [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] | ||
| private static extern int inflateReset(ref ZStream sz); | ||
|
|
||
| [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] | ||
| private static extern int inflateEnd(ref ZStream sz); | ||
| #endregion | ||
|
|
||
| /// <summary> | ||
| /// Constructs an new instance of the <c>Inflater</c> | ||
| /// </summary> | ||
| public Inflater() : base() | ||
| { | ||
| int retval = inflateInit_(ref _ztream, Info.Version, Marshal.SizeOf(_ztream)); | ||
| if (retval != 0) | ||
| throw new ZLibException(retval, "Could not initialize inflater"); | ||
|
|
||
| resetOutput(); | ||
| } | ||
|
|
||
|
|
||
| /// <summary> | ||
| /// Adds more data to the codec to be processed. | ||
| /// </summary> | ||
| /// <param name="data">Byte array containing the data to be added to the codec</param> | ||
| /// <param name="offset">The index of the first byte to add from <c>data</c></param> | ||
| /// <param name="count">The number of bytes to add</param> | ||
| /// <remarks>Adding data may, or may not, raise the <c>DataAvailable</c> event</remarks> | ||
| public override void Add(byte[] data, int offset, int count) | ||
| { | ||
| if (data == null) throw new ArgumentNullException(); | ||
| if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); | ||
| if ((offset+count) > data.Length) throw new ArgumentException(); | ||
|
|
||
| int total = count; | ||
| int inputIndex = offset; | ||
| int err = 0; | ||
|
|
||
| while (err >= 0 && inputIndex < total) | ||
| { | ||
| copyInput(data, inputIndex, Math.Min(total - inputIndex, kBufferSize)); | ||
| err = inflate(ref _ztream, (int)FlushTypes.None); | ||
| if (err == 0) | ||
| while (_ztream.avail_out == 0) | ||
| { | ||
| OnDataAvailable(); | ||
| err = inflate(ref _ztream, (int)FlushTypes.None); | ||
| } | ||
|
|
||
| inputIndex += (int)_ztream.total_in; | ||
| } | ||
| setChecksum( _ztream.adler ); | ||
| } | ||
|
|
||
|
|
||
| /// <summary> | ||
| /// Finishes up any pending data that needs to be processed and handled. | ||
| /// </summary> | ||
| public override void Finish() | ||
| { | ||
| int err; | ||
| do | ||
| { | ||
| err = inflate(ref _ztream, (int)FlushTypes.Finish); | ||
| OnDataAvailable(); | ||
| } | ||
| while (err == 0); | ||
| setChecksum( _ztream.adler ); | ||
| inflateReset(ref _ztream); | ||
| resetOutput(); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Closes the internal zlib inflate stream | ||
| /// </summary> | ||
| protected override void CleanUp() { inflateEnd(ref _ztream); } | ||
|
|
||
|
|
||
| } | ||
| } |
| @@ -0,0 +1,274 @@ | ||
| // | ||
| // © Copyright Henrik Ravn 2004 | ||
| // | ||
| // Use, modification and distribution are subject to the Boost Software License, Version 1.0. | ||
| // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
| // | ||
|
|
||
| using System; | ||
| using System.Collections; | ||
| using System.IO; | ||
|
|
||
| // uncomment the define below to include unit tests | ||
| //#define nunit | ||
| #if nunit | ||
| using NUnit.Framework; | ||
|
|
||
| // Unit tests for the DotZLib class library | ||
| // ---------------------------------------- | ||
| // | ||
| // Use this with NUnit 2 from http://www.nunit.org | ||
| // | ||
|
|
||
| namespace DotZLibTests | ||
| { | ||
| using DotZLib; | ||
|
|
||
| // helper methods | ||
| internal class Utils | ||
| { | ||
| public static bool byteArrEqual( byte[] lhs, byte[] rhs ) | ||
| { | ||
| if (lhs.Length != rhs.Length) | ||
| return false; | ||
| for (int i = lhs.Length-1; i >= 0; --i) | ||
| if (lhs[i] != rhs[i]) | ||
| return false; | ||
| return true; | ||
| } | ||
|
|
||
| } | ||
|
|
||
|
|
||
| [TestFixture] | ||
| public class CircBufferTests | ||
| { | ||
| #region Circular buffer tests | ||
| [Test] | ||
| public void SinglePutGet() | ||
| { | ||
| CircularBuffer buf = new CircularBuffer(10); | ||
| Assert.AreEqual( 0, buf.Size ); | ||
| Assert.AreEqual( -1, buf.Get() ); | ||
|
|
||
| Assert.IsTrue(buf.Put( 1 )); | ||
| Assert.AreEqual( 1, buf.Size ); | ||
| Assert.AreEqual( 1, buf.Get() ); | ||
| Assert.AreEqual( 0, buf.Size ); | ||
| Assert.AreEqual( -1, buf.Get() ); | ||
| } | ||
|
|
||
| [Test] | ||
| public void BlockPutGet() | ||
| { | ||
| CircularBuffer buf = new CircularBuffer(10); | ||
| byte[] arr = {1,2,3,4,5,6,7,8,9,10}; | ||
| Assert.AreEqual( 10, buf.Put(arr,0,10) ); | ||
| Assert.AreEqual( 10, buf.Size ); | ||
| Assert.IsFalse( buf.Put(11) ); | ||
| Assert.AreEqual( 1, buf.Get() ); | ||
| Assert.IsTrue( buf.Put(11) ); | ||
|
|
||
| byte[] arr2 = (byte[])arr.Clone(); | ||
| Assert.AreEqual( 9, buf.Get(arr2,1,9) ); | ||
| Assert.IsTrue( Utils.byteArrEqual(arr,arr2) ); | ||
| } | ||
|
|
||
| #endregion | ||
| } | ||
|
|
||
| [TestFixture] | ||
| public class ChecksumTests | ||
| { | ||
| #region CRC32 Tests | ||
| [Test] | ||
| public void CRC32_Null() | ||
| { | ||
| CRC32Checksum crc32 = new CRC32Checksum(); | ||
| Assert.AreEqual( 0, crc32.Value ); | ||
|
|
||
| crc32 = new CRC32Checksum(1); | ||
| Assert.AreEqual( 1, crc32.Value ); | ||
|
|
||
| crc32 = new CRC32Checksum(556); | ||
| Assert.AreEqual( 556, crc32.Value ); | ||
| } | ||
|
|
||
| [Test] | ||
| public void CRC32_Data() | ||
| { | ||
| CRC32Checksum crc32 = new CRC32Checksum(); | ||
| byte[] data = { 1,2,3,4,5,6,7 }; | ||
| crc32.Update(data); | ||
| Assert.AreEqual( 0x70e46888, crc32.Value ); | ||
|
|
||
| crc32 = new CRC32Checksum(); | ||
| crc32.Update("penguin"); | ||
| Assert.AreEqual( 0x0e5c1a120, crc32.Value ); | ||
|
|
||
| crc32 = new CRC32Checksum(1); | ||
| crc32.Update("penguin"); | ||
| Assert.AreEqual(0x43b6aa94, crc32.Value); | ||
|
|
||
| } | ||
| #endregion | ||
|
|
||
| #region Adler tests | ||
|
|
||
| [Test] | ||
| public void Adler_Null() | ||
| { | ||
| AdlerChecksum adler = new AdlerChecksum(); | ||
| Assert.AreEqual(0, adler.Value); | ||
|
|
||
| adler = new AdlerChecksum(1); | ||
| Assert.AreEqual( 1, adler.Value ); | ||
|
|
||
| adler = new AdlerChecksum(556); | ||
| Assert.AreEqual( 556, adler.Value ); | ||
| } | ||
|
|
||
| [Test] | ||
| public void Adler_Data() | ||
| { | ||
| AdlerChecksum adler = new AdlerChecksum(1); | ||
| byte[] data = { 1,2,3,4,5,6,7 }; | ||
| adler.Update(data); | ||
| Assert.AreEqual( 0x5b001d, adler.Value ); | ||
|
|
||
| adler = new AdlerChecksum(); | ||
| adler.Update("penguin"); | ||
| Assert.AreEqual(0x0bcf02f6, adler.Value ); | ||
|
|
||
| adler = new AdlerChecksum(1); | ||
| adler.Update("penguin"); | ||
| Assert.AreEqual(0x0bd602f7, adler.Value); | ||
|
|
||
| } | ||
| #endregion | ||
| } | ||
|
|
||
| [TestFixture] | ||
| public class InfoTests | ||
| { | ||
| #region Info tests | ||
| [Test] | ||
| public void Info_Version() | ||
| { | ||
| Info info = new Info(); | ||
| Assert.AreEqual("1.2.8", Info.Version); | ||
| Assert.AreEqual(32, info.SizeOfUInt); | ||
| Assert.AreEqual(32, info.SizeOfULong); | ||
| Assert.AreEqual(32, info.SizeOfPointer); | ||
| Assert.AreEqual(32, info.SizeOfOffset); | ||
| } | ||
| #endregion | ||
| } | ||
|
|
||
| [TestFixture] | ||
| public class DeflateInflateTests | ||
| { | ||
| #region Deflate tests | ||
| [Test] | ||
| public void Deflate_Init() | ||
| { | ||
| using (Deflater def = new Deflater(CompressLevel.Default)) | ||
| { | ||
| } | ||
| } | ||
|
|
||
| private ArrayList compressedData = new ArrayList(); | ||
| private uint adler1; | ||
|
|
||
| private ArrayList uncompressedData = new ArrayList(); | ||
| private uint adler2; | ||
|
|
||
| public void CDataAvail(byte[] data, int startIndex, int count) | ||
| { | ||
| for (int i = 0; i < count; ++i) | ||
| compressedData.Add(data[i+startIndex]); | ||
| } | ||
|
|
||
| [Test] | ||
| public void Deflate_Compress() | ||
| { | ||
| compressedData.Clear(); | ||
|
|
||
| byte[] testData = new byte[35000]; | ||
| for (int i = 0; i < testData.Length; ++i) | ||
| testData[i] = 5; | ||
|
|
||
| using (Deflater def = new Deflater((CompressLevel)5)) | ||
| { | ||
| def.DataAvailable += new DataAvailableHandler(CDataAvail); | ||
| def.Add(testData); | ||
| def.Finish(); | ||
| adler1 = def.Checksum; | ||
| } | ||
| } | ||
| #endregion | ||
|
|
||
| #region Inflate tests | ||
| [Test] | ||
| public void Inflate_Init() | ||
| { | ||
| using (Inflater inf = new Inflater()) | ||
| { | ||
| } | ||
| } | ||
|
|
||
| private void DDataAvail(byte[] data, int startIndex, int count) | ||
| { | ||
| for (int i = 0; i < count; ++i) | ||
| uncompressedData.Add(data[i+startIndex]); | ||
| } | ||
|
|
||
| [Test] | ||
| public void Inflate_Expand() | ||
| { | ||
| uncompressedData.Clear(); | ||
|
|
||
| using (Inflater inf = new Inflater()) | ||
| { | ||
| inf.DataAvailable += new DataAvailableHandler(DDataAvail); | ||
| inf.Add((byte[])compressedData.ToArray(typeof(byte))); | ||
| inf.Finish(); | ||
| adler2 = inf.Checksum; | ||
| } | ||
| Assert.AreEqual( adler1, adler2 ); | ||
| } | ||
| #endregion | ||
| } | ||
|
|
||
| [TestFixture] | ||
| public class GZipStreamTests | ||
| { | ||
| #region GZipStream test | ||
| [Test] | ||
| public void GZipStream_WriteRead() | ||
| { | ||
| using (GZipStream gzOut = new GZipStream("gzstream.gz", CompressLevel.Best)) | ||
| { | ||
| BinaryWriter writer = new BinaryWriter(gzOut); | ||
| writer.Write("hi there"); | ||
| writer.Write(Math.PI); | ||
| writer.Write(42); | ||
| } | ||
|
|
||
| using (GZipStream gzIn = new GZipStream("gzstream.gz")) | ||
| { | ||
| BinaryReader reader = new BinaryReader(gzIn); | ||
| string s = reader.ReadString(); | ||
| Assert.AreEqual("hi there",s); | ||
| double d = reader.ReadDouble(); | ||
| Assert.AreEqual(Math.PI, d); | ||
| int i = reader.ReadInt32(); | ||
| Assert.AreEqual(42,i); | ||
| } | ||
|
|
||
| } | ||
| #endregion | ||
| } | ||
| } | ||
|
|
||
| #endif |
| @@ -0,0 +1,23 @@ | ||
| Boost Software License - Version 1.0 - August 17th, 2003 | ||
|
|
||
| Permission is hereby granted, free of charge, to any person or organization | ||
| obtaining a copy of the software and accompanying documentation covered by | ||
| this license (the "Software") to use, reproduce, display, distribute, | ||
| execute, and transmit the Software, and to prepare derivative works of the | ||
| Software, and to permit third-parties to whom the Software is furnished to | ||
| do so, all subject to the following: | ||
|
|
||
| The copyright notices in the Software and this entire statement, including | ||
| the above license grant, this restriction and the following disclaimer, | ||
| must be included in all copies of the Software, in whole or in part, and | ||
| all derivative works of the Software, unless such copies or derivative | ||
| works are solely in the form of machine-executable object code generated by | ||
| a source language processor. | ||
|
|
||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT | ||
| SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE | ||
| FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, | ||
| ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| DEALINGS IN THE SOFTWARE. |
| @@ -0,0 +1,58 @@ | ||
| This directory contains a .Net wrapper class library for the ZLib1.dll | ||
|
|
||
| The wrapper includes support for inflating/deflating memory buffers, | ||
| .Net streaming wrappers for the gz streams part of zlib, and wrappers | ||
| for the checksum parts of zlib. See DotZLib/UnitTests.cs for examples. | ||
|
|
||
| Directory structure: | ||
| -------------------- | ||
|
|
||
| LICENSE_1_0.txt - License file. | ||
| readme.txt - This file. | ||
| DotZLib.chm - Class library documentation | ||
| DotZLib.build - NAnt build file | ||
| DotZLib.sln - Microsoft Visual Studio 2003 solution file | ||
|
|
||
| DotZLib\*.cs - Source files for the class library | ||
|
|
||
| Unit tests: | ||
| ----------- | ||
| The file DotZLib/UnitTests.cs contains unit tests for use with NUnit 2.1 or higher. | ||
| To include unit tests in the build, define nunit before building. | ||
|
|
||
|
|
||
| Build instructions: | ||
| ------------------- | ||
|
|
||
| 1. Using Visual Studio.Net 2003: | ||
| Open DotZLib.sln in VS.Net and build from there. Output file (DotZLib.dll) | ||
| will be found ./DotZLib/bin/release or ./DotZLib/bin/debug, depending on | ||
| you are building the release or debug version of the library. Check | ||
| DotZLib/UnitTests.cs for instructions on how to include unit tests in the | ||
| build. | ||
|
|
||
| 2. Using NAnt: | ||
| Open a command prompt with access to the build environment and run nant | ||
| in the same directory as the DotZLib.build file. | ||
| You can define 2 properties on the nant command-line to control the build: | ||
| debug={true|false} to toggle between release/debug builds (default=true). | ||
| nunit={true|false} to include or esclude unit tests (default=true). | ||
| Also the target clean will remove binaries. | ||
| Output file (DotZLib.dll) will be found in either ./DotZLib/bin/release | ||
| or ./DotZLib/bin/debug, depending on whether you are building the release | ||
| or debug version of the library. | ||
|
|
||
| Examples: | ||
| nant -D:debug=false -D:nunit=false | ||
| will build a release mode version of the library without unit tests. | ||
| nant | ||
| will build a debug version of the library with unit tests | ||
| nant clean | ||
| will remove all previously built files. | ||
|
|
||
|
|
||
| --------------------------------- | ||
| Copyright (c) Henrik Ravn 2004 | ||
|
|
||
| Use, modification and distribution are subject to the Boost Software License, Version 1.0. | ||
| (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| @@ -0,0 +1 @@ | ||
| See infback9.h for what this is and how to use it. |