Welcome to mirror list, hosted at ThFree Co, Russian Federation.

QuantumDecoder.h « Compress « 7zip « CPP - github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: afeba70880d88e50a59c9399f8a3cfb28f75a31a (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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
// QuantumDecoder.h

#ifndef __COMPRESS_QUANTUM_DECODER_H
#define __COMPRESS_QUANTUM_DECODER_H

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

#include "LzOutWindow.h"

namespace NCompress {
namespace NQuantum {

class CBitDecoder
{
  UInt32 Value;
  bool _extra;
  const Byte *_buf;
  const Byte *_bufLim;
public:
  void SetStreamAndInit(const Byte *inData, size_t inSize)
  {
    _buf = inData;
    _bufLim = inData + inSize;
    Value = 0x10000;
    _extra = false;
  }

  bool WasExtraRead() const { return _extra; }

  bool WasFinishedOK() const
  {
    return !_extra && _buf == _bufLim;
  }
  
  UInt32 ReadBit()
  {
    if (Value >= 0x10000)
    {
      Byte b;
      if (_buf >= _bufLim)
      {
        b = 0xFF;
        _extra = true;
      }
      else
        b = *_buf++;
      Value = 0x100 | b;
    }
    UInt32 res = (Value >> 7) & 1;
    Value <<= 1;
    return res;
  }

  UInt32 ReadStart16Bits()
  {
    // we use check for extra read in another code.
    UInt32 val = ((UInt32)*_buf << 8) | _buf[1];
    _buf += 2;
    return val;
  }

  UInt32 ReadBits(unsigned numBits) // numBits > 0
  {
    UInt32 res = 0;
    do
      res = (res << 1) | ReadBit();
    while (--numBits);
    return res;
  }
};


class CRangeDecoder
{
  UInt32 Low;
  UInt32 Range;
  UInt32 Code;
public:
  CBitDecoder Stream;

  void Init()
  {
    Low = 0;
    Range = 0x10000;
    Code = Stream.ReadStart16Bits();
  }

  bool Finish()
  {
    // do all streams use these two bits at end?
    if (Stream.ReadBit() != 0) return false;
    if (Stream.ReadBit() != 0) return false;
    return Stream.WasFinishedOK();
  }

  UInt32 GetThreshold(UInt32 total) const
  {
    return ((Code + 1) * total - 1) / Range; // & 0xFFFF is not required;
  }

  void Decode(UInt32 start, UInt32 end, UInt32 total)
  {
    UInt32 high = Low + end * Range / total - 1;
    UInt32 offset = start * Range / total;
    Code -= offset;
    Low += offset;
    for (;;)
    {
      if ((Low & 0x8000) != (high & 0x8000))
      {
        if ((Low & 0x4000) == 0 || (high & 0x4000) != 0)
          break;
        Low &= 0x3FFF;
        high |= 0x4000;
      }
      Low = (Low << 1) & 0xFFFF;
      high = ((high << 1) | 1) & 0xFFFF;
      Code = ((Code << 1) | Stream.ReadBit());
    }
    Range = high - Low + 1;
  }
};


const unsigned kNumLitSelectorBits = 2;
const unsigned kNumLitSelectors = (1 << kNumLitSelectorBits);
const unsigned kNumLitSymbols = 1 << (8 - kNumLitSelectorBits);
const unsigned kNumMatchSelectors = 3;
const unsigned kNumSelectors = kNumLitSelectors + kNumMatchSelectors;
const unsigned kNumSymbolsMax = kNumLitSymbols; // 64


class CModelDecoder
{
  unsigned NumItems;
  unsigned ReorderCount;
  UInt16 Freqs[kNumSymbolsMax + 1];
  Byte Vals[kNumSymbolsMax];
public:
  void Init(unsigned numItems);
  unsigned Decode(CRangeDecoder *rc);
};


class CDecoder:
  public IUnknown,
  public CMyUnknownImp
{
  CLzOutWindow _outWindow;
  unsigned _numDictBits;

  CModelDecoder m_Selector;
  CModelDecoder m_Literals[kNumLitSelectors];
  CModelDecoder m_PosSlot[kNumMatchSelectors];
  CModelDecoder m_LenSlot;

  void Init();
  HRESULT CodeSpec(const Byte *inData, size_t inSize, UInt32 outSize);
public:

  MY_UNKNOWN_IMP

  HRESULT Code(const Byte *inData, size_t inSize,
      ISequentialOutStream *outStream, UInt32 outSize,
      bool keepHistory);

  HRESULT SetParams(unsigned numDictBits);
  
  CDecoder(): _numDictBits(0) {}
  virtual ~CDecoder() {}
};

}}

#endif