easy zlib C/C++ compress and XML compression

This free easy zlib C/C++ source code download makes it painless if you want simple in-memory XML compression (or any text, HTML, image or data compression) and decompression and don't want to spend time learning about zlib.

         

Download Release 1.0 zip (85k)
easyzlib C/C++ source code for most compilers

The zlib compression library is amalgamated in a single file easyzlib.c so you can easily add it to your C or C++ project without hassles.

How to use easy zlib

Download the zip file, open it, copy easyzlib.c and easyzlib.h and add them to your project. Use the ezcompress and ezuncompress functions to compress or decompress your source buffer to your destination buffer.

int ezcompress( unsigned char* pDest, long* pnDestLen,
                const unsigned char* pSrc, long nSrcLen );
int ezuncompress( unsigned char* pDest, long* pnDestLen,
                  const unsigned char* pSrc, long nSrcLen );

These are the return codes:

Return codeValueLikely reason
EZ_STREAM_ERROR-2pDest is NULL
EZ_DATA_ERROR-3corrupted pSrc passed to ezuncompress
EZ_MEM_ERROR-4out of memory
EZ_BUF_ERROR-5pDest length is not enough

Determining buffer size for the result

The hard part of using compression functions is guessing or determining buffer sizes. With zlib, you are guaranteed the compressed result will be at most the size of the source plus 12 plus 0.1%. The easyzlib.h header defines EZ_COMPRESSMAXDESTLENGTH to do this calculation for you.

#define EZ_COMPRESSMAXDESTLENGTH(n) (n+(((n)/1000)+1)+12)

That is the maximum memory length of your compressed result. The actual compressed length will be returned from ezcompress in pnDestLen.

If you store the original size with your compressed result, you can allocate exactly the memory you need to decompress it later. However, if you don't know the decompressed size, or you don't want to allocate the maximum compress size, easy zlib provides another option...

Getting the exact result size beforehand

In the core functions ezcompress and ezuncompress, I've added a feature that the regular zlib compress and uncompress functions don't have. If the destination buffer is too small, the functions still continue on to discover the required memory to complete the operation (which is returned in the pnDestLen parameter).

This way you can pass a small buffer in order to find out the exact size and then allocate only the size you need, whether compressing or decompressing. Here is an example that allocates 8192 bytes up front and then allocates the actual size if 8192 wasn't enough.

long nDestLen = 8192;
unsigned char* pDest = new unsigned char[nDestLen];
int nErr = ezuncompress( pDest, &nDestLen, pSrcBuf, nSrcLen );
if ( nErr == EZ_BUF_ERROR )
{
  delete[] pDest;
  pDest = new unsigned char[nDestLen]; // enough room now
  nErr = ezuncompress( pDest, &nDestLen, pSrcBuf, nSrcLen );
}

Help with allocating buffers

If you are using C++, there are additional overloaded functions implemented in easyzlib.h to make compression even easier. First of all there is a simple buffer class called ezbuffer to streamline your code. By encapsulating the buffer pointer and length in a structure, your code is simpler, plus these functions automatically allocate the destination buffer to accomodate the result.

int ezcompress( ezbuffer& bufDest, const ezbuffer& bufSrc );
int ezuncompress( ezbuffer& bufDest, const ezbuffer& bufSrc );

The resulting destination length is returned in bufDest.nLen. Here are the public members of ezbuffer:

struct ezbuffer
{
  ezbuffer(); // constructor
  ezbuffer( int n ); // constructor allocates n bytes
  ~ezbuffer(); // destructor
  unsigned char* Alloc( int n );
  void Release();
  unsigned char* pBuf;
  long nLen; // data length
};

Here is an example reading nBytes from a file into an ezbuffer and compressing it into another ezbuffer that is allocated automatically.

ezbuffer bufSrc( nBytes );
fread( bufSrc.pBuf, nBytes, 1, fp );
ezbuffer bufDest;
ezcompress( bufDest, bufSrc );

String and XML compression

C++ string functions are provided if you are using CMarkup and you include easylib.h after Markup.h since the necessary string types and functions are defined in Markup.h. Again, you do not need to estimate the size or do buffer allocations.

int ezcompress( ezbuffer& bufDest, const MCD_STR& strSrc );
int ezuncompress( MCD_STR& strDest, const ezbuffer& bufSrc );

To compress a string such as an XML document, just do the following:

ezbuffer buf;
ezcompress( buf, xml.GetDoc() );

The buf object now contains the compressed document. Use buf.pBuf and buf.nLen to access the compression data.

Why easy zlib?

The zlib compression library is widely used compression software written by Jean-loup Gailly and Mark Adler which is free at zlib.net. If you download it there you will find 28 source code files (plus another 167 supporting files in 34 subfolders).

I've used zlib in numerous projects, and every time I've had to go through the hassle of adding 28 source files to my project. Plus I need to sort out exactly which functions I need, deflate or compress, inflate or uncompress, and which arguments, headers and settings. And there is jargon I have to familiarize myself with everytime I look through zlib.

Also, all of the headers create opportunities for compiling and naming conflicts. There is no reason for every piece of code that needs to compress and uncompress to compile gobs of zlib headers. Headers should provide only the prototypes you need.

 

comment posted multiply defined symbol errors in easy zlib

Dusan Stevanovic 08-Sep-2009

First of all thank you for developing and sharing this extremely useful lib. It has all I ever wanted from zlib, but in much smaller and easier to use package. :) I wanted you to know that I compiled it under mac OS X using xcode 3.1 (intel mac). I found only one issue, the linker was reporting duplicate symbols for function (since multiple source files have easy zlib included).

int ezcompress( ezbuffer& bufDest, const ezbuffer& bufSrc )
and similar...

I solved it by declaring the functions inline:

inline int ezcompress( ezbuffer& bufDest, const ezbuffer& bufSrc )
inline int ezuncompress( ezbuffer& bufDest, const ezbuffer& bufSrc )
inline int ezcompress( ezbuffer& bufDest, const MCD_STR& strSrc )
inline int ezuncompress( MCD_STR& strDest, const ezbuffer& bufSrc )

Thank you so much. Release 1.1 will incorporate this fix. In the meantime, all C++ users including easyzlib.h in multiple places will need to add the inline keyword as described.

 

comment posted easy zlib written permission

Lars Olsson 13-Nov-2008

I want written permission to use easy zlib in our streaming server application. I needed a simple way to compress/decompress the payload of a certain message sent by UDP and it would be an incredible relief to just have to use your two files instead of the whole zlib.

You only need written permission if you want to redistribute easyzlib.c on the web or as part of a source code distribution. You can freely compile it in your commercial product, use it and modify it however you like. Best wishes with your project.

 

comment posted easy zlib checksum question

Mortaza Doulaty 01-Jun-2009

I've downloaded and used your easy zlib, it is really easy to use! But when I compress and decompress files using your library, the checksum of files are different. Here is my sample source code:

The reason the checksum was different on the saved file from the original was that the fopen read mode was "r" while the write mode was "wb". The read mode needed to be binary too, i.e. "rb". I'm putting the corrected code below as example C code to read a binary file, compress and decompress it, and write it back out.

FILE *f = fopen("C:\\sunset.bmp","rb");
fseek(f,0,SEEK_END);
long bufferSize=ftell(f);
fseek(f,0,SEEK_SET);
unsigned char *buffer = new unsigned char[bufferSize];
ezbuffer b1(bufferSize),b2,b3;
fread(b1.pBuf,bufferSize,1,f);
fclose(f);
ezcompress(b2,b1);
ezuncompress(b3,b2);
FILE *f2 = fopen("C:\\mrt.bmp","wb");
fwrite(b3.pBuf,1,b3.nLen,f2);
fclose(f2);