|
|
|
#ifndef CRYPTOPP_ZDEFLATE_H
|
|
|
|
#define CRYPTOPP_ZDEFLATE_H
|
|
|
|
|
|
|
|
#include "filters.h"
|
|
|
|
#include "misc.h"
|
|
|
|
|
|
|
|
NAMESPACE_BEGIN(CryptoPP)
|
|
|
|
|
|
|
|
//! _
|
|
|
|
class LowFirstBitWriter : public Filter
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
LowFirstBitWriter(BufferedTransformation *attachment);
|
|
|
|
void PutBits(unsigned long value, unsigned int length);
|
|
|
|
void FlushBitBuffer();
|
|
|
|
void ClearBitBuffer();
|
|
|
|
|
|
|
|
void StartCounting();
|
|
|
|
unsigned long FinishCounting();
|
|
|
|
|
|
|
|
protected:
|
|
|
|
bool m_counting;
|
|
|
|
unsigned long m_bitCount;
|
|
|
|
unsigned long m_buffer;
|
|
|
|
unsigned int m_bitsBuffered, m_bytesBuffered;
|
|
|
|
FixedSizeSecBlock<byte, 256> m_outputBuffer;
|
|
|
|
};
|
|
|
|
|
|
|
|
//! Huffman Encoder
|
|
|
|
class HuffmanEncoder
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef unsigned int code_t;
|
|
|
|
typedef unsigned int value_t;
|
|
|
|
|
|
|
|
HuffmanEncoder() {}
|
|
|
|
HuffmanEncoder(const unsigned int *codeBits, unsigned int nCodes);
|
|
|
|
void Initialize(const unsigned int *codeBits, unsigned int nCodes);
|
|
|
|
|
|
|
|
static void GenerateCodeLengths(unsigned int *codeBits, unsigned int maxCodeBits, const unsigned int *codeCounts, size_t nCodes);
|
|
|
|
|
|
|
|
void Encode(LowFirstBitWriter &writer, value_t value) const;
|
|
|
|
|
|
|
|
struct Code
|
|
|
|
{
|
|
|
|
unsigned int code;
|
|
|
|
unsigned int len;
|
|
|
|
};
|
|
|
|
|
|
|
|
SecBlock<Code> m_valueToCode;
|
|
|
|
};
|
|
|
|
|
|
|
|
//! DEFLATE (RFC 1951) compressor
|
|
|
|
|
|
|
|
class Deflator : public LowFirstBitWriter
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
enum {MIN_DEFLATE_LEVEL = 0, DEFAULT_DEFLATE_LEVEL = 6, MAX_DEFLATE_LEVEL = 9};
|
|
|
|
enum {MIN_LOG2_WINDOW_SIZE = 9, DEFAULT_LOG2_WINDOW_SIZE = 15, MAX_LOG2_WINDOW_SIZE = 15};
|
|
|
|
/*! \note detectUncompressible makes it faster to process uncompressible files, but
|
|
|
|
if a file has both compressible and uncompressible parts, it may fail to compress some of the
|
|
|
|
compressible parts. */
|
|
|
|
Deflator(BufferedTransformation *attachment=NULL, int deflateLevel=DEFAULT_DEFLATE_LEVEL, int log2WindowSize=DEFAULT_LOG2_WINDOW_SIZE, bool detectUncompressible=true);
|
|
|
|
//! possible parameter names: Log2WindowSize, DeflateLevel, DetectUncompressible
|
|
|
|
Deflator(const NameValuePairs ¶meters, BufferedTransformation *attachment=NULL);
|
|
|
|
|
|
|
|
//! this function can be used to set the deflate level in the middle of compression
|
|
|
|
void SetDeflateLevel(int deflateLevel);
|
|
|
|
int GetDeflateLevel() const {return m_deflateLevel;}
|
|
|
|
int GetLog2WindowSize() const {return m_log2WindowSize;}
|
|
|
|
|
|
|
|
void IsolatedInitialize(const NameValuePairs ¶meters);
|
|
|
|
size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking);
|
|
|
|
bool IsolatedFlush(bool hardFlush, bool blocking);
|
|
|
|
|
|
|
|
protected:
|
|
|
|
virtual void WritePrestreamHeader() {}
|
|
|
|
virtual void ProcessUncompressedData(const byte *string, size_t length) {}
|
|
|
|
virtual void WritePoststreamTail() {}
|
|
|
|
|
|
|
|
enum {STORED = 0, STATIC = 1, DYNAMIC = 2};
|
|
|
|
enum {MIN_MATCH = 3, MAX_MATCH = 258};
|
|
|
|
|
|
|
|
void InitializeStaticEncoders();
|
|
|
|
void Reset(bool forceReset = false);
|
|
|
|
unsigned int FillWindow(const byte *str, size_t length);
|
|
|
|
unsigned int ComputeHash(const byte *str) const;
|
|
|
|
unsigned int LongestMatch(unsigned int &bestMatch) const;
|
|
|
|
void InsertString(unsigned int start);
|
|
|
|
void ProcessBuffer();
|
|
|
|
|
|
|
|
void LiteralByte(byte b);
|
|
|
|
void MatchFound(unsigned int distance, unsigned int length);
|
|
|
|
void EncodeBlock(bool eof, unsigned int blockType);
|
|
|
|
void EndBlock(bool eof);
|
|
|
|
|
|
|
|
struct EncodedMatch
|
|
|
|
{
|
|
|
|
unsigned literalCode : 9;
|
|
|
|
unsigned literalExtra : 5;
|
|
|
|
unsigned distanceCode : 5;
|
|
|
|
unsigned distanceExtra : 13;
|
|
|
|
};
|
|
|
|
|
|
|
|
int m_deflateLevel, m_log2WindowSize, m_compressibleDeflateLevel;
|
|
|
|
unsigned int m_detectSkip, m_detectCount;
|
|
|
|
unsigned int DSIZE, DMASK, HSIZE, HMASK, GOOD_MATCH, MAX_LAZYLENGTH, MAX_CHAIN_LENGTH;
|
|
|
|
bool m_headerWritten, m_matchAvailable;
|
|
|
|
unsigned int m_dictionaryEnd, m_stringStart, m_lookahead, m_minLookahead, m_previousMatch, m_previousLength;
|
|
|
|
HuffmanEncoder m_staticLiteralEncoder, m_staticDistanceEncoder, m_dynamicLiteralEncoder, m_dynamicDistanceEncoder;
|
|
|
|
SecByteBlock m_byteBuffer;
|
|
|
|
SecBlock<word16> m_head, m_prev;
|
|
|
|
FixedSizeSecBlock<unsigned int, 286> m_literalCounts;
|
|
|
|
FixedSizeSecBlock<unsigned int, 30> m_distanceCounts;
|
|
|
|
SecBlock<EncodedMatch> m_matchBuffer;
|
|
|
|
unsigned int m_matchBufferEnd, m_blockStart, m_blockLength;
|
|
|
|
};
|
|
|
|
|
|
|
|
NAMESPACE_END
|
|
|
|
|
|
|
|
#endif
|