ruby-lzma 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }}