/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef CRYINCLUDE_CRYCOMMON_IZLIBCOMPRESSOR_H
#define CRYINCLUDE_CRYCOMMON_IZLIBCOMPRESSOR_H
#pragma once
/*
wrapper interface for the zlib compression / deflate interface
supports multiple compression streams with an async compatible wrapper
Gotchas:
the ptr to the input data must remain valid whilst the stream is deflating
the ptr to the output buffer must remain valid whilst the stream is deflating
****************************************************************************************
usage example:
IZLibCompressor *pComp=GetISystem()->GetIZLibCompressor();
// see deflateInit2() documentation zlib manual for more info on the parameters here
// this initializes the stream to produce a gzip format block with fairly low memory requirements
IZLibDeflateStream *pStream=pComp->CreateDeflateStream(2,eZMeth_Deflated,24,3,eZStrat_Default,eZFlush_NoFlush);
char *pOutput=new char[512]; // arbitrary size
const char *pInputData="This is an example piece of data that is to be compressed. It can be any arbitrary block of binary data - not just text";
const int inputBlockSize=16; // to simulate streaming of input, this example provides the input in 16 byte blocks
int totalInput=sizeof(pInputData);
int bytesInput=0;
bool done=false;
FILE *outputFile=fopen("myfile.gz","rb");
do
{
EZDeflateState state=pStream->GetState();
switch (state)
{
case eZDefState_AwaitingInput:
// 'stream' input data, there is no restriction on the block size you can input, if all the data is available immediately, input all of it at once
{
int inputSize=min(inputBlockSize,totalInput-bytesInput);
if (inputSize<=0)
{
pStream->EndInput();
}
else
{
pStream->Input(pInputData+bytesInput,inputSize);
bytesInput+=inputSize;
}
}
break;
case eZDefState_Deflating:
// do something more interesting... like getting out of this loop and running the rest of your game...
break;
case eZDefState_ConsumeOutput:
// stream output to a file
{
int bytesToOutput=pStream->GetBytesOutput();
if (bytesToOutput>0)
{
fwrite(pOutput,1,bytesToOutput,outputFile);
}
pStream->SetOutputBuffer(pOutput,sizeof(pOutput));
}
break;
case eZDefState_Finished:
case ezDefState_Error:
done=true;
break;
}
} while (!done);
fclose(outputFile);
pStream->Release();
delete [] pOutput;
****************************************************************************************/
// don't change the order of these zlib wrapping enum values without updating the mapping
// implementation in CZLibCompressorStream
enum EZLibStrategy
{
eZStrat_Default, // Z_DEFAULT_STRATEGY
eZStrat_Filtered, // Z_FILTERED
eZStrat_HuffmanOnly, // Z_HUFFMAN_ONLY
eZStrat_RLE // Z_RLE
};
enum EZLibMethod
{
eZMeth_Deflated // Z_DEFLATED
};
enum EZLibFlush
{
eZFlush_NoFlush, // Z_NO_FLUSH
eZFlush_PartialFlush, // Z_PARTIAL_FLUSH
eZFlush_SyncFlush, // Z_SYNC_FLUSH
eZFlush_FullFlush, // Z_FULL_FLUSH
};
enum EZDeflateState
{
eZDefState_AwaitingInput, // caller must call Input() or Finish() to continue
eZDefState_Deflating, // caller must wait
eZDefState_ConsumeOutput, // caller must consume output and then call SetOutputBuffer() to continue
eZDefState_Finished, // stream finished, caller must call Release() to destroy stream
eZDefState_Error // error has occurred and the stream has been closed and will no longer compress
};
struct IZLibDeflateStream
{
protected:
virtual ~IZLibDeflateStream() {}; // use Release()
public:
struct SStats
{
int bytesInput;
int bytesOutput;
int curMemoryUsed;
int peakMemoryUsed;
};
//
// Description:
// Specifies the output buffer for the deflate operation
// Should be set before providing input
// The specified buffer must remain valid (ie do not free) whilst compression is in progress (state == eZDefState_Deflating)
virtual void SetOutputBuffer(char* pInBuffer, int inSize) = 0;
// Description:
// Returns the number of bytes from the output buffer that are ready to be consumed. After consuming any output, you should call SetOutputBuffer() again to mark the buffer as available
virtual int GetBytesOutput() = 0;
// Description:
// Begins compressing the source data pInSource of length inSourceSize to a previously specified output buffer
// Only valid to be called if the stream is in state eZDefState_AwaitingInput
// The specified buffer must remain valid (ie do not free) whilst compression is in progress (state == eZDefState_Deflating)
virtual void Input(const char* pInSource, int inSourceSize) = 0;
// Description:
// Finishes the compression, causing all data to be flushed to the output buffer
// Once called no more data can be input
// After calling the caller must wait until GetState() reutrns eZDefState_Finished
virtual void EndInput() = 0;
// Description:
// Returns the state of the stream,
virtual EZDeflateState GetState() = 0;
// Description:
// Gets stats on deflate stream, valid to call at anytime
virtual void GetStats(SStats* pOutStats) = 0;
// Description:
// Deletes the deflate stream. Will assert if stream is in an invalid state to be released (in state eZDefState_Deflating)
virtual void Release() = 0;
//
};
// md5 support structure
struct SMD5Context
{
uint32 buf[4];
uint32 bits[2];
unsigned char in[64];
};
struct IZLibCompressor
{
protected:
virtual ~IZLibCompressor() {}; // use Release()
public:
//
// Description:
// Creates a deflate stream to compress data using zlib
// See documentation for zlib deflateInit2() for usage details
// inFlushMethod is passed to calls to zlib deflate(), see zlib docs on deflate() for more details
virtual IZLibDeflateStream* CreateDeflateStream(int inLevel, EZLibMethod inMethod, int inWindowBits, int inMemLevel, EZLibStrategy inStrategy, EZLibFlush inFlushMethod) = 0;
virtual void Release() = 0;
// Description:
// Initializes an MD5 context
virtual void MD5Init(SMD5Context* pIOCtx) = 0;
// Description:
// Digests some data into an existing MD5 context
virtual void MD5Update(SMD5Context* pIOCtx, const char* pInBuff, unsigned int len) = 0;
// Description:
// Closes the MD5 context and extract the final 16 byte MD5 digest value
virtual void MD5Final(SMD5Context * pIOCtx, char outDigest[16]) = 0;
//
};
#endif // CRYINCLUDE_CRYCOMMON_IZLIBCOMPRESSOR_H