From 48540940b6c28bb4378abfeb500ec45a625b37b6 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Tue, 15 May 2012 10:38:20 +0000 Subject: initial commit git-svn-id: http://svn.miranda-ng.org/main/trunk@2 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/CryptoPP/crypto/zinflate.h | 149 +++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 plugins/CryptoPP/crypto/zinflate.h (limited to 'plugins/CryptoPP/crypto/zinflate.h') diff --git a/plugins/CryptoPP/crypto/zinflate.h b/plugins/CryptoPP/crypto/zinflate.h new file mode 100644 index 0000000000..4d536beb2d --- /dev/null +++ b/plugins/CryptoPP/crypto/zinflate.h @@ -0,0 +1,149 @@ +#ifndef CRYPTOPP_ZINFLATE_H +#define CRYPTOPP_ZINFLATE_H + +#include "filters.h" +#include + +NAMESPACE_BEGIN(CryptoPP) + +//! _ +class LowFirstBitReader +{ +public: + LowFirstBitReader(BufferedTransformation &store) + : m_store(store), m_buffer(0), m_bitsBuffered(0) {} +// unsigned long BitsLeft() const {return m_store.MaxRetrievable() * 8 + m_bitsBuffered;} + unsigned int BitsBuffered() const {return m_bitsBuffered;} + unsigned long PeekBuffer() const {return m_buffer;} + bool FillBuffer(unsigned int length); + unsigned long PeekBits(unsigned int length); + void SkipBits(unsigned int length); + unsigned long GetBits(unsigned int length); + +private: + BufferedTransformation &m_store; + unsigned long m_buffer; + unsigned int m_bitsBuffered; +}; + +struct CodeLessThan; + +//! Huffman Decoder +class HuffmanDecoder +{ +public: + typedef unsigned int code_t; + typedef unsigned int value_t; + enum {MAX_CODE_BITS = sizeof(code_t)*8}; + + class Err : public Exception {public: Err(const std::string &what) : Exception(INVALID_DATA_FORMAT, "HuffmanDecoder: " + what) {}}; + + HuffmanDecoder() {} + HuffmanDecoder(const unsigned int *codeBitLengths, unsigned int nCodes) {Initialize(codeBitLengths, nCodes);} + + void Initialize(const unsigned int *codeBitLengths, unsigned int nCodes); + unsigned int Decode(code_t code, /* out */ value_t &value) const; + bool Decode(LowFirstBitReader &reader, value_t &value) const; + +private: + friend struct CodeLessThan; + + struct CodeInfo + { + CodeInfo(code_t code=0, unsigned int len=0, value_t value=0) : code(code), len(len), value(value) {} + inline bool operator<(const CodeInfo &rhs) const {return code < rhs.code;} + code_t code; + unsigned int len; + value_t value; + }; + + struct LookupEntry + { + unsigned int type; + union + { + value_t value; + const CodeInfo *begin; + }; + union + { + unsigned int len; + const CodeInfo *end; + }; + }; + + static code_t NormalizeCode(code_t code, unsigned int codeBits); + void FillCacheEntry(LookupEntry &entry, code_t normalizedCode) const; + + unsigned int m_maxCodeBits, m_cacheBits, m_cacheMask, m_normalizedCacheMask; + std::vector > m_codeToValue; + mutable std::vector > m_cache; +}; + +//! DEFLATE (RFC 1951) decompressor + +class Inflator : public AutoSignaling +{ +public: + class Err : public Exception + { + public: + Err(ErrorType e, const std::string &s) + : Exception(e, s) {} + }; + class UnexpectedEndErr : public Err {public: UnexpectedEndErr() : Err(INVALID_DATA_FORMAT, "Inflator: unexpected end of compressed block") {}}; + class BadBlockErr : public Err {public: BadBlockErr() : Err(INVALID_DATA_FORMAT, "Inflator: error in compressed block") {}}; + + /*! \param repeat decompress multiple compressed streams in series + \param autoSignalPropagation 0 to turn off MessageEnd signal + */ + Inflator(BufferedTransformation *attachment = NULL, bool repeat = false, int autoSignalPropagation = -1); + + void IsolatedInitialize(const NameValuePairs ¶meters); + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking); + bool IsolatedFlush(bool hardFlush, bool blocking); + + virtual unsigned int GetLog2WindowSize() const {return 15;} + +protected: + ByteQueue m_inQueue; + +private: + virtual unsigned int MaxPrestreamHeaderSize() const {return 0;} + virtual void ProcessPrestreamHeader() {} + virtual void ProcessDecompressedData(const byte *string, size_t length) + {AttachedTransformation()->Put(string, length);} + virtual unsigned int MaxPoststreamTailSize() const {return 0;} + virtual void ProcessPoststreamTail() {} + + void ProcessInput(bool flush); + void DecodeHeader(); + bool DecodeBody(); + void FlushOutput(); + void OutputByte(byte b); + void OutputString(const byte *string, size_t length); + void OutputPast(unsigned int length, unsigned int distance); + + static const HuffmanDecoder *FixedLiteralDecoder(); + static const HuffmanDecoder *FixedDistanceDecoder(); + + const HuffmanDecoder& GetLiteralDecoder() const; + const HuffmanDecoder& GetDistanceDecoder() const; + + enum State {PRE_STREAM, WAIT_HEADER, DECODING_BODY, POST_STREAM, AFTER_END}; + State m_state; + bool m_repeat, m_eof, m_wrappedAround; + byte m_blockType; + word16 m_storedLen; + enum NextDecode {LITERAL, LENGTH_BITS, DISTANCE, DISTANCE_BITS}; + NextDecode m_nextDecode; + unsigned int m_literal, m_distance; // for LENGTH_BITS or DISTANCE_BITS + HuffmanDecoder m_dynamicLiteralDecoder, m_dynamicDistanceDecoder; + LowFirstBitReader m_reader; + SecByteBlock m_window; + size_t m_current, m_lastFlush; +}; + +NAMESPACE_END + +#endif -- cgit v1.2.3