summaryrefslogtreecommitdiffstats
path: root/src/libs/7zip/win/CPP/7zip/Compress/DeflateDecoder.h
blob: 56ab2bea266a6b16b313c74ea16632fb0850a429 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
// DeflateDecoder.h

#ifndef __DEFLATE_DECODER_H
#define __DEFLATE_DECODER_H

#include "../../Common/MyCom.h"

#include "../ICoder.h"

#include "../Common/InBuffer.h"

#include "BitlDecoder.h"
#include "DeflateConst.h"
#include "HuffmanDecoder.h"
#include "LzOutWindow.h"

namespace NCompress {
namespace NDeflate {
namespace NDecoder {

class CCoder:
  public ICompressCoder,
  public ICompressGetInStreamProcessedSize,
  #ifndef NO_READ_FROM_CODER
  public ICompressSetInStream,
  public ICompressSetOutStreamSize,
  public ISequentialInStream,
  #endif
  public CMyUnknownImp
{
  CLzOutWindow m_OutWindowStream;
  NBitl::CDecoder<CInBuffer> m_InBitStream;
  NCompress::NHuffman::CDecoder<kNumHuffmanBits, kFixedMainTableSize> m_MainDecoder;
  NCompress::NHuffman::CDecoder<kNumHuffmanBits, kFixedDistTableSize> m_DistDecoder;
  NCompress::NHuffman::CDecoder<kNumHuffmanBits, kLevelTableSize> m_LevelDecoder;

  UInt32 m_StoredBlockSize;

  bool m_FinalBlock;
  bool m_StoredMode;
  UInt32 _numDistLevels;


  bool _deflateNSIS;
  bool _deflate64Mode;
  bool _keepHistory;
  bool _needInitInStream;
  Int32 _remainLen;
  UInt32 _rep0;
  bool _needReadTable;

  UInt32 ReadBits(int numBits);

  bool DeCodeLevelTable(Byte *values, int numSymbols);
  bool ReadTables();
  
  HRESULT Flush() { return m_OutWindowStream.Flush(); }
  class CCoderReleaser
  {
    CCoder *_coder;
  public:
    bool NeedFlush;
    CCoderReleaser(CCoder *coder): _coder(coder), NeedFlush(true) {}
    ~CCoderReleaser()
    {
      if (NeedFlush)
        _coder->Flush();
      _coder->ReleaseOutStream();
    }
  };
  friend class CCoderReleaser;

  HRESULT CodeSpec(UInt32 curSize);
public:
  bool ZlibMode;
  Byte ZlibFooter[4];

  CCoder(bool deflate64Mode, bool deflateNSIS = false);
  virtual ~CCoder() {};

  void SetKeepHistory(bool keepHistory) { _keepHistory = keepHistory; }

  void ReleaseOutStream()
  {
    m_OutWindowStream.ReleaseStream();
  }

  HRESULT CodeReal(ISequentialOutStream *outStream,
      const UInt64 *outSize, ICompressProgressInfo *progress);

  #ifndef NO_READ_FROM_CODER
  MY_UNKNOWN_IMP4(
      ICompressGetInStreamProcessedSize,
      ICompressSetInStream,
      ICompressSetOutStreamSize,
      ISequentialInStream
      )
  #else
  MY_UNKNOWN_IMP1(
      ICompressGetInStreamProcessedSize)
  #endif

  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);

  STDMETHOD(SetInStream)(ISequentialInStream *inStream);
  STDMETHOD(ReleaseInStream)();
  STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
  
  #ifndef NO_READ_FROM_CODER
  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
  #endif

  STDMETHOD(CodeResume)(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress);

  HRESULT InitInStream(bool needInit)
  {
    if (!m_InBitStream.Create(1 << 17))
      return E_OUTOFMEMORY;
    if (needInit)
    {
      m_InBitStream.Init();
      _needInitInStream = false;
    }
    return S_OK;
  }

  void AlignToByte() { m_InBitStream.AlignToByte(); }
  Byte ReadByte() { return (Byte)m_InBitStream.ReadBits(8); }
  bool InputEofError() const { return m_InBitStream.ExtraBitsWereRead(); }
  UInt64 GetInputProcessedSize() const { return m_InBitStream.GetProcessedSize(); }

  // IGetInStreamProcessedSize
  STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
};

class CCOMCoder : public CCoder
{
public:
  CCOMCoder(): CCoder(false) {}
};

class CNsisCOMCoder : public CCoder
{
public:
  CNsisCOMCoder(): CCoder(false, true) {}
};

class CCOMCoder64 : public CCoder
{
public:
  CCOMCoder64(): CCoder(true) {}
};

}}}

#endif