summaryrefslogtreecommitdiffstats
path: root/src/libs/7zip/win/CPP/7zip/Compress/LzhDecoder.h
blob: ed631e20d1dfc2252a93d31fbdd96983fbf257ad (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
// LzhDecoder.h

#ifndef __COMPRESS_LZH_DECODER_H
#define __COMPRESS_LZH_DECODER_H

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

#include "../ICoder.h"

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

#include "BitmDecoder.h"
#include "HuffmanDecoder.h"
#include "LzOutWindow.h"

namespace NCompress {
namespace NLzh {
namespace NDecoder {

const int kMaxHuffmanLen = 16; // Check it

const int kNumSpecLevelSymbols = 3;
const int kNumLevelSymbols = kNumSpecLevelSymbols + kMaxHuffmanLen;

const int kDictBitsMax = 16;
const int kNumDistanceSymbols = kDictBitsMax + 1;

const int kMaxMatch = 256;
const int kMinMatch = 3;
const int kNumCSymbols = 256 + kMaxMatch + 2 - kMinMatch;

template <UInt32 m_NumSymbols>
class CHuffmanDecoder:public NCompress::NHuffman::CDecoder<kMaxHuffmanLen, m_NumSymbols>
{
public:
  int Symbol;
  template <class TBitDecoder>
  UInt32 Decode(TBitDecoder *bitStream)
  {
    if (Symbol >= 0)
      return (UInt32)Symbol;
    return DecodeSymbol(bitStream);
  }
};

class CCoder :
  public ICompressCoder,
  public CMyUnknownImp
{
  CLzOutWindow m_OutWindowStream;
  NBitm::CDecoder<CInBuffer> m_InBitStream;

  int m_NumDictBits;

  CHuffmanDecoder<kNumLevelSymbols> m_LevelHuffman;
  CHuffmanDecoder<kNumDistanceSymbols> m_PHuffmanDecoder;
  CHuffmanDecoder<kNumCSymbols> m_CHuffmanDecoder;

  void ReleaseStreams()
  {
    m_OutWindowStream.ReleaseStream();
    m_InBitStream.ReleaseStream();
  }

  class CCoderReleaser
  {
    CCoder *m_Coder;
  public:
    bool NeedFlush;
    CCoderReleaser(CCoder *coder): m_Coder(coder), NeedFlush(true) {}
    ~CCoderReleaser()
    {
      if (NeedFlush)
        m_Coder->m_OutWindowStream.Flush();
      m_Coder->ReleaseStreams();
    }
  };
  friend class CCoderReleaser;

  void MakeTable(int nchar, Byte *bitlen, int tablebits,
      UInt32 *table, int tablesize);
  
  UInt32 ReadBits(int numBits);
  HRESULT ReadLevelTable();
  HRESULT ReadPTable(int numBits);
  HRESULT ReadCTable();

public:
  
  MY_UNKNOWN_IMP

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

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

  void SetDictionary(int numDictBits) { m_NumDictBits = numDictBits; }
  CCoder(): m_NumDictBits(0) {}
};

}}}

#endif