1#ifndef CRYPTOPP_ZDEFLATE_H
2#define CRYPTOPP_ZDEFLATE_H
3
4#include "filters.h"
5#include "misc.h"
6
7NAMESPACE_BEGIN(CryptoPP)
8
9//! _
10class LowFirstBitWriter : public Filter
11{
12public:
13	LowFirstBitWriter(BufferedTransformation *attachment);
14	void PutBits(unsigned long value, unsigned int length);
15	void FlushBitBuffer();
16	void ClearBitBuffer();
17
18	void StartCounting();
19	unsigned long FinishCounting();
20
21protected:
22	bool m_counting;
23	unsigned long m_bitCount;
24	unsigned long m_buffer;
25	unsigned int m_bitsBuffered, m_bytesBuffered;
26	FixedSizeSecBlock<byte, 256> m_outputBuffer;
27};
28
29//! Huffman Encoder
30class HuffmanEncoder
31{
32public:
33	typedef unsigned int code_t;
34	typedef unsigned int value_t;
35
36	HuffmanEncoder() {}
37	HuffmanEncoder(const unsigned int *codeBits, unsigned int nCodes);
38	void Initialize(const unsigned int *codeBits, unsigned int nCodes);
39
40	static void GenerateCodeLengths(unsigned int *codeBits, unsigned int maxCodeBits, const unsigned int *codeCounts, size_t nCodes);
41
42	void Encode(LowFirstBitWriter &writer, value_t value) const;
43
44	struct Code
45	{
46		unsigned int code;
47		unsigned int len;
48	};
49
50	SecBlock<Code> m_valueToCode;
51};
52
53//! DEFLATE (RFC 1951) compressor
54
55class Deflator : public LowFirstBitWriter
56{
57public:
58	enum {MIN_DEFLATE_LEVEL = 0, DEFAULT_DEFLATE_LEVEL = 6, MAX_DEFLATE_LEVEL = 9};
59	enum {MIN_LOG2_WINDOW_SIZE = 9, DEFAULT_LOG2_WINDOW_SIZE = 15, MAX_LOG2_WINDOW_SIZE = 15};
60	/*! \note detectUncompressible makes it faster to process uncompressible files, but
61		if a file has both compressible and uncompressible parts, it may fail to compress some of the
62		compressible parts. */
63	Deflator(BufferedTransformation *attachment=NULL, int deflateLevel=DEFAULT_DEFLATE_LEVEL, int log2WindowSize=DEFAULT_LOG2_WINDOW_SIZE, bool detectUncompressible=true);
64	//! possible parameter names: Log2WindowSize, DeflateLevel, DetectUncompressible
65	Deflator(const NameValuePairs &parameters, BufferedTransformation *attachment=NULL);
66
67	//! this function can be used to set the deflate level in the middle of compression
68	void SetDeflateLevel(int deflateLevel);
69	int GetDeflateLevel() const {return m_deflateLevel;}
70	int GetLog2WindowSize() const {return m_log2WindowSize;}
71
72	void IsolatedInitialize(const NameValuePairs &parameters);
73	size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking);
74	bool IsolatedFlush(bool hardFlush, bool blocking);
75
76protected:
77	virtual void WritePrestreamHeader() {}
78	virtual void ProcessUncompressedData(const byte *string, size_t length) {}
79	virtual void WritePoststreamTail() {}
80
81	enum {STORED = 0, STATIC = 1, DYNAMIC = 2};
82	enum {MIN_MATCH = 3, MAX_MATCH = 258};
83
84	void InitializeStaticEncoders();
85	void Reset(bool forceReset = false);
86	unsigned int FillWindow(const byte *str, size_t length);
87	unsigned int ComputeHash(const byte *str) const;
88	unsigned int LongestMatch(unsigned int &bestMatch) const;
89	void InsertString(unsigned int start);
90	void ProcessBuffer();
91
92	void LiteralByte(byte b);
93	void MatchFound(unsigned int distance, unsigned int length);
94	void EncodeBlock(bool eof, unsigned int blockType);
95	void EndBlock(bool eof);
96
97	struct EncodedMatch
98	{
99		unsigned literalCode : 9;
100		unsigned literalExtra : 5;
101		unsigned distanceCode : 5;
102		unsigned distanceExtra : 13;
103	};
104
105	int m_deflateLevel, m_log2WindowSize, m_compressibleDeflateLevel;
106	unsigned int m_detectSkip, m_detectCount;
107	unsigned int DSIZE, DMASK, HSIZE, HMASK, GOOD_MATCH, MAX_LAZYLENGTH, MAX_CHAIN_LENGTH;
108	bool m_headerWritten, m_matchAvailable;
109	unsigned int m_dictionaryEnd, m_stringStart, m_lookahead, m_minLookahead, m_previousMatch, m_previousLength;
110	HuffmanEncoder m_staticLiteralEncoder, m_staticDistanceEncoder, m_dynamicLiteralEncoder, m_dynamicDistanceEncoder;
111	SecByteBlock m_byteBuffer;
112	SecBlock<word16> m_head, m_prev;
113	FixedSizeSecBlock<unsigned int, 286> m_literalCounts;
114	FixedSizeSecBlock<unsigned int, 30> m_distanceCounts;
115	SecBlock<EncodedMatch> m_matchBuffer;
116	unsigned int m_matchBufferEnd, m_blockStart, m_blockLength;
117};
118
119NAMESPACE_END
120
121#endif
122