6 #include "../../../Common/Alloc.h"
8 static const int kBufferSize
= 1 << 17;
10 inline bool IsJcc(Byte b0
, Byte b1
)
12 return (b0
== 0x0F && (b1
& 0xF0) == 0x80);
17 static bool inline Test86MSByte(Byte b
)
19 return (b
== 0 || b
== 0xFF);
22 bool CBCJ2_x86_Encoder::Create()
24 if (!_mainStream
.Create(1 << 16))
26 if (!_callStream
.Create(1 << 20))
28 if (!_jumpStream
.Create(1 << 20))
30 if (!_rangeEncoder
.Create(1 << 20))
34 _buffer
= (Byte
*)MidAlloc(kBufferSize
);
41 CBCJ2_x86_Encoder::~CBCJ2_x86_Encoder()
46 HRESULT
CBCJ2_x86_Encoder::Flush()
48 RINOK(_mainStream
.Flush());
49 RINOK(_callStream
.Flush());
50 RINOK(_jumpStream
.Flush());
51 _rangeEncoder
.FlushData();
52 return _rangeEncoder
.FlushStream();
55 const UInt32 kDefaultLimit
= (1 << 24);
57 HRESULT
CBCJ2_x86_Encoder::CodeReal(ISequentialInStream
**inStreams
,
58 const UInt64
**inSizes
,
60 ISequentialOutStream
**outStreams
,
61 const UInt64
**outSizes
,
63 ICompressProgressInfo
*progress
)
65 if (numInStreams
!= 1 || numOutStreams
!= 4)
71 bool sizeIsDefined
= false;
74 if (inSizes
[0] != NULL
)
77 if (inSize
<= kDefaultLimit
)
81 ISequentialInStream
*inStream
= inStreams
[0];
83 _mainStream
.SetStream(outStreams
[0]);
85 _callStream
.SetStream(outStreams
[1]);
87 _jumpStream
.SetStream(outStreams
[2]);
89 _rangeEncoder
.SetStream(outStreams
[3]);
91 for (int i
= 0; i
< 256; i
++)
92 _statusE8Encoder
[i
].Init();
93 _statusE9Encoder
.Init();
94 _statusJccEncoder
.Init();
95 CCoderReleaser
releaser(this);
97 CMyComPtr
<ICompressGetSubStreamSize
> getSubStreamSize
;
99 inStream
->QueryInterface(IID_ICompressGetSubStreamSize
, (void **)&getSubStreamSize
);
104 UInt32 bufferPos
= 0;
108 UInt64 subStreamIndex
= 0;
109 UInt64 subStreamStartPos
= 0;
110 UInt64 subStreamEndPos
= 0;
114 UInt32 processedSize
= 0;
117 UInt32 size
= kBufferSize
- (bufferPos
+ processedSize
);
118 UInt32 processedSizeLoc
;
121 RINOK(inStream
->Read(_buffer
+ bufferPos
+ processedSize
, size
, &processedSizeLoc
));
122 if (processedSizeLoc
== 0)
124 processedSize
+= processedSizeLoc
;
126 UInt32 endPos
= bufferPos
+ processedSize
;
131 for (bufferPos
= 0; bufferPos
< endPos
; bufferPos
++)
133 Byte b
= _buffer
[bufferPos
];
134 _mainStream
.WriteByte(b
);
136 _statusE8Encoder
[prevByte
].Encode(&_rangeEncoder
, 0);
138 _statusE9Encoder
.Encode(&_rangeEncoder
, 0);
139 else if (IsJcc(prevByte
, b
))
140 _statusJccEncoder
.Encode(&_rangeEncoder
, 0);
148 UInt32 limit
= endPos
- 5;
149 while(bufferPos
<= limit
)
151 Byte b
= _buffer
[bufferPos
];
152 _mainStream
.WriteByte(b
);
153 if (b
!= 0xE8 && b
!= 0xE9 && !IsJcc(prevByte
, b
))
159 Byte nextByte
= _buffer
[bufferPos
+ 4];
161 (UInt32(nextByte
) << 24) |
162 (UInt32(_buffer
[bufferPos
+ 3]) << 16) |
163 (UInt32(_buffer
[bufferPos
+ 2]) << 8) |
164 (_buffer
[bufferPos
+ 1]);
165 UInt32 dest
= (nowPos
+ bufferPos
+ 5) + src
;
166 // if (Test86MSByte(nextByte))
168 if (getSubStreamSize
!= NULL
)
170 UInt64 currentPos
= (nowPos64
+ bufferPos
);
171 while (subStreamEndPos
< currentPos
)
173 UInt64 subStreamSize
;
174 HRESULT result
= getSubStreamSize
->GetSubStreamSize(subStreamIndex
, &subStreamSize
);
177 subStreamStartPos
= subStreamEndPos
;
178 subStreamEndPos
+= subStreamSize
;
181 else if (result
== S_FALSE
|| result
== E_NOTIMPL
)
183 getSubStreamSize
.Release();
184 subStreamStartPos
= 0;
185 subStreamEndPos
= subStreamStartPos
- 1;
190 if (getSubStreamSize
== NULL
)
193 convert
= (dest
< inSize
);
195 convert
= Test86MSByte(nextByte
);
197 else if (subStreamEndPos
- subStreamStartPos
> kDefaultLimit
)
198 convert
= Test86MSByte(nextByte
);
201 UInt64 dest64
= (currentPos
+ 5) + Int64(Int32(src
));
202 convert
= (dest64
>= subStreamStartPos
&& dest64
< subStreamEndPos
);
205 else if (sizeIsDefined
)
206 convert
= (dest
< inSize
);
208 convert
= Test86MSByte(nextByte
);
212 _statusE8Encoder
[prevByte
].Encode(&_rangeEncoder
, 1);
214 _statusE9Encoder
.Encode(&_rangeEncoder
, 1);
216 _statusJccEncoder
.Encode(&_rangeEncoder
, 1);
221 _callStream
.WriteByte((Byte
)(dest
>> 24));
222 _callStream
.WriteByte((Byte
)(dest
>> 16));
223 _callStream
.WriteByte((Byte
)(dest
>> 8));
224 _callStream
.WriteByte((Byte
)(dest
));
228 _jumpStream
.WriteByte((Byte
)(dest
>> 24));
229 _jumpStream
.WriteByte((Byte
)(dest
>> 16));
230 _jumpStream
.WriteByte((Byte
)(dest
>> 8));
231 _jumpStream
.WriteByte((Byte
)(dest
));
238 _statusE8Encoder
[prevByte
].Encode(&_rangeEncoder
, 0);
240 _statusE9Encoder
.Encode(&_rangeEncoder
, 0);
242 _statusJccEncoder
.Encode(&_rangeEncoder
, 0);
248 nowPos64
+= bufferPos
;
250 if (progress
!= NULL
)
252 RINOK(progress
->SetRatioInfo(&nowPos64
, NULL
));
256 while(bufferPos
< endPos
)
257 _buffer
[i
++] = _buffer
[bufferPos
++];
262 STDMETHODIMP
CBCJ2_x86_Encoder::Code(ISequentialInStream
**inStreams
,
263 const UInt64
**inSizes
,
265 ISequentialOutStream
**outStreams
,
266 const UInt64
**outSizes
,
267 UInt32 numOutStreams
,
268 ICompressProgressInfo
*progress
)
272 return CodeReal(inStreams
, inSizes
, numInStreams
,
273 outStreams
, outSizes
,numOutStreams
, progress
);
275 catch(const COutBufferException
&e
) { return e
.ErrorCode
; }
276 catch(...) { return S_FALSE
; }
281 HRESULT
CBCJ2_x86_Decoder::CodeReal(ISequentialInStream
**inStreams
,
282 const UInt64
**inSizes
,
284 ISequentialOutStream
**outStreams
,
285 const UInt64
**outSizes
,
286 UInt32 numOutStreams
,
287 ICompressProgressInfo
*progress
)
289 if (numInStreams
!= 4 || numOutStreams
!= 1)
292 if (!_mainInStream
.Create(1 << 16))
293 return E_OUTOFMEMORY
;
294 if (!_callStream
.Create(1 << 20))
295 return E_OUTOFMEMORY
;
296 if (!_jumpStream
.Create(1 << 16))
297 return E_OUTOFMEMORY
;
298 if (!_rangeDecoder
.Create(1 << 20))
299 return E_OUTOFMEMORY
;
300 if (!_outStream
.Create(1 << 16))
301 return E_OUTOFMEMORY
;
303 _mainInStream
.SetStream(inStreams
[0]);
304 _callStream
.SetStream(inStreams
[1]);
305 _jumpStream
.SetStream(inStreams
[2]);
306 _rangeDecoder
.SetStream(inStreams
[3]);
307 _outStream
.SetStream(outStreams
[0]);
309 _mainInStream
.Init();
312 _rangeDecoder
.Init();
315 for (int i
= 0; i
< 256; i
++)
316 _statusE8Decoder
[i
].Init();
317 _statusE9Decoder
.Init();
318 _statusJccDecoder
.Init();
320 CCoderReleaser
releaser(this);
323 UInt32 processedBytes
= 0;
326 if (processedBytes
> (1 << 20) && progress
!= NULL
)
328 UInt64 nowPos64
= _outStream
.GetProcessedSize();
329 RINOK(progress
->SetRatioInfo(NULL
, &nowPos64
));
334 if (!_mainInStream
.ReadByte(b
))
336 _outStream
.WriteByte(b
);
337 if (b
!= 0xE8 && b
!= 0xE9 && !IsJcc(prevByte
, b
))
344 status
= (_statusE8Decoder
[prevByte
].Decode(&_rangeDecoder
) == 1);
346 status
= (_statusE9Decoder
.Decode(&_rangeDecoder
) == 1);
348 status
= (_statusJccDecoder
.Decode(&_rangeDecoder
) == 1);
355 if(!_callStream
.ReadByte(b0
))
357 src
= ((UInt32
)b0
) << 24;
358 if(!_callStream
.ReadByte(b0
))
360 src
|= ((UInt32
)b0
) << 16;
361 if(!_callStream
.ReadByte(b0
))
363 src
|= ((UInt32
)b0
) << 8;
364 if(!_callStream
.ReadByte(b0
))
371 if(!_jumpStream
.ReadByte(b0
))
373 src
= ((UInt32
)b0
) << 24;
374 if(!_jumpStream
.ReadByte(b0
))
376 src
|= ((UInt32
)b0
) << 16;
377 if(!_jumpStream
.ReadByte(b0
))
379 src
|= ((UInt32
)b0
) << 8;
380 if(!_jumpStream
.ReadByte(b0
))
384 UInt32 dest
= src
- (UInt32(_outStream
.GetProcessedSize()) + 4) ;
385 _outStream
.WriteByte((Byte
)(dest
));
386 _outStream
.WriteByte((Byte
)(dest
>> 8));
387 _outStream
.WriteByte((Byte
)(dest
>> 16));
388 _outStream
.WriteByte((Byte
)(dest
>> 24));
389 prevByte
= (dest
>> 24);
397 STDMETHODIMP
CBCJ2_x86_Decoder::Code(ISequentialInStream
**inStreams
,
398 const UInt64
**inSizes
,
400 ISequentialOutStream
**outStreams
,
401 const UInt64
**outSizes
,
402 UInt32 numOutStreams
,
403 ICompressProgressInfo
*progress
)
407 return CodeReal(inStreams
, inSizes
, numInStreams
,
408 outStreams
, outSizes
,numOutStreams
, progress
);
410 catch(const COutBufferException
&e
) { return e
.ErrorCode
; }
411 catch(...) { return S_FALSE
; }