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.
- data/.gitignore +6 -0
- data/README.markdown +15 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/ext/Alloc.cpp +118 -0
- data/ext/Alloc.h +29 -0
- data/ext/BinTree.h +55 -0
- data/ext/BinTree2.h +12 -0
- data/ext/BinTree3.h +16 -0
- data/ext/BinTree3Z.h +16 -0
- data/ext/BinTree4.h +18 -0
- data/ext/BinTree4b.h +20 -0
- data/ext/BinTreeMain.h +444 -0
- data/ext/BranchX86.c +101 -0
- data/ext/BranchX86.h +19 -0
- data/ext/CRC.cpp +61 -0
- data/ext/CRC.h +36 -0
- data/ext/C_FileIO.h +45 -0
- data/ext/CommandLineParser.h +82 -0
- data/ext/Defs.h +20 -0
- data/ext/FileStreams.h +98 -0
- data/ext/HC.h +55 -0
- data/ext/HC2.h +13 -0
- data/ext/HC3.h +17 -0
- data/ext/HC4.h +19 -0
- data/ext/HC4b.h +21 -0
- data/ext/HCMain.h +350 -0
- data/ext/ICoder.h +156 -0
- data/ext/IMatchFinder.h +63 -0
- data/ext/IStream.h +62 -0
- data/ext/InBuffer.cpp +80 -0
- data/ext/InBuffer.h +76 -0
- data/ext/LZInWindow.cpp +102 -0
- data/ext/LZInWindow.h +84 -0
- data/ext/LZMA.h +82 -0
- data/ext/LZMADecoder.h +248 -0
- data/ext/LZMAEncoder.cpp +1504 -0
- data/ext/LZMAEncoder.h +416 -0
- data/ext/LZOutWindow.cpp +17 -0
- data/ext/LZOutWindow.h +66 -0
- data/ext/LzmaBench.h +11 -0
- data/ext/LzmaDecode.c +588 -0
- data/ext/LzmaDecode.h +131 -0
- data/ext/LzmaRam.cpp +228 -0
- data/ext/LzmaRam.h +46 -0
- data/ext/LzmaRamDecode.c +79 -0
- data/ext/LzmaRamDecode.h +55 -0
- data/ext/MyCom.h +203 -0
- data/ext/MyGuidDef.h +54 -0
- data/ext/MyInitGuid.h +13 -0
- data/ext/MyString.h +631 -0
- data/ext/MyUnknown.h +24 -0
- data/ext/MyWindows.h +183 -0
- data/ext/OutBuffer.cpp +117 -0
- data/ext/OutBuffer.h +64 -0
- data/ext/Pat.h +318 -0
- data/ext/Pat2.h +22 -0
- data/ext/Pat2H.h +24 -0
- data/ext/Pat2R.h +20 -0
- data/ext/Pat3H.h +24 -0
- data/ext/Pat4H.h +24 -0
- data/ext/PatMain.h +989 -0
- data/ext/RangeCoder.h +205 -0
- data/ext/RangeCoderBit.cpp +80 -0
- data/ext/RangeCoderBit.h +120 -0
- data/ext/RangeCoderBitTree.h +161 -0
- data/ext/RangeCoderOpt.h +31 -0
- data/ext/StdAfx.h +8 -0
- data/ext/StreamUtils.cpp +44 -0
- data/ext/StreamUtils.h +11 -0
- data/ext/StringConvert.h +71 -0
- data/ext/StringToInt.h +17 -0
- data/ext/Types.h +19 -0
- data/ext/Vector.h +211 -0
- data/ext/extconf.rb +7 -0
- data/ext/lzma_ruby.cpp +51 -0
- data/ext/lzmalib.h +64 -0
- data/ext/mylib.cpp +81 -0
- data/java/SevenZip/CRC.java +52 -0
- data/java/SevenZip/Compression/LZ/BinTree.java +382 -0
- data/java/SevenZip/Compression/LZ/InWindow.java +131 -0
- data/java/SevenZip/Compression/LZ/OutWindow.java +85 -0
- data/java/SevenZip/Compression/LZMA/Base.java +88 -0
- data/java/SevenZip/Compression/LZMA/Decoder.java +329 -0
- data/java/SevenZip/Compression/LZMA/Encoder.java +1415 -0
- data/java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java +55 -0
- data/java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java +99 -0
- data/java/SevenZip/Compression/RangeCoder/Decoder.java +88 -0
- data/java/SevenZip/Compression/RangeCoder/Encoder.java +151 -0
- data/java/SevenZip/ICodeProgress.java +6 -0
- data/java/SevenZip/LzmaAlone.java +253 -0
- data/java/SevenZip/LzmaBench.java +391 -0
- data/java/com/ephemeronindustries/lzma/LZMA.java +104 -0
- data/lib/lzma.rb +32 -0
- data/ruby-lzma.gemspec +136 -0
- data/test/test_lzma.rb +42 -0
- 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
|
data/ext/LZMAEncoder.cpp
ADDED
@@ -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
|
+
}}
|