ruby-lzma 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. data/.gitignore +6 -0
  2. data/README.markdown +15 -0
  3. data/Rakefile +53 -0
  4. data/VERSION +1 -0
  5. data/ext/Alloc.cpp +118 -0
  6. data/ext/Alloc.h +29 -0
  7. data/ext/BinTree.h +55 -0
  8. data/ext/BinTree2.h +12 -0
  9. data/ext/BinTree3.h +16 -0
  10. data/ext/BinTree3Z.h +16 -0
  11. data/ext/BinTree4.h +18 -0
  12. data/ext/BinTree4b.h +20 -0
  13. data/ext/BinTreeMain.h +444 -0
  14. data/ext/BranchX86.c +101 -0
  15. data/ext/BranchX86.h +19 -0
  16. data/ext/CRC.cpp +61 -0
  17. data/ext/CRC.h +36 -0
  18. data/ext/C_FileIO.h +45 -0
  19. data/ext/CommandLineParser.h +82 -0
  20. data/ext/Defs.h +20 -0
  21. data/ext/FileStreams.h +98 -0
  22. data/ext/HC.h +55 -0
  23. data/ext/HC2.h +13 -0
  24. data/ext/HC3.h +17 -0
  25. data/ext/HC4.h +19 -0
  26. data/ext/HC4b.h +21 -0
  27. data/ext/HCMain.h +350 -0
  28. data/ext/ICoder.h +156 -0
  29. data/ext/IMatchFinder.h +63 -0
  30. data/ext/IStream.h +62 -0
  31. data/ext/InBuffer.cpp +80 -0
  32. data/ext/InBuffer.h +76 -0
  33. data/ext/LZInWindow.cpp +102 -0
  34. data/ext/LZInWindow.h +84 -0
  35. data/ext/LZMA.h +82 -0
  36. data/ext/LZMADecoder.h +248 -0
  37. data/ext/LZMAEncoder.cpp +1504 -0
  38. data/ext/LZMAEncoder.h +416 -0
  39. data/ext/LZOutWindow.cpp +17 -0
  40. data/ext/LZOutWindow.h +66 -0
  41. data/ext/LzmaBench.h +11 -0
  42. data/ext/LzmaDecode.c +588 -0
  43. data/ext/LzmaDecode.h +131 -0
  44. data/ext/LzmaRam.cpp +228 -0
  45. data/ext/LzmaRam.h +46 -0
  46. data/ext/LzmaRamDecode.c +79 -0
  47. data/ext/LzmaRamDecode.h +55 -0
  48. data/ext/MyCom.h +203 -0
  49. data/ext/MyGuidDef.h +54 -0
  50. data/ext/MyInitGuid.h +13 -0
  51. data/ext/MyString.h +631 -0
  52. data/ext/MyUnknown.h +24 -0
  53. data/ext/MyWindows.h +183 -0
  54. data/ext/OutBuffer.cpp +117 -0
  55. data/ext/OutBuffer.h +64 -0
  56. data/ext/Pat.h +318 -0
  57. data/ext/Pat2.h +22 -0
  58. data/ext/Pat2H.h +24 -0
  59. data/ext/Pat2R.h +20 -0
  60. data/ext/Pat3H.h +24 -0
  61. data/ext/Pat4H.h +24 -0
  62. data/ext/PatMain.h +989 -0
  63. data/ext/RangeCoder.h +205 -0
  64. data/ext/RangeCoderBit.cpp +80 -0
  65. data/ext/RangeCoderBit.h +120 -0
  66. data/ext/RangeCoderBitTree.h +161 -0
  67. data/ext/RangeCoderOpt.h +31 -0
  68. data/ext/StdAfx.h +8 -0
  69. data/ext/StreamUtils.cpp +44 -0
  70. data/ext/StreamUtils.h +11 -0
  71. data/ext/StringConvert.h +71 -0
  72. data/ext/StringToInt.h +17 -0
  73. data/ext/Types.h +19 -0
  74. data/ext/Vector.h +211 -0
  75. data/ext/extconf.rb +7 -0
  76. data/ext/lzma_ruby.cpp +51 -0
  77. data/ext/lzmalib.h +64 -0
  78. data/ext/mylib.cpp +81 -0
  79. data/java/SevenZip/CRC.java +52 -0
  80. data/java/SevenZip/Compression/LZ/BinTree.java +382 -0
  81. data/java/SevenZip/Compression/LZ/InWindow.java +131 -0
  82. data/java/SevenZip/Compression/LZ/OutWindow.java +85 -0
  83. data/java/SevenZip/Compression/LZMA/Base.java +88 -0
  84. data/java/SevenZip/Compression/LZMA/Decoder.java +329 -0
  85. data/java/SevenZip/Compression/LZMA/Encoder.java +1415 -0
  86. data/java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java +55 -0
  87. data/java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java +99 -0
  88. data/java/SevenZip/Compression/RangeCoder/Decoder.java +88 -0
  89. data/java/SevenZip/Compression/RangeCoder/Encoder.java +151 -0
  90. data/java/SevenZip/ICodeProgress.java +6 -0
  91. data/java/SevenZip/LzmaAlone.java +253 -0
  92. data/java/SevenZip/LzmaBench.java +391 -0
  93. data/java/com/ephemeronindustries/lzma/LZMA.java +104 -0
  94. data/lib/lzma.rb +32 -0
  95. data/ruby-lzma.gemspec +136 -0
  96. data/test/test_lzma.rb +42 -0
  97. metadata +157 -0
data/ext/LZInWindow.h ADDED
@@ -0,0 +1,84 @@
1
+ // LZInWindow.h
2
+
3
+ #ifndef __LZ_IN_WINDOW_H
4
+ #define __LZ_IN_WINDOW_H
5
+
6
+ #include "IStream.h"
7
+
8
+ class CLZInWindow
9
+ {
10
+ Byte *_bufferBase; // pointer to buffer with data
11
+ ISequentialInStream *_stream;
12
+ UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done
13
+ bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream
14
+ const Byte *_pointerToLastSafePosition;
15
+ protected:
16
+ Byte *_buffer; // Pointer to virtual Buffer begin
17
+ UInt32 _blockSize; // Size of Allocated memory block
18
+ UInt32 _pos; // offset (from _buffer) of curent byte
19
+ UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos
20
+ UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos
21
+ UInt32 _keepSizeReserv; // how many BYTEs must be kept as reserv
22
+ UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream
23
+
24
+ virtual void BeforeMoveBlock() {};
25
+ virtual void AfterMoveBlock() {};
26
+ void MoveBlock();
27
+ virtual HRESULT ReadBlock();
28
+ void Free();
29
+ public:
30
+ CLZInWindow(): _bufferBase(0) {}
31
+ virtual ~CLZInWindow() { Free(); }
32
+
33
+ bool Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter,
34
+ UInt32 keepSizeReserv = (1<<17));
35
+
36
+ HRESULT Init(ISequentialInStream *stream);
37
+ // void ReleaseStream();
38
+
39
+ Byte *GetBuffer() const { return _buffer; }
40
+
41
+ const Byte *GetPointerToCurrentPos() const { return _buffer + _pos; }
42
+
43
+ HRESULT MovePos()
44
+ {
45
+ _pos++;
46
+ if (_pos > _posLimit)
47
+ {
48
+ const Byte *pointerToPostion = _buffer + _pos;
49
+ if(pointerToPostion > _pointerToLastSafePosition)
50
+ MoveBlock();
51
+ return ReadBlock();
52
+ }
53
+ else
54
+ return S_OK;
55
+ }
56
+ Byte GetIndexByte(Int32 index)const
57
+ { return _buffer[(size_t)_pos + index]; }
58
+
59
+ // index + limit have not to exceed _keepSizeAfter;
60
+ UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) const
61
+ {
62
+ if(_streamEndWasReached)
63
+ if ((_pos + index) + limit > _streamPos)
64
+ limit = _streamPos - (_pos + index);
65
+ distance++;
66
+ Byte *pby = _buffer + (size_t)_pos + index;
67
+ UInt32 i;
68
+ for(i = 0; i < limit && pby[i] == pby[(size_t)i - distance]; i++);
69
+ return i;
70
+ }
71
+
72
+ UInt32 GetNumAvailableBytes() const { return _streamPos - _pos; }
73
+
74
+ void ReduceOffsets(Int32 subValue)
75
+ {
76
+ _buffer += subValue;
77
+ _posLimit -= subValue;
78
+ _pos -= subValue;
79
+ _streamPos -= subValue;
80
+ }
81
+
82
+ };
83
+
84
+ #endif
data/ext/LZMA.h ADDED
@@ -0,0 +1,82 @@
1
+ // LZMA.h
2
+
3
+ #ifndef __LZMA_H
4
+ #define __LZMA_H
5
+
6
+ namespace NCompress {
7
+ namespace NLZMA {
8
+
9
+ const UInt32 kNumRepDistances = 4;
10
+
11
+ const int kNumStates = 12;
12
+
13
+ const Byte kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5};
14
+ const Byte kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
15
+ const Byte kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
16
+ const Byte kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
17
+
18
+ class CState
19
+ {
20
+ public:
21
+ Byte Index;
22
+ void Init() { Index = 0; }
23
+ void UpdateChar() { Index = kLiteralNextStates[Index]; }
24
+ void UpdateMatch() { Index = kMatchNextStates[Index]; }
25
+ void UpdateRep() { Index = kRepNextStates[Index]; }
26
+ void UpdateShortRep() { Index = kShortRepNextStates[Index]; }
27
+ bool IsCharState() const { return Index < 7; }
28
+ };
29
+
30
+ const int kNumPosSlotBits = 6;
31
+ const int kDicLogSizeMin = 0;
32
+ const int kDicLogSizeMax = 32;
33
+ const int kDistTableSizeMax = kDicLogSizeMax * 2;
34
+
35
+ const UInt32 kNumLenToPosStates = 4;
36
+
37
+ inline UInt32 GetLenToPosState(UInt32 len)
38
+ {
39
+ len -= 2;
40
+ if (len < kNumLenToPosStates)
41
+ return len;
42
+ return kNumLenToPosStates - 1;
43
+ }
44
+
45
+ namespace NLength {
46
+
47
+ const int kNumPosStatesBitsMax = 4;
48
+ const UInt32 kNumPosStatesMax = (1 << kNumPosStatesBitsMax);
49
+
50
+ const int kNumPosStatesBitsEncodingMax = 4;
51
+ const UInt32 kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax);
52
+
53
+ const int kNumLowBits = 3;
54
+ const int kNumMidBits = 3;
55
+ const int kNumHighBits = 8;
56
+ const UInt32 kNumLowSymbols = 1 << kNumLowBits;
57
+ const UInt32 kNumMidSymbols = 1 << kNumMidBits;
58
+ const UInt32 kNumSymbolsTotal = kNumLowSymbols + kNumMidSymbols + (1 << kNumHighBits);
59
+
60
+ }
61
+
62
+ const UInt32 kMatchMinLen = 2;
63
+ const UInt32 kMatchMaxLen = kMatchMinLen + NLength::kNumSymbolsTotal - 1;
64
+
65
+ const int kNumAlignBits = 4;
66
+ const UInt32 kAlignTableSize = 1 << kNumAlignBits;
67
+ const UInt32 kAlignMask = (kAlignTableSize - 1);
68
+
69
+ const UInt32 kStartPosModelIndex = 4;
70
+ const UInt32 kEndPosModelIndex = 14;
71
+ const UInt32 kNumPosModels = kEndPosModelIndex - kStartPosModelIndex;
72
+
73
+ const UInt32 kNumFullDistances = 1 << (kEndPosModelIndex / 2);
74
+
75
+ const int kNumLitPosStatesBitsEncodingMax = 4;
76
+ const int kNumLitContextBitsMax = 8;
77
+
78
+ const int kNumMoveBits = 5;
79
+
80
+ }}
81
+
82
+ #endif
data/ext/LZMADecoder.h ADDED
@@ -0,0 +1,248 @@
1
+ // LZMA/Decoder.h
2
+
3
+ #ifndef __LZMA_DECODER_H
4
+ #define __LZMA_DECODER_H
5
+
6
+ #include "MyCom.h"
7
+ #include "Alloc.h"
8
+ #include "ICoder.h"
9
+ #include "LZOutWindow.h"
10
+ #include "RangeCoderBitTree.h"
11
+
12
+ #include "LZMA.h"
13
+
14
+ namespace NCompress {
15
+ namespace NLZMA {
16
+
17
+ typedef NRangeCoder::CBitDecoder<kNumMoveBits> CMyBitDecoder;
18
+
19
+ class CLiteralDecoder2
20
+ {
21
+ CMyBitDecoder _decoders[0x300];
22
+ public:
23
+ void Init()
24
+ {
25
+ for (int i = 0; i < 0x300; i++)
26
+ _decoders[i].Init();
27
+ }
28
+ Byte DecodeNormal(NRangeCoder::CDecoder *rangeDecoder)
29
+ {
30
+ UInt32 symbol = 1;
31
+ RC_INIT_VAR
32
+ do
33
+ {
34
+ // symbol = (symbol << 1) | _decoders[0][symbol].Decode(rangeDecoder);
35
+ RC_GETBIT(kNumMoveBits, _decoders[symbol].Prob, symbol)
36
+ }
37
+ while (symbol < 0x100);
38
+ RC_FLUSH_VAR
39
+ return (Byte)symbol;
40
+ }
41
+ Byte DecodeWithMatchByte(NRangeCoder::CDecoder *rangeDecoder, Byte matchByte)
42
+ {
43
+ UInt32 symbol = 1;
44
+ RC_INIT_VAR
45
+ do
46
+ {
47
+ UInt32 matchBit = (matchByte >> 7) & 1;
48
+ matchByte <<= 1;
49
+ // UInt32 bit = _decoders[1 + matchBit][symbol].Decode(rangeDecoder);
50
+ // symbol = (symbol << 1) | bit;
51
+ UInt32 bit;
52
+ RC_GETBIT2(kNumMoveBits, _decoders[0x100 + (matchBit << 8) + symbol].Prob, symbol,
53
+ bit = 0, bit = 1)
54
+ if (matchBit != bit)
55
+ {
56
+ while (symbol < 0x100)
57
+ {
58
+ // symbol = (symbol << 1) | _decoders[0][symbol].Decode(rangeDecoder);
59
+ RC_GETBIT(kNumMoveBits, _decoders[symbol].Prob, symbol)
60
+ }
61
+ break;
62
+ }
63
+ }
64
+ while (symbol < 0x100);
65
+ RC_FLUSH_VAR
66
+ return (Byte)symbol;
67
+ }
68
+ };
69
+
70
+ class CLiteralDecoder
71
+ {
72
+ CLiteralDecoder2 *_coders;
73
+ int _numPrevBits;
74
+ int _numPosBits;
75
+ UInt32 _posMask;
76
+ public:
77
+ CLiteralDecoder(): _coders(0) {}
78
+ ~CLiteralDecoder() { Free(); }
79
+ void Free()
80
+ {
81
+ MyFree(_coders);
82
+ _coders = 0;
83
+ }
84
+ bool Create(int numPosBits, int numPrevBits)
85
+ {
86
+ if (_coders == 0 || (numPosBits + numPrevBits) !=
87
+ (_numPrevBits + _numPosBits) )
88
+ {
89
+ Free();
90
+ UInt32 numStates = 1 << (numPosBits + numPrevBits);
91
+ _coders = (CLiteralDecoder2 *)MyAlloc(numStates * sizeof(CLiteralDecoder2));
92
+ }
93
+ _numPosBits = numPosBits;
94
+ _posMask = (1 << numPosBits) - 1;
95
+ _numPrevBits = numPrevBits;
96
+ return (_coders != 0);
97
+ }
98
+ void Init()
99
+ {
100
+ UInt32 numStates = 1 << (_numPrevBits + _numPosBits);
101
+ for (UInt32 i = 0; i < numStates; i++)
102
+ _coders[i].Init();
103
+ }
104
+ UInt32 GetState(UInt32 pos, Byte prevByte) const
105
+ { return ((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits)); }
106
+ Byte DecodeNormal(NRangeCoder::CDecoder *rangeDecoder, UInt32 pos, Byte prevByte)
107
+ { return _coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); }
108
+ Byte DecodeWithMatchByte(NRangeCoder::CDecoder *rangeDecoder, UInt32 pos, Byte prevByte, Byte matchByte)
109
+ { return _coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); }
110
+ };
111
+
112
+ namespace NLength {
113
+
114
+ class CDecoder
115
+ {
116
+ CMyBitDecoder _choice;
117
+ CMyBitDecoder _choice2;
118
+ NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumLowBits> _lowCoder[kNumPosStatesMax];
119
+ NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumMidBits> _midCoder[kNumPosStatesMax];
120
+ NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumHighBits> _highCoder;
121
+ public:
122
+ void Init(UInt32 numPosStates)
123
+ {
124
+ _choice.Init();
125
+ _choice2.Init();
126
+ for (UInt32 posState = 0; posState < numPosStates; posState++)
127
+ {
128
+ _lowCoder[posState].Init();
129
+ _midCoder[posState].Init();
130
+ }
131
+ _highCoder.Init();
132
+ }
133
+ UInt32 Decode(NRangeCoder::CDecoder *rangeDecoder, UInt32 posState)
134
+ {
135
+ if(_choice.Decode(rangeDecoder) == 0)
136
+ return _lowCoder[posState].Decode(rangeDecoder);
137
+ if(_choice2.Decode(rangeDecoder) == 0)
138
+ return kNumLowSymbols + _midCoder[posState].Decode(rangeDecoder);
139
+ return kNumLowSymbols + kNumMidSymbols + _highCoder.Decode(rangeDecoder);
140
+ }
141
+ };
142
+
143
+ }
144
+
145
+ class CDecoder:
146
+ public ICompressCoder,
147
+ public ICompressSetDecoderProperties2,
148
+ #ifdef _ST_MODE
149
+ public ICompressSetInStream,
150
+ public ICompressSetOutStreamSize,
151
+ public ISequentialInStream,
152
+ #endif
153
+ public CMyUnknownImp
154
+ {
155
+ CLZOutWindow _outWindowStream;
156
+ NRangeCoder::CDecoder _rangeDecoder;
157
+
158
+ CMyBitDecoder _isMatch[kNumStates][NLength::kNumPosStatesMax];
159
+ CMyBitDecoder _isRep[kNumStates];
160
+ CMyBitDecoder _isRepG0[kNumStates];
161
+ CMyBitDecoder _isRepG1[kNumStates];
162
+ CMyBitDecoder _isRepG2[kNumStates];
163
+ CMyBitDecoder _isRep0Long[kNumStates][NLength::kNumPosStatesMax];
164
+
165
+ NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumPosSlotBits> _posSlotDecoder[kNumLenToPosStates];
166
+
167
+ CMyBitDecoder _posDecoders[kNumFullDistances - kEndPosModelIndex];
168
+ NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumAlignBits> _posAlignDecoder;
169
+
170
+ NLength::CDecoder _lenDecoder;
171
+ NLength::CDecoder _repMatchLenDecoder;
172
+
173
+ CLiteralDecoder _literalDecoder;
174
+
175
+ UInt32 _posStateMask;
176
+
177
+ ///////////////////
178
+ // State
179
+ UInt32 _reps[4];
180
+ CState _state;
181
+ Int32 _remainLen; // -1 means end of stream. // -2 means need Init
182
+ UInt64 _outSize;
183
+ bool _outSizeDefined;
184
+
185
+ void Init();
186
+ HRESULT CodeSpec(UInt32 size);
187
+ public:
188
+
189
+ #ifdef _ST_MODE
190
+ MY_UNKNOWN_IMP4(
191
+ ICompressSetDecoderProperties2,
192
+ ICompressSetInStream,
193
+ ICompressSetOutStreamSize,
194
+ ISequentialInStream)
195
+ #else
196
+ MY_UNKNOWN_IMP1(
197
+ ICompressSetDecoderProperties2)
198
+ #endif
199
+
200
+ void ReleaseStreams()
201
+ {
202
+ _outWindowStream.ReleaseStream();
203
+ ReleaseInStream();
204
+ }
205
+
206
+ class CDecoderFlusher
207
+ {
208
+ CDecoder *_decoder;
209
+ public:
210
+ bool NeedFlush;
211
+ CDecoderFlusher(CDecoder *decoder): _decoder(decoder), NeedFlush(true) {}
212
+ ~CDecoderFlusher()
213
+ {
214
+ if (NeedFlush)
215
+ _decoder->Flush();
216
+ _decoder->ReleaseStreams();
217
+ }
218
+ };
219
+
220
+ HRESULT Flush() { return _outWindowStream.Flush(); }
221
+
222
+ STDMETHOD(CodeReal)(ISequentialInStream *inStream,
223
+ ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
224
+ ICompressProgressInfo *progress);
225
+
226
+ STDMETHOD(Code)(ISequentialInStream *inStream,
227
+ ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
228
+ ICompressProgressInfo *progress);
229
+
230
+ STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
231
+
232
+ STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
233
+
234
+ STDMETHOD(SetInStream)(ISequentialInStream *inStream);
235
+ STDMETHOD(ReleaseInStream)();
236
+ STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
237
+
238
+ #ifdef _ST_MODE
239
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
240
+ #endif
241
+
242
+ CDecoder(): _outSizeDefined(false) {}
243
+ virtual ~CDecoder() {}
244
+ };
245
+
246
+ }}
247
+
248
+ #endif
@@ -0,0 +1,1504 @@
1
+ // LZMA/Encoder.cpp
2
+
3
+ #include "StdAfx.h"
4
+
5
+ #include "Defs.h"
6
+ #include "StreamUtils.h"
7
+
8
+ #include "LZMAEncoder.h"
9
+
10
+ // for minimal compressing code size define these:
11
+ // #define COMPRESS_MF_BT
12
+ // #define COMPRESS_MF_BT4
13
+
14
+ #if !defined(COMPRESS_MF_BT) && !defined(COMPRESS_MF_PAT) && !defined(COMPRESS_MF_HC)
15
+ #define COMPRESS_MF_BT
16
+ #define COMPRESS_MF_PAT
17
+ #define COMPRESS_MF_HC
18
+ #endif
19
+
20
+ #ifdef COMPRESS_MF_BT
21
+ #if !defined(COMPRESS_MF_BT2) && !defined(COMPRESS_MF_BT3) && !defined(COMPRESS_MF_BT4) && !defined(COMPRESS_MF_BT4B)
22
+ #define COMPRESS_MF_BT2
23
+ #define COMPRESS_MF_BT3
24
+ #define COMPRESS_MF_BT4
25
+ #define COMPRESS_MF_BT4B
26
+ #endif
27
+ #ifdef COMPRESS_MF_BT2
28
+ #include "BinTree2.h"
29
+ #endif
30
+ #ifdef COMPRESS_MF_BT3
31
+ #include "BinTree3.h"
32
+ #endif
33
+ #ifdef COMPRESS_MF_BT4
34
+ #include "BinTree4.h"
35
+ #endif
36
+ #ifdef COMPRESS_MF_BT4B
37
+ #include "BinTree4b.h"
38
+ #endif
39
+ #endif
40
+
41
+ #ifdef COMPRESS_MF_PAT
42
+ #include "Pat2.h"
43
+ #include "Pat2H.h"
44
+ #include "Pat3H.h"
45
+ #include "Pat4H.h"
46
+ #include "Pat2R.h"
47
+ #endif
48
+
49
+ #ifdef COMPRESS_MF_HC
50
+ #include "HC3.h"
51
+ #include "HC4.h"
52
+ #endif
53
+
54
+ #ifdef COMPRESS_MF_MT
55
+ #include "MT.h"
56
+ #endif
57
+
58
+ namespace NCompress {
59
+ namespace NLZMA {
60
+
61
+ const int kDefaultDictionaryLogSize = 22;
62
+ const UInt32 kNumFastBytesDefault = 0x20;
63
+
64
+ enum
65
+ {
66
+ kBT2,
67
+ kBT3,
68
+ kBT4,
69
+ kBT4B,
70
+ kPat2,
71
+ kPat2H,
72
+ kPat3H,
73
+ kPat4H,
74
+ kPat2R,
75
+ kHC3,
76
+ kHC4
77
+ };
78
+
79
+ static const wchar_t *kMatchFinderIDs[] =
80
+ {
81
+ L"BT2",
82
+ L"BT3",
83
+ L"BT4",
84
+ L"BT4B",
85
+ L"PAT2",
86
+ L"PAT2H",
87
+ L"PAT3H",
88
+ L"PAT4H",
89
+ L"PAT2R",
90
+ L"HC3",
91
+ L"HC4"
92
+ };
93
+
94
+ Byte g_FastPos[1024];
95
+
96
+ class CFastPosInit
97
+ {
98
+ public:
99
+ CFastPosInit() { Init(); }
100
+ void Init()
101
+ {
102
+ const Byte kFastSlots = 20;
103
+ int c = 2;
104
+ g_FastPos[0] = 0;
105
+ g_FastPos[1] = 1;
106
+
107
+ for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++)
108
+ {
109
+ UInt32 k = (1 << ((slotFast >> 1) - 1));
110
+ for (UInt32 j = 0; j < k; j++, c++)
111
+ g_FastPos[c] = slotFast;
112
+ }
113
+ }
114
+ } g_FastPosInit;
115
+
116
+
117
+ void CLiteralEncoder2::Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol)
118
+ {
119
+ UInt32 context = 1;
120
+ int i = 8;
121
+ do
122
+ {
123
+ i--;
124
+ UInt32 bit = (symbol >> i) & 1;
125
+ _encoders[context].Encode(rangeEncoder, bit);
126
+ context = (context << 1) | bit;
127
+ }
128
+ while(i != 0);
129
+ }
130
+
131
+ void CLiteralEncoder2::EncodeMatched(NRangeCoder::CEncoder *rangeEncoder,
132
+ Byte matchByte, Byte symbol)
133
+ {
134
+ UInt32 context = 1;
135
+ int i = 8;
136
+ do
137
+ {
138
+ i--;
139
+ UInt32 bit = (symbol >> i) & 1;
140
+ UInt32 matchBit = (matchByte >> i) & 1;
141
+ _encoders[0x100 + (matchBit << 8) + context].Encode(rangeEncoder, bit);
142
+ context = (context << 1) | bit;
143
+ if (matchBit != bit)
144
+ {
145
+ while(i != 0)
146
+ {
147
+ i--;
148
+ UInt32 bit = (symbol >> i) & 1;
149
+ _encoders[context].Encode(rangeEncoder, bit);
150
+ context = (context << 1) | bit;
151
+ }
152
+ break;
153
+ }
154
+ }
155
+ while(i != 0);
156
+ }
157
+
158
+ UInt32 CLiteralEncoder2::GetPrice(bool matchMode, Byte matchByte, Byte symbol) const
159
+ {
160
+ UInt32 price = 0;
161
+ UInt32 context = 1;
162
+ int i = 8;
163
+ if (matchMode)
164
+ {
165
+ do
166
+ {
167
+ i--;
168
+ UInt32 matchBit = (matchByte >> i) & 1;
169
+ UInt32 bit = (symbol >> i) & 1;
170
+ price += _encoders[0x100 + (matchBit << 8) + context].GetPrice(bit);
171
+ context = (context << 1) | bit;
172
+ if (matchBit != bit)
173
+ break;
174
+ }
175
+ while (i != 0);
176
+ }
177
+ while(i != 0)
178
+ {
179
+ i--;
180
+ UInt32 bit = (symbol >> i) & 1;
181
+ price += _encoders[context].GetPrice(bit);
182
+ context = (context << 1) | bit;
183
+ }
184
+ return price;
185
+ };
186
+
187
+
188
+ namespace NLength {
189
+
190
+ void CEncoder::Init(UInt32 numPosStates)
191
+ {
192
+ _choice.Init();
193
+ _choice2.Init();
194
+ for (UInt32 posState = 0; posState < numPosStates; posState++)
195
+ {
196
+ _lowCoder[posState].Init();
197
+ _midCoder[posState].Init();
198
+ }
199
+ _highCoder.Init();
200
+ }
201
+
202
+ void CEncoder::Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState)
203
+ {
204
+ if(symbol < kNumLowSymbols)
205
+ {
206
+ _choice.Encode(rangeEncoder, 0);
207
+ _lowCoder[posState].Encode(rangeEncoder, symbol);
208
+ }
209
+ else
210
+ {
211
+ _choice.Encode(rangeEncoder, 1);
212
+ if(symbol < kNumLowSymbols + kNumMidSymbols)
213
+ {
214
+ _choice2.Encode(rangeEncoder, 0);
215
+ _midCoder[posState].Encode(rangeEncoder, symbol - kNumLowSymbols);
216
+ }
217
+ else
218
+ {
219
+ _choice2.Encode(rangeEncoder, 1);
220
+ _highCoder.Encode(rangeEncoder, symbol - kNumLowSymbols - kNumMidSymbols);
221
+ }
222
+ }
223
+ }
224
+
225
+ UInt32 CEncoder::GetPrice(UInt32 symbol, UInt32 posState) const
226
+ {
227
+ if(symbol < kNumLowSymbols)
228
+ return _choice.GetPrice0() + _lowCoder[posState].GetPrice(symbol);
229
+ UInt32 price = _choice.GetPrice1();
230
+ if(symbol < kNumLowSymbols + kNumMidSymbols)
231
+ {
232
+ price += _choice2.GetPrice0();
233
+ price += _midCoder[posState].GetPrice(symbol - kNumLowSymbols);
234
+ }
235
+ else
236
+ {
237
+ price += _choice2.GetPrice1();
238
+ price += _highCoder.GetPrice(symbol - kNumLowSymbols - kNumMidSymbols);
239
+ }
240
+ return price;
241
+ }
242
+
243
+ }
244
+ CEncoder::CEncoder():
245
+ _numFastBytes(kNumFastBytesDefault),
246
+ _distTableSize(kDefaultDictionaryLogSize * 2),
247
+ _posStateBits(2),
248
+ _posStateMask(4 - 1),
249
+ _numLiteralPosStateBits(0),
250
+ _numLiteralContextBits(3),
251
+ _dictionarySize(1 << kDefaultDictionaryLogSize),
252
+ _dictionarySizePrev(UInt32(-1)),
253
+ _numFastBytesPrev(UInt32(-1)),
254
+ _matchFinderIndex(kBT4),
255
+ #ifdef COMPRESS_MF_MT
256
+ _multiThread(false),
257
+ #endif
258
+ _writeEndMark(false)
259
+ {
260
+ _maxMode = false;
261
+ _fastMode = false;
262
+ }
263
+
264
+ HRESULT CEncoder::Create()
265
+ {
266
+ if (!_rangeEncoder.Create(1 << 20))
267
+ return E_OUTOFMEMORY;
268
+ if (!_matchFinder)
269
+ {
270
+ switch(_matchFinderIndex)
271
+ {
272
+ #ifdef COMPRESS_MF_BT
273
+ #ifdef COMPRESS_MF_BT2
274
+ case kBT2:
275
+ _matchFinder = new NBT2::CMatchFinderBinTree;
276
+ break;
277
+ #endif
278
+ #ifdef COMPRESS_MF_BT3
279
+ case kBT3:
280
+ _matchFinder = new NBT3::CMatchFinderBinTree;
281
+ break;
282
+ #endif
283
+ #ifdef COMPRESS_MF_BT4
284
+ case kBT4:
285
+ _matchFinder = new NBT4::CMatchFinderBinTree;
286
+ break;
287
+ #endif
288
+ #ifdef COMPRESS_MF_BT4B
289
+ case kBT4B:
290
+ _matchFinder = new NBT4B::CMatchFinderBinTree;
291
+ break;
292
+ #endif
293
+ #endif
294
+
295
+ #ifdef COMPRESS_MF_PAT
296
+ case kPat2:
297
+ _matchFinder = new NPat2::CPatricia;
298
+ break;
299
+ case kPat2H:
300
+ _matchFinder = new NPat2H::CPatricia;
301
+ break;
302
+ case kPat3H:
303
+ _matchFinder = new NPat3H::CPatricia;
304
+ break;
305
+ case kPat4H:
306
+ _matchFinder = new NPat4H::CPatricia;
307
+ break;
308
+ case kPat2R:
309
+ _matchFinder = new NPat2R::CPatricia;
310
+ break;
311
+ #endif
312
+
313
+ #ifdef COMPRESS_MF_HC
314
+ case kHC3:
315
+ _matchFinder = new NHC3::CMatchFinderHC;
316
+ break;
317
+ case kHC4:
318
+ _matchFinder = new NHC4::CMatchFinderHC;
319
+ break;
320
+ #endif
321
+ }
322
+ if (_matchFinder == 0)
323
+ return E_OUTOFMEMORY;
324
+
325
+ #ifdef COMPRESS_MF_MT
326
+ if (_multiThread && !(_fastMode && (_matchFinderIndex == kHC3 || _matchFinderIndex == kHC4)))
327
+ {
328
+ CMatchFinderMT *mfSpec = new CMatchFinderMT;
329
+ if (mfSpec == 0)
330
+ return E_OUTOFMEMORY;
331
+ CMyComPtr<IMatchFinder> mf = mfSpec;
332
+ RINOK(mfSpec->SetMatchFinder(_matchFinder));
333
+ _matchFinder.Release();
334
+ _matchFinder = mf;
335
+ }
336
+ #endif
337
+ }
338
+
339
+ if (!_literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits))
340
+ return E_OUTOFMEMORY;
341
+
342
+ if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes)
343
+ return S_OK;
344
+ RINOK(_matchFinder->Create(_dictionarySize, kNumOpts, _numFastBytes,
345
+ kMatchMaxLen * 2 + 1 - _numFastBytes));
346
+ _dictionarySizePrev = _dictionarySize;
347
+ _numFastBytesPrev = _numFastBytes;
348
+ return S_OK;
349
+ }
350
+
351
+ static bool AreStringsEqual(const wchar_t *base, const wchar_t *testString)
352
+ {
353
+ while (true)
354
+ {
355
+ wchar_t c = *testString;
356
+ if (c >= 'a' && c <= 'z')
357
+ c -= 0x20;
358
+ if (*base != c)
359
+ return false;
360
+ if (c == 0)
361
+ return true;
362
+ base++;
363
+ testString++;
364
+ }
365
+ }
366
+
367
+ static int FindMatchFinder(const wchar_t *s)
368
+ {
369
+ for (int m = 0; m < (int)(sizeof(kMatchFinderIDs) / sizeof(kMatchFinderIDs[0])); m++)
370
+ if (AreStringsEqual(kMatchFinderIDs[m], s))
371
+ return m;
372
+ return -1;
373
+ }
374
+
375
+ STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
376
+ const PROPVARIANT *properties, UInt32 numProperties)
377
+ {
378
+ for (UInt32 i = 0; i < numProperties; i++)
379
+ {
380
+ const PROPVARIANT &prop = properties[i];
381
+ switch(propIDs[i])
382
+ {
383
+ case NCoderPropID::kNumFastBytes:
384
+ {
385
+ if (prop.vt != VT_UI4)
386
+ return E_INVALIDARG;
387
+ UInt32 numFastBytes = prop.ulVal;
388
+ if(numFastBytes < 5 || numFastBytes > kMatchMaxLen)
389
+ return E_INVALIDARG;
390
+ _numFastBytes = numFastBytes;
391
+ break;
392
+ }
393
+ case NCoderPropID::kAlgorithm:
394
+ {
395
+ if (prop.vt != VT_UI4)
396
+ return E_INVALIDARG;
397
+ UInt32 maximize = prop.ulVal;
398
+ _fastMode = (maximize == 0);
399
+ _maxMode = (maximize >= 2);
400
+ break;
401
+ }
402
+ case NCoderPropID::kMatchFinder:
403
+ {
404
+ if (prop.vt != VT_BSTR)
405
+ return E_INVALIDARG;
406
+ int matchFinderIndexPrev = _matchFinderIndex;
407
+ int m = FindMatchFinder(prop.bstrVal);
408
+ if (m < 0)
409
+ return E_INVALIDARG;
410
+ _matchFinderIndex = m;
411
+ if (_matchFinder && matchFinderIndexPrev != _matchFinderIndex)
412
+ {
413
+ _dictionarySizePrev = UInt32(-1);
414
+ _matchFinder.Release();
415
+ }
416
+ break;
417
+ }
418
+ #ifdef COMPRESS_MF_MT
419
+ case NCoderPropID::kMultiThread:
420
+ {
421
+ if (prop.vt != VT_BOOL)
422
+ return E_INVALIDARG;
423
+ bool newMultiThread = (prop.boolVal == VARIANT_TRUE);
424
+ if (newMultiThread != _multiThread)
425
+ {
426
+ _dictionarySizePrev = UInt32(-1);
427
+ _matchFinder.Release();
428
+ }
429
+ _multiThread = newMultiThread;
430
+ break;
431
+ }
432
+ #endif
433
+ case NCoderPropID::kDictionarySize:
434
+ {
435
+ const int kDicLogSizeMaxCompress = 28;
436
+ if (prop.vt != VT_UI4)
437
+ return E_INVALIDARG;
438
+ UInt32 dictionarySize = prop.ulVal;
439
+ if (dictionarySize < UInt32(1 << kDicLogSizeMin) ||
440
+ dictionarySize > UInt32(1 << kDicLogSizeMaxCompress))
441
+ return E_INVALIDARG;
442
+ _dictionarySize = dictionarySize;
443
+ UInt32 dicLogSize;
444
+ for(dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++)
445
+ if (dictionarySize <= (UInt32(1) << dicLogSize))
446
+ break;
447
+ _distTableSize = dicLogSize * 2;
448
+ break;
449
+ }
450
+ case NCoderPropID::kPosStateBits:
451
+ {
452
+ if (prop.vt != VT_UI4)
453
+ return E_INVALIDARG;
454
+ UInt32 value = prop.ulVal;
455
+ if (value > (UInt32)NLength::kNumPosStatesBitsEncodingMax)
456
+ return E_INVALIDARG;
457
+ _posStateBits = value;
458
+ _posStateMask = (1 << _posStateBits) - 1;
459
+ break;
460
+ }
461
+ case NCoderPropID::kLitPosBits:
462
+ {
463
+ if (prop.vt != VT_UI4)
464
+ return E_INVALIDARG;
465
+ UInt32 value = prop.ulVal;
466
+ if (value > (UInt32)kNumLitPosStatesBitsEncodingMax)
467
+ return E_INVALIDARG;
468
+ _numLiteralPosStateBits = value;
469
+ break;
470
+ }
471
+ case NCoderPropID::kLitContextBits:
472
+ {
473
+ if (prop.vt != VT_UI4)
474
+ return E_INVALIDARG;
475
+ UInt32 value = prop.ulVal;
476
+ if (value > (UInt32)kNumLitContextBitsMax)
477
+ return E_INVALIDARG;
478
+ _numLiteralContextBits = value;
479
+ break;
480
+ }
481
+ case NCoderPropID::kEndMarker:
482
+ {
483
+ if (prop.vt != VT_BOOL)
484
+ return E_INVALIDARG;
485
+ SetWriteEndMarkerMode(prop.boolVal == VARIANT_TRUE);
486
+ break;
487
+ }
488
+ default:
489
+ return E_INVALIDARG;
490
+ }
491
+ }
492
+ return S_OK;
493
+ }
494
+
495
+ STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
496
+ {
497
+ const UInt32 kPropSize = 5;
498
+ Byte properties[kPropSize];
499
+ properties[0] = (_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits;
500
+ for (int i = 0; i < 4; i++)
501
+ properties[1 + i] = Byte(_dictionarySize >> (8 * i));
502
+ return WriteStream(outStream, properties, kPropSize, NULL);
503
+ }
504
+
505
+ STDMETHODIMP CEncoder::SetOutStream(ISequentialOutStream *outStream)
506
+ {
507
+ _rangeEncoder.SetStream(outStream);
508
+ return S_OK;
509
+ }
510
+
511
+ STDMETHODIMP CEncoder::ReleaseOutStream()
512
+ {
513
+ _rangeEncoder.ReleaseStream();
514
+ return S_OK;
515
+ }
516
+
517
+ HRESULT CEncoder::Init()
518
+ {
519
+ CBaseState::Init();
520
+
521
+ // RINOK(_matchFinder->Init(inStream));
522
+ _rangeEncoder.Init();
523
+
524
+ for(int i = 0; i < kNumStates; i++)
525
+ {
526
+ for (UInt32 j = 0; j <= _posStateMask; j++)
527
+ {
528
+ _isMatch[i][j].Init();
529
+ _isRep0Long[i][j].Init();
530
+ }
531
+ _isRep[i].Init();
532
+ _isRepG0[i].Init();
533
+ _isRepG1[i].Init();
534
+ _isRepG2[i].Init();
535
+ }
536
+
537
+ _literalEncoder.Init();
538
+
539
+ // _repMatchLenEncoder.Init();
540
+
541
+ {
542
+ for(UInt32 i = 0; i < kNumLenToPosStates; i++)
543
+ _posSlotEncoder[i].Init();
544
+ }
545
+ {
546
+ for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++)
547
+ _posEncoders[i].Init();
548
+ }
549
+
550
+ _lenEncoder.Init(1 << _posStateBits);
551
+ _repMatchLenEncoder.Init(1 << _posStateBits);
552
+
553
+ _posAlignEncoder.Init();
554
+
555
+ _longestMatchWasFound = false;
556
+ _optimumEndIndex = 0;
557
+ _optimumCurrentIndex = 0;
558
+ _additionalOffset = 0;
559
+
560
+ return S_OK;
561
+ }
562
+
563
+ HRESULT CEncoder::MovePos(UInt32 num)
564
+ {
565
+ for (;num != 0; num--)
566
+ {
567
+ _matchFinder->DummyLongestMatch();
568
+ RINOK(_matchFinder->MovePos());
569
+ _additionalOffset++;
570
+ }
571
+ return S_OK;
572
+ }
573
+
574
+ UInt32 CEncoder::Backward(UInt32 &backRes, UInt32 cur)
575
+ {
576
+ _optimumEndIndex = cur;
577
+ UInt32 posMem = _optimum[cur].PosPrev;
578
+ UInt32 backMem = _optimum[cur].BackPrev;
579
+ do
580
+ {
581
+ if (_optimum[cur].Prev1IsChar)
582
+ {
583
+ _optimum[posMem].MakeAsChar();
584
+ _optimum[posMem].PosPrev = posMem - 1;
585
+ if (_optimum[cur].Prev2)
586
+ {
587
+ _optimum[posMem - 1].Prev1IsChar = false;
588
+ _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2;
589
+ _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2;
590
+ }
591
+ }
592
+ UInt32 posPrev = posMem;
593
+ UInt32 backCur = backMem;
594
+
595
+ backMem = _optimum[posPrev].BackPrev;
596
+ posMem = _optimum[posPrev].PosPrev;
597
+
598
+ _optimum[posPrev].BackPrev = backCur;
599
+ _optimum[posPrev].PosPrev = cur;
600
+ cur = posPrev;
601
+ }
602
+ while(cur != 0);
603
+ backRes = _optimum[0].BackPrev;
604
+ _optimumCurrentIndex = _optimum[0].PosPrev;
605
+ return _optimumCurrentIndex;
606
+ }
607
+
608
+ /*
609
+ inline UInt32 GetMatchLen(const Byte *data, UInt32 back, UInt32 limit)
610
+ {
611
+ back++;
612
+ for(UInt32 i = 0; i < limit && data[i] == data[i - back]; i++);
613
+ return i;
614
+ }
615
+ */
616
+
617
+
618
+ /*
619
+ Out:
620
+ (lenRes == 1) && (backRes == 0xFFFFFFFF) means Literal
621
+ */
622
+
623
+ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes)
624
+ {
625
+ if(_optimumEndIndex != _optimumCurrentIndex)
626
+ {
627
+ const COptimal &optimum = _optimum[_optimumCurrentIndex];
628
+ lenRes = optimum.PosPrev - _optimumCurrentIndex;
629
+ backRes = optimum.BackPrev;
630
+ _optimumCurrentIndex = optimum.PosPrev;
631
+ return S_OK;
632
+ }
633
+ _optimumCurrentIndex = 0;
634
+ _optimumEndIndex = 0; // test it;
635
+
636
+ UInt32 lenMain;
637
+ if (!_longestMatchWasFound)
638
+ {
639
+ RINOK(ReadMatchDistances(lenMain));
640
+ }
641
+ else
642
+ {
643
+ lenMain = _longestMatchLength;
644
+ _longestMatchWasFound = false;
645
+ }
646
+
647
+
648
+ UInt32 reps[kNumRepDistances];
649
+ UInt32 repLens[kNumRepDistances];
650
+ UInt32 repMaxIndex = 0;
651
+ UInt32 i;
652
+ for(i = 0; i < kNumRepDistances; i++)
653
+ {
654
+ reps[i] = _repDistances[i];
655
+ repLens[i] = _matchFinder->GetMatchLen(0 - 1, reps[i], kMatchMaxLen);
656
+ if (i == 0 || repLens[i] > repLens[repMaxIndex])
657
+ repMaxIndex = i;
658
+ }
659
+ if(repLens[repMaxIndex] >= _numFastBytes)
660
+ {
661
+ backRes = repMaxIndex;
662
+ lenRes = repLens[repMaxIndex];
663
+ return MovePos(lenRes - 1);
664
+ }
665
+
666
+ if(lenMain >= _numFastBytes)
667
+ {
668
+ backRes = _matchDistances[_numFastBytes] + kNumRepDistances;
669
+ lenRes = lenMain;
670
+ return MovePos(lenMain - 1);
671
+ }
672
+ Byte currentByte = _matchFinder->GetIndexByte(0 - 1);
673
+
674
+ _optimum[0].State = _state;
675
+
676
+ Byte matchByte;
677
+
678
+ matchByte = _matchFinder->GetIndexByte(0 - _repDistances[0] - 1 - 1);
679
+
680
+ UInt32 posState = (position & _posStateMask);
681
+
682
+ _optimum[1].Price = _isMatch[_state.Index][posState].GetPrice0() +
683
+ _literalEncoder.GetPrice(position, _previousByte, !_state.IsCharState(), matchByte, currentByte);
684
+ _optimum[1].MakeAsChar();
685
+
686
+ _optimum[1].PosPrev = 0;
687
+
688
+ for (i = 0; i < kNumRepDistances; i++)
689
+ _optimum[0].Backs[i] = reps[i];
690
+
691
+ UInt32 matchPrice = _isMatch[_state.Index][posState].GetPrice1();
692
+ UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1();
693
+
694
+ if(matchByte == currentByte)
695
+ {
696
+ UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState);
697
+ if(shortRepPrice < _optimum[1].Price)
698
+ {
699
+ _optimum[1].Price = shortRepPrice;
700
+ _optimum[1].MakeAsShortRep();
701
+ }
702
+ }
703
+ if(lenMain < 2)
704
+ {
705
+ backRes = _optimum[1].BackPrev;
706
+ lenRes = 1;
707
+ return S_OK;
708
+ }
709
+
710
+
711
+ UInt32 normalMatchPrice = matchPrice +
712
+ _isRep[_state.Index].GetPrice0();
713
+
714
+ if (lenMain <= repLens[repMaxIndex])
715
+ lenMain = 0;
716
+
717
+ UInt32 len;
718
+ for(len = 2; len <= lenMain; len++)
719
+ {
720
+ _optimum[len].PosPrev = 0;
721
+ _optimum[len].BackPrev = _matchDistances[len] + kNumRepDistances;
722
+ _optimum[len].Price = normalMatchPrice +
723
+ GetPosLenPrice(_matchDistances[len], len, posState);
724
+ _optimum[len].Prev1IsChar = false;
725
+ }
726
+
727
+ if (lenMain < repLens[repMaxIndex])
728
+ lenMain = repLens[repMaxIndex];
729
+
730
+ for (; len <= lenMain; len++)
731
+ _optimum[len].Price = kIfinityPrice;
732
+
733
+ for(i = 0; i < kNumRepDistances; i++)
734
+ {
735
+ UInt32 repLen = repLens[i];
736
+ for(UInt32 lenTest = 2; lenTest <= repLen; lenTest++)
737
+ {
738
+ UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(i, lenTest, _state, posState);
739
+ COptimal &optimum = _optimum[lenTest];
740
+ if (curAndLenPrice < optimum.Price)
741
+ {
742
+ optimum.Price = curAndLenPrice;
743
+ optimum.PosPrev = 0;
744
+ optimum.BackPrev = i;
745
+ optimum.Prev1IsChar = false;
746
+ }
747
+ }
748
+ }
749
+
750
+ UInt32 cur = 0;
751
+ UInt32 lenEnd = lenMain;
752
+
753
+ while(true)
754
+ {
755
+ cur++;
756
+ if(cur == lenEnd)
757
+ {
758
+ lenRes = Backward(backRes, cur);
759
+ return S_OK;
760
+ }
761
+ position++;
762
+ COptimal &curOptimum = _optimum[cur];
763
+ UInt32 posPrev = curOptimum.PosPrev;
764
+ CState state;
765
+ if (curOptimum.Prev1IsChar)
766
+ {
767
+ posPrev--;
768
+ if (curOptimum.Prev2)
769
+ {
770
+ state = _optimum[curOptimum.PosPrev2].State;
771
+ if (curOptimum.BackPrev2 < kNumRepDistances)
772
+ state.UpdateRep();
773
+ else
774
+ state.UpdateMatch();
775
+ }
776
+ else
777
+ state = _optimum[posPrev].State;
778
+ state.UpdateChar();
779
+ }
780
+ else
781
+ state = _optimum[posPrev].State;
782
+ if (posPrev == cur - 1)
783
+ {
784
+ if (curOptimum.IsShortRep())
785
+ state.UpdateShortRep();
786
+ else
787
+ state.UpdateChar();
788
+ /*
789
+ if (curOptimum.Prev1IsChar)
790
+ for(int i = 0; i < kNumRepDistances; i++)
791
+ reps[i] = _optimum[posPrev].Backs[i];
792
+ */
793
+ }
794
+ else
795
+ {
796
+ UInt32 pos;
797
+ if (curOptimum.Prev1IsChar && curOptimum.Prev2)
798
+ {
799
+ posPrev = curOptimum.PosPrev2;
800
+ pos = curOptimum.BackPrev2;
801
+ state.UpdateRep();
802
+ }
803
+ else
804
+ {
805
+ pos = curOptimum.BackPrev;
806
+ if (pos < kNumRepDistances)
807
+ state.UpdateRep();
808
+ else
809
+ state.UpdateMatch();
810
+ }
811
+ const COptimal &prevOptimum = _optimum[posPrev];
812
+ if (pos < kNumRepDistances)
813
+ {
814
+ reps[0] = prevOptimum.Backs[pos];
815
+ UInt32 i;
816
+ for(i = 1; i <= pos; i++)
817
+ reps[i] = prevOptimum.Backs[i - 1];
818
+ for(; i < kNumRepDistances; i++)
819
+ reps[i] = prevOptimum.Backs[i];
820
+ }
821
+ else
822
+ {
823
+ reps[0] = (pos - kNumRepDistances);
824
+ for(UInt32 i = 1; i < kNumRepDistances; i++)
825
+ reps[i] = prevOptimum.Backs[i - 1];
826
+ }
827
+ }
828
+ curOptimum.State = state;
829
+ for(UInt32 i = 0; i < kNumRepDistances; i++)
830
+ curOptimum.Backs[i] = reps[i];
831
+ UInt32 newLen;
832
+ RINOK(ReadMatchDistances(newLen));
833
+ if(newLen >= _numFastBytes)
834
+ {
835
+ _longestMatchLength = newLen;
836
+ _longestMatchWasFound = true;
837
+ lenRes = Backward(backRes, cur);
838
+ return S_OK;
839
+ }
840
+ UInt32 curPrice = curOptimum.Price;
841
+ // Byte currentByte = _matchFinder->GetIndexByte(0 - 1);
842
+ // Byte matchByte = _matchFinder->GetIndexByte(0 - reps[0] - 1 - 1);
843
+ const Byte *data = _matchFinder->GetPointerToCurrentPos() - 1;
844
+ Byte currentByte = *data;
845
+ Byte matchByte = data[(size_t)0 - reps[0] - 1];
846
+
847
+ UInt32 posState = (position & _posStateMask);
848
+
849
+ UInt32 curAnd1Price = curPrice +
850
+ _isMatch[state.Index][posState].GetPrice0() +
851
+ _literalEncoder.GetPrice(position, data[(size_t)0 - 1], !state.IsCharState(), matchByte, currentByte);
852
+
853
+ COptimal &nextOptimum = _optimum[cur + 1];
854
+
855
+ bool nextIsChar = false;
856
+ if (curAnd1Price < nextOptimum.Price)
857
+ {
858
+ nextOptimum.Price = curAnd1Price;
859
+ nextOptimum.PosPrev = cur;
860
+ nextOptimum.MakeAsChar();
861
+ nextIsChar = true;
862
+ }
863
+
864
+ UInt32 matchPrice = curPrice + _isMatch[state.Index][posState].GetPrice1();
865
+ UInt32 repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1();
866
+
867
+ if(matchByte == currentByte &&
868
+ !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0))
869
+ {
870
+ UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState);
871
+ if(shortRepPrice <= nextOptimum.Price)
872
+ {
873
+ nextOptimum.Price = shortRepPrice;
874
+ nextOptimum.PosPrev = cur;
875
+ nextOptimum.MakeAsShortRep();
876
+ // nextIsChar = false;
877
+ }
878
+ }
879
+ /*
880
+ if(newLen == 2 && _matchDistances[2] >= kDistLimit2) // test it maybe set 2000 ?
881
+ continue;
882
+ */
883
+
884
+ UInt32 numAvailableBytesFull = _matchFinder->GetNumAvailableBytes() + 1;
885
+ numAvailableBytesFull = MyMin(kNumOpts - 1 - cur, numAvailableBytesFull);
886
+ UInt32 numAvailableBytes = numAvailableBytesFull;
887
+
888
+ if (numAvailableBytes < 2)
889
+ continue;
890
+ if (numAvailableBytes > _numFastBytes)
891
+ numAvailableBytes = _numFastBytes;
892
+ if (numAvailableBytes >= 3 && !nextIsChar)
893
+ {
894
+ // try Literal + rep0
895
+ UInt32 backOffset = reps[0] + 1;
896
+ UInt32 temp;
897
+ for (temp = 1; temp < numAvailableBytes; temp++)
898
+ if (data[temp] != data[(size_t)temp - backOffset])
899
+ break;
900
+ UInt32 lenTest2 = temp - 1;
901
+ if (lenTest2 >= 2)
902
+ {
903
+ CState state2 = state;
904
+ state2.UpdateChar();
905
+ UInt32 posStateNext = (position + 1) & _posStateMask;
906
+ UInt32 nextRepMatchPrice = curAnd1Price +
907
+ _isMatch[state2.Index][posStateNext].GetPrice1() +
908
+ _isRep[state2.Index].GetPrice1();
909
+ // for (; lenTest2 >= 2; lenTest2--)
910
+ {
911
+ while(lenEnd < cur + 1 + lenTest2)
912
+ _optimum[++lenEnd].Price = kIfinityPrice;
913
+ UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(
914
+ 0, lenTest2, state2, posStateNext);
915
+ COptimal &optimum = _optimum[cur + 1 + lenTest2];
916
+ if (curAndLenPrice < optimum.Price)
917
+ {
918
+ optimum.Price = curAndLenPrice;
919
+ optimum.PosPrev = cur + 1;
920
+ optimum.BackPrev = 0;
921
+ optimum.Prev1IsChar = true;
922
+ optimum.Prev2 = false;
923
+ }
924
+ }
925
+ }
926
+ }
927
+ for(UInt32 repIndex = 0; repIndex < kNumRepDistances; repIndex++)
928
+ {
929
+ // UInt32 repLen = _matchFinder->GetMatchLen(0 - 1, reps[repIndex], newLen); // test it;
930
+ UInt32 backOffset = reps[repIndex] + 1;
931
+ if (data[0] != data[(size_t)0 - backOffset] ||
932
+ data[1] != data[(size_t)1 - backOffset])
933
+ continue;
934
+ UInt32 lenTest;
935
+ for (lenTest = 2; lenTest < numAvailableBytes; lenTest++)
936
+ if (data[lenTest] != data[(size_t)lenTest - backOffset])
937
+ break;
938
+ UInt32 lenTestTemp = lenTest;
939
+ do
940
+ {
941
+ while(lenEnd < cur + lenTest)
942
+ _optimum[++lenEnd].Price = kIfinityPrice;
943
+ UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState);
944
+ COptimal &optimum = _optimum[cur + lenTest];
945
+ if (curAndLenPrice < optimum.Price)
946
+ {
947
+ optimum.Price = curAndLenPrice;
948
+ optimum.PosPrev = cur;
949
+ optimum.BackPrev = repIndex;
950
+ optimum.Prev1IsChar = false;
951
+ }
952
+ }
953
+ while(--lenTest >= 2);
954
+ lenTest = lenTestTemp;
955
+
956
+ if (_maxMode)
957
+ {
958
+ UInt32 lenTest2 = lenTest + 1;
959
+ UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes);
960
+ for (; lenTest2 < limit; lenTest2++)
961
+ if (data[lenTest2] != data[(size_t)lenTest2 - backOffset])
962
+ break;
963
+ lenTest2 -= lenTest + 1;
964
+ if (lenTest2 >= 2)
965
+ {
966
+ CState state2 = state;
967
+ state2.UpdateRep();
968
+ UInt32 posStateNext = (position + lenTest) & _posStateMask;
969
+ UInt32 curAndLenCharPrice =
970
+ repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) +
971
+ _isMatch[state2.Index][posStateNext].GetPrice0() +
972
+ _literalEncoder.GetPrice(position + lenTest, data[(size_t)lenTest - 1],
973
+ true, data[(size_t)lenTest - backOffset], data[lenTest]);
974
+ state2.UpdateChar();
975
+ posStateNext = (position + lenTest + 1) & _posStateMask;
976
+ UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[state2.Index][posStateNext].GetPrice1();
977
+ UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1();
978
+
979
+ // for(; lenTest2 >= 2; lenTest2--)
980
+ {
981
+ UInt32 offset = lenTest + 1 + lenTest2;
982
+ while(lenEnd < cur + offset)
983
+ _optimum[++lenEnd].Price = kIfinityPrice;
984
+ UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(
985
+ 0, lenTest2, state2, posStateNext);
986
+ COptimal &optimum = _optimum[cur + offset];
987
+ if (curAndLenPrice < optimum.Price)
988
+ {
989
+ optimum.Price = curAndLenPrice;
990
+ optimum.PosPrev = cur + lenTest + 1;
991
+ optimum.BackPrev = 0;
992
+ optimum.Prev1IsChar = true;
993
+ optimum.Prev2 = true;
994
+ optimum.PosPrev2 = cur;
995
+ optimum.BackPrev2 = repIndex;
996
+ }
997
+ }
998
+ }
999
+ }
1000
+ }
1001
+
1002
+ // for(UInt32 lenTest = 2; lenTest <= newLen; lenTest++)
1003
+ if (newLen > numAvailableBytes)
1004
+ newLen = numAvailableBytes;
1005
+ if (newLen >= 2)
1006
+ {
1007
+ if (newLen == 2 && _matchDistances[2] >= 0x80)
1008
+ continue;
1009
+ UInt32 normalMatchPrice = matchPrice +
1010
+ _isRep[state.Index].GetPrice0();
1011
+ while(lenEnd < cur + newLen)
1012
+ _optimum[++lenEnd].Price = kIfinityPrice;
1013
+
1014
+ for(UInt32 lenTest = newLen; lenTest >= 2; lenTest--)
1015
+ {
1016
+ UInt32 curBack = _matchDistances[lenTest];
1017
+ UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState);
1018
+ COptimal &optimum = _optimum[cur + lenTest];
1019
+ if (curAndLenPrice < optimum.Price)
1020
+ {
1021
+ optimum.Price = curAndLenPrice;
1022
+ optimum.PosPrev = cur;
1023
+ optimum.BackPrev = curBack + kNumRepDistances;
1024
+ optimum.Prev1IsChar = false;
1025
+ }
1026
+
1027
+ if (_maxMode && (lenTest == newLen || curBack != _matchDistances[lenTest + 1]))
1028
+ {
1029
+ // Try Match + Literal + Rep0
1030
+ UInt32 backOffset = curBack + 1;
1031
+ UInt32 lenTest2 = lenTest + 1;
1032
+ UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes);
1033
+ for (; lenTest2 < limit; lenTest2++)
1034
+ if (data[lenTest2] != data[(size_t)lenTest2 - backOffset])
1035
+ break;
1036
+ lenTest2 -= lenTest + 1;
1037
+ if (lenTest2 >= 2)
1038
+ {
1039
+ CState state2 = state;
1040
+ state2.UpdateMatch();
1041
+ UInt32 posStateNext = (position + lenTest) & _posStateMask;
1042
+ UInt32 curAndLenCharPrice = curAndLenPrice +
1043
+ _isMatch[state2.Index][posStateNext].GetPrice0() +
1044
+ _literalEncoder.GetPrice(position + lenTest, data[(size_t)lenTest - 1],
1045
+ true, data[(size_t)lenTest - backOffset], data[lenTest]);
1046
+ state2.UpdateChar();
1047
+ posStateNext = (position + lenTest + 1) & _posStateMask;
1048
+ UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[state2.Index][posStateNext].GetPrice1();
1049
+ UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1();
1050
+
1051
+ // for(; lenTest2 >= 2; lenTest2--)
1052
+ {
1053
+ UInt32 offset = lenTest + 1 + lenTest2;
1054
+ while(lenEnd < cur + offset)
1055
+ _optimum[++lenEnd].Price = kIfinityPrice;
1056
+ UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(
1057
+ 0, lenTest2, state2, posStateNext);
1058
+ COptimal &optimum = _optimum[cur + offset];
1059
+ if (curAndLenPrice < optimum.Price)
1060
+ {
1061
+ optimum.Price = curAndLenPrice;
1062
+ optimum.PosPrev = cur + lenTest + 1;
1063
+ optimum.BackPrev = 0;
1064
+ optimum.Prev1IsChar = true;
1065
+ optimum.Prev2 = true;
1066
+ optimum.PosPrev2 = cur;
1067
+ optimum.BackPrev2 = curBack + kNumRepDistances;
1068
+ }
1069
+ }
1070
+ }
1071
+ }
1072
+ }
1073
+ }
1074
+ }
1075
+ }
1076
+
1077
+ static inline bool ChangePair(UInt32 smallDist, UInt32 bigDist)
1078
+ {
1079
+ const int kDif = 7;
1080
+ return (smallDist < (UInt32(1) << (32-kDif)) && bigDist >= (smallDist << kDif));
1081
+ }
1082
+
1083
+
1084
+ HRESULT CEncoder::ReadMatchDistances(UInt32 &lenRes)
1085
+ {
1086
+ lenRes = _matchFinder->GetLongestMatch(_matchDistances);
1087
+ if (lenRes == _numFastBytes)
1088
+ lenRes += _matchFinder->GetMatchLen(lenRes, _matchDistances[lenRes],
1089
+ kMatchMaxLen - lenRes);
1090
+ _additionalOffset++;
1091
+ return _matchFinder->MovePos();
1092
+ }
1093
+
1094
+ HRESULT CEncoder::GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRes)
1095
+ {
1096
+ UInt32 lenMain;
1097
+ if (!_longestMatchWasFound)
1098
+ {
1099
+ RINOK(ReadMatchDistances(lenMain));
1100
+ }
1101
+ else
1102
+ {
1103
+ lenMain = _longestMatchLength;
1104
+ _longestMatchWasFound = false;
1105
+ }
1106
+ UInt32 repLens[kNumRepDistances];
1107
+ UInt32 repMaxIndex = 0;
1108
+ for(UInt32 i = 0; i < kNumRepDistances; i++)
1109
+ {
1110
+ repLens[i] = _matchFinder->GetMatchLen(0 - 1, _repDistances[i], kMatchMaxLen);
1111
+ if (i == 0 || repLens[i] > repLens[repMaxIndex])
1112
+ repMaxIndex = i;
1113
+ }
1114
+ if(repLens[repMaxIndex] >= _numFastBytes)
1115
+ {
1116
+ backRes = repMaxIndex;
1117
+ lenRes = repLens[repMaxIndex];
1118
+ return MovePos(lenRes - 1);
1119
+ }
1120
+ if(lenMain >= _numFastBytes)
1121
+ {
1122
+ backRes = _matchDistances[_numFastBytes] + kNumRepDistances;
1123
+ lenRes = lenMain;
1124
+ return MovePos(lenMain - 1);
1125
+ }
1126
+ while (lenMain > 2)
1127
+ {
1128
+ if (!ChangePair(_matchDistances[lenMain - 1], _matchDistances[lenMain]))
1129
+ break;
1130
+ lenMain--;
1131
+ }
1132
+ if (lenMain == 2 && _matchDistances[2] >= 0x80)
1133
+ lenMain = 1;
1134
+
1135
+ UInt32 backMain = _matchDistances[lenMain];
1136
+ if (repLens[repMaxIndex] >= 2)
1137
+ {
1138
+ if (repLens[repMaxIndex] + 1 >= lenMain ||
1139
+ repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1<<12)))
1140
+ {
1141
+ backRes = repMaxIndex;
1142
+ lenRes = repLens[repMaxIndex];
1143
+ return MovePos(lenRes - 1);
1144
+ }
1145
+ }
1146
+
1147
+
1148
+ if (lenMain >= 2)
1149
+ {
1150
+ RINOK(ReadMatchDistances(_longestMatchLength));
1151
+ if (_longestMatchLength >= 2 &&
1152
+ (
1153
+ (_longestMatchLength >= lenMain && _matchDistances[lenMain] < backMain) ||
1154
+ _longestMatchLength == lenMain + 1 &&
1155
+ !ChangePair(backMain, _matchDistances[_longestMatchLength]) ||
1156
+ _longestMatchLength > lenMain + 1 ||
1157
+ _longestMatchLength + 1 >= lenMain && lenMain >= 3 &&
1158
+ ChangePair(_matchDistances[lenMain - 1], backMain)
1159
+ )
1160
+ )
1161
+ {
1162
+ _longestMatchWasFound = true;
1163
+ backRes = UInt32(-1);
1164
+ lenRes = 1;
1165
+ return S_OK;
1166
+ }
1167
+ for(UInt32 i = 0; i < kNumRepDistances; i++)
1168
+ {
1169
+ UInt32 repLen = _matchFinder->GetMatchLen(0 - 1, _repDistances[i], kMatchMaxLen);
1170
+ if (repLen >= 2 && repLen + 1 >= lenMain)
1171
+ {
1172
+ _longestMatchWasFound = true;
1173
+ backRes = UInt32(-1);
1174
+ lenRes = 1;
1175
+ return S_OK;
1176
+ }
1177
+ }
1178
+ backRes = backMain + kNumRepDistances;
1179
+ lenRes = lenMain;
1180
+ return MovePos(lenMain - 2);
1181
+ }
1182
+ backRes = UInt32(-1);
1183
+ lenRes = 1;
1184
+ return S_OK;
1185
+ }
1186
+
1187
+ STDMETHODIMP CEncoder::InitMatchFinder(IMatchFinder *matchFinder)
1188
+ {
1189
+ _matchFinder = matchFinder;
1190
+ return S_OK;
1191
+ }
1192
+
1193
+ HRESULT CEncoder::Flush(UInt32 nowPos)
1194
+ {
1195
+ ReleaseMFStream();
1196
+ WriteEndMarker(nowPos & _posStateMask);
1197
+ _rangeEncoder.FlushData();
1198
+ return _rangeEncoder.FlushStream();
1199
+ }
1200
+
1201
+ void CEncoder::WriteEndMarker(UInt32 posState)
1202
+ {
1203
+ // This function for writing End Mark for stream version of LZMA.
1204
+ // In current version this feature is not used.
1205
+ if (!_writeEndMark)
1206
+ return;
1207
+
1208
+ _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1);
1209
+ _isRep[_state.Index].Encode(&_rangeEncoder, 0);
1210
+ _state.UpdateMatch();
1211
+ UInt32 len = kMatchMinLen; // kMatchMaxLen;
1212
+ _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState);
1213
+ UInt32 posSlot = (1 << kNumPosSlotBits) - 1;
1214
+ UInt32 lenToPosState = GetLenToPosState(len);
1215
+ _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot);
1216
+ UInt32 footerBits = 30;
1217
+ UInt32 posReduced = (UInt32(1) << footerBits) - 1;
1218
+ _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
1219
+ _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask);
1220
+ }
1221
+
1222
+ HRESULT CEncoder::CodeReal(ISequentialInStream *inStream,
1223
+ ISequentialOutStream *outStream,
1224
+ const UInt64 *inSize, const UInt64 *outSize,
1225
+ ICompressProgressInfo *progress)
1226
+ {
1227
+ _needReleaseMFStream = false;
1228
+ CCoderReleaser coderReleaser(this);
1229
+ RINOK(SetStreams(inStream, outStream, inSize, outSize));
1230
+ while(true)
1231
+ {
1232
+ UInt64 processedInSize;
1233
+ UInt64 processedOutSize;
1234
+ Int32 finished;
1235
+ RINOK(CodeOneBlock(&processedInSize, &processedOutSize, &finished));
1236
+ if (finished != 0)
1237
+ return S_OK;
1238
+ if (progress != 0)
1239
+ {
1240
+ RINOK(progress->SetRatioInfo(&processedInSize, &processedOutSize));
1241
+ }
1242
+ }
1243
+ }
1244
+
1245
+ HRESULT CEncoder::SetStreams(ISequentialInStream *inStream,
1246
+ ISequentialOutStream *outStream,
1247
+ const UInt64 *inSize, const UInt64 *outSize)
1248
+ {
1249
+ _inStream = inStream;
1250
+ _finished = false;
1251
+ RINOK(Create());
1252
+ RINOK(SetOutStream(outStream));
1253
+ RINOK(Init());
1254
+
1255
+ // CCoderReleaser releaser(this);
1256
+
1257
+ /*
1258
+ if (_matchFinder->GetNumAvailableBytes() == 0)
1259
+ return Flush();
1260
+ */
1261
+
1262
+ if (!_fastMode)
1263
+ {
1264
+ FillPosSlotPrices();
1265
+ FillDistancesPrices();
1266
+ FillAlignPrices();
1267
+ }
1268
+
1269
+ _lenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen);
1270
+ _lenEncoder.UpdateTables(1 << _posStateBits);
1271
+ _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen);
1272
+ _repMatchLenEncoder.UpdateTables(1 << _posStateBits);
1273
+
1274
+ lastPosSlotFillingPos = 0;
1275
+ nowPos64 = 0;
1276
+ return S_OK;
1277
+ }
1278
+
1279
+ HRESULT CEncoder::CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished)
1280
+ {
1281
+ if (_inStream != 0)
1282
+ {
1283
+ RINOK(_matchFinder->Init(_inStream));
1284
+ _needReleaseMFStream = true;
1285
+ _inStream = 0;
1286
+ }
1287
+
1288
+
1289
+ *finished = 1;
1290
+ if (_finished)
1291
+ return S_OK;
1292
+ _finished = true;
1293
+
1294
+
1295
+ UInt64 progressPosValuePrev = nowPos64;
1296
+ if (nowPos64 == 0)
1297
+ {
1298
+ if (_matchFinder->GetNumAvailableBytes() == 0)
1299
+ return Flush(UInt32(nowPos64));
1300
+ UInt32 len; // it's not used
1301
+ RINOK(ReadMatchDistances(len));
1302
+ UInt32 posState = UInt32(nowPos64) & _posStateMask;
1303
+ _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0);
1304
+ _state.UpdateChar();
1305
+ Byte curByte = _matchFinder->GetIndexByte(0 - _additionalOffset);
1306
+ _literalEncoder.GetSubCoder(UInt32(nowPos64), _previousByte)->Encode(&_rangeEncoder, curByte);
1307
+ _previousByte = curByte;
1308
+ _additionalOffset--;
1309
+ nowPos64++;
1310
+ }
1311
+ if (_matchFinder->GetNumAvailableBytes() == 0)
1312
+ return Flush(UInt32(nowPos64));
1313
+ while(true)
1314
+ {
1315
+ #ifdef _NO_EXCEPTIONS
1316
+ if (_rangeEncoder.Stream.ErrorCode != S_OK)
1317
+ return _rangeEncoder.Stream.ErrorCode;
1318
+ #endif
1319
+ UInt32 pos;
1320
+ UInt32 posState = UInt32(nowPos64) & _posStateMask;
1321
+
1322
+ UInt32 len;
1323
+ HRESULT result;
1324
+ if (_fastMode)
1325
+ result = GetOptimumFast(UInt32(nowPos64), pos, len);
1326
+ else
1327
+ result = GetOptimum(UInt32(nowPos64), pos, len);
1328
+ RINOK(result);
1329
+
1330
+ if(len == 1 && pos == 0xFFFFFFFF)
1331
+ {
1332
+ _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0);
1333
+ Byte curByte = _matchFinder->GetIndexByte(0 - _additionalOffset);
1334
+ CLiteralEncoder2 *subCoder = _literalEncoder.GetSubCoder(UInt32(nowPos64), _previousByte);
1335
+ if(!_state.IsCharState())
1336
+ {
1337
+ Byte matchByte = _matchFinder->GetIndexByte(0 - _repDistances[0] - 1 - _additionalOffset);
1338
+ subCoder->EncodeMatched(&_rangeEncoder, matchByte, curByte);
1339
+ }
1340
+ else
1341
+ subCoder->Encode(&_rangeEncoder, curByte);
1342
+ _state.UpdateChar();
1343
+ _previousByte = curByte;
1344
+ }
1345
+ else
1346
+ {
1347
+ _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1);
1348
+ if(pos < kNumRepDistances)
1349
+ {
1350
+ _isRep[_state.Index].Encode(&_rangeEncoder, 1);
1351
+ if(pos == 0)
1352
+ {
1353
+ _isRepG0[_state.Index].Encode(&_rangeEncoder, 0);
1354
+ if(len == 1)
1355
+ _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, 0);
1356
+ else
1357
+ _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, 1);
1358
+ }
1359
+ else
1360
+ {
1361
+ _isRepG0[_state.Index].Encode(&_rangeEncoder, 1);
1362
+ if (pos == 1)
1363
+ _isRepG1[_state.Index].Encode(&_rangeEncoder, 0);
1364
+ else
1365
+ {
1366
+ _isRepG1[_state.Index].Encode(&_rangeEncoder, 1);
1367
+ _isRepG2[_state.Index].Encode(&_rangeEncoder, pos - 2);
1368
+ }
1369
+ }
1370
+ if (len == 1)
1371
+ _state.UpdateShortRep();
1372
+ else
1373
+ {
1374
+ _repMatchLenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState);
1375
+ _state.UpdateRep();
1376
+ }
1377
+
1378
+
1379
+ UInt32 distance = _repDistances[pos];
1380
+ if (pos != 0)
1381
+ {
1382
+ for(UInt32 i = pos; i >= 1; i--)
1383
+ _repDistances[i] = _repDistances[i - 1];
1384
+ _repDistances[0] = distance;
1385
+ }
1386
+ }
1387
+ else
1388
+ {
1389
+ _isRep[_state.Index].Encode(&_rangeEncoder, 0);
1390
+ _state.UpdateMatch();
1391
+ _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState);
1392
+ pos -= kNumRepDistances;
1393
+ UInt32 posSlot = GetPosSlot(pos);
1394
+ UInt32 lenToPosState = GetLenToPosState(len);
1395
+ _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot);
1396
+
1397
+ if (posSlot >= kStartPosModelIndex)
1398
+ {
1399
+ UInt32 footerBits = ((posSlot >> 1) - 1);
1400
+ UInt32 base = ((2 | (posSlot & 1)) << footerBits);
1401
+ UInt32 posReduced = pos - base;
1402
+
1403
+ if (posSlot < kEndPosModelIndex)
1404
+ NRangeCoder::ReverseBitTreeEncode(_posEncoders + base - posSlot - 1,
1405
+ &_rangeEncoder, footerBits, posReduced);
1406
+ else
1407
+ {
1408
+ _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
1409
+ _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask);
1410
+ if (!_fastMode)
1411
+ if (--_alignPriceCount == 0)
1412
+ FillAlignPrices();
1413
+ }
1414
+ }
1415
+ UInt32 distance = pos;
1416
+ for(UInt32 i = kNumRepDistances - 1; i >= 1; i--)
1417
+ _repDistances[i] = _repDistances[i - 1];
1418
+ _repDistances[0] = distance;
1419
+ }
1420
+ _previousByte = _matchFinder->GetIndexByte(len - 1 - _additionalOffset);
1421
+ }
1422
+ _additionalOffset -= len;
1423
+ nowPos64 += len;
1424
+ if (!_fastMode)
1425
+ if (nowPos64 - lastPosSlotFillingPos >= (1 << 9))
1426
+ {
1427
+ FillPosSlotPrices();
1428
+ FillDistancesPrices();
1429
+ lastPosSlotFillingPos = nowPos64;
1430
+ }
1431
+ if (_additionalOffset == 0)
1432
+ {
1433
+ *inSize = nowPos64;
1434
+ *outSize = _rangeEncoder.GetProcessedSize();
1435
+ if (_matchFinder->GetNumAvailableBytes() == 0)
1436
+ return Flush(UInt32(nowPos64));
1437
+ if (nowPos64 - progressPosValuePrev >= (1 << 12))
1438
+ {
1439
+ _finished = false;
1440
+ *finished = 0;
1441
+ return S_OK;
1442
+ }
1443
+ }
1444
+ }
1445
+ }
1446
+
1447
+ STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream,
1448
+ ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
1449
+ ICompressProgressInfo *progress)
1450
+ {
1451
+ #ifndef _NO_EXCEPTIONS
1452
+ try
1453
+ {
1454
+ #endif
1455
+ return CodeReal(inStream, outStream, inSize, outSize, progress);
1456
+ #ifndef _NO_EXCEPTIONS
1457
+ }
1458
+ catch(const COutBufferException &e) { return e.ErrorCode; }
1459
+ catch(...) { return E_FAIL; }
1460
+ #endif
1461
+ }
1462
+
1463
+ void CEncoder::FillPosSlotPrices()
1464
+ {
1465
+ for (UInt32 lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)
1466
+ {
1467
+ UInt32 posSlot;
1468
+ for (posSlot = 0; posSlot < kEndPosModelIndex && posSlot < _distTableSize; posSlot++)
1469
+ _posSlotPrices[lenToPosState][posSlot] = _posSlotEncoder[lenToPosState].GetPrice(posSlot);
1470
+ for (; posSlot < _distTableSize; posSlot++)
1471
+ _posSlotPrices[lenToPosState][posSlot] = _posSlotEncoder[lenToPosState].GetPrice(posSlot) +
1472
+ ((((posSlot >> 1) - 1) - kNumAlignBits) << NRangeCoder::kNumBitPriceShiftBits);
1473
+ }
1474
+ }
1475
+
1476
+ void CEncoder::FillDistancesPrices()
1477
+ {
1478
+ for (UInt32 lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)
1479
+ {
1480
+ UInt32 i;
1481
+ for (i = 0; i < kStartPosModelIndex; i++)
1482
+ _distancesPrices[lenToPosState][i] = _posSlotPrices[lenToPosState][i];
1483
+ for (; i < kNumFullDistances; i++)
1484
+ {
1485
+ UInt32 posSlot = GetPosSlot(i);
1486
+ UInt32 footerBits = ((posSlot >> 1) - 1);
1487
+ UInt32 base = ((2 | (posSlot & 1)) << footerBits);
1488
+
1489
+ _distancesPrices[lenToPosState][i] = _posSlotPrices[lenToPosState][posSlot] +
1490
+ NRangeCoder::ReverseBitTreeGetPrice(_posEncoders +
1491
+ base - posSlot - 1, footerBits, i - base);
1492
+
1493
+ }
1494
+ }
1495
+ }
1496
+
1497
+ void CEncoder::FillAlignPrices()
1498
+ {
1499
+ for (UInt32 i = 0; i < kAlignTableSize; i++)
1500
+ _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i);
1501
+ _alignPriceCount = kAlignTableSize;
1502
+ }
1503
+
1504
+ }}