BCM WL 6.30.102.9 (r366174)
[tomato.git] / release / src-rt / linux / linux-2.6 / scripts / squashfs / lzma / C / 7zip / Compress / Branch / x86_2.cpp
blobfc87bd937d31549757ada41c8c75dd805410c984
1 // x86_2.cpp
3 #include "StdAfx.h"
4 #include "x86_2.h"
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);
15 #ifndef EXTRACT_ONLY
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))
25 return false;
26 if (!_callStream.Create(1 << 20))
27 return false;
28 if (!_jumpStream.Create(1 << 20))
29 return false;
30 if (!_rangeEncoder.Create(1 << 20))
31 return false;
32 if (_buffer == 0)
34 _buffer = (Byte *)MidAlloc(kBufferSize);
35 if (_buffer == 0)
36 return false;
38 return true;
41 CBCJ2_x86_Encoder::~CBCJ2_x86_Encoder()
43 ::MidFree(_buffer);
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,
59 UInt32 numInStreams,
60 ISequentialOutStream **outStreams,
61 const UInt64 **outSizes,
62 UInt32 numOutStreams,
63 ICompressProgressInfo *progress)
65 if (numInStreams != 1 || numOutStreams != 4)
66 return E_INVALIDARG;
68 if (!Create())
69 return E_OUTOFMEMORY;
71 bool sizeIsDefined = false;
72 UInt64 inSize;
73 if (inSizes != NULL)
74 if (inSizes[0] != NULL)
76 inSize = *inSizes[0];
77 if (inSize <= kDefaultLimit)
78 sizeIsDefined = true;
81 ISequentialInStream *inStream = inStreams[0];
83 _mainStream.SetStream(outStreams[0]);
84 _mainStream.Init();
85 _callStream.SetStream(outStreams[1]);
86 _callStream.Init();
87 _jumpStream.SetStream(outStreams[2]);
88 _jumpStream.Init();
89 _rangeEncoder.SetStream(outStreams[3]);
90 _rangeEncoder.Init();
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);
102 UInt32 nowPos = 0;
103 UInt64 nowPos64 = 0;
104 UInt32 bufferPos = 0;
106 Byte prevByte = 0;
108 UInt64 subStreamIndex = 0;
109 UInt64 subStreamStartPos = 0;
110 UInt64 subStreamEndPos = 0;
112 while(true)
114 UInt32 processedSize = 0;
115 while(true)
117 UInt32 size = kBufferSize - (bufferPos + processedSize);
118 UInt32 processedSizeLoc;
119 if (size == 0)
120 break;
121 RINOK(inStream->Read(_buffer + bufferPos + processedSize, size, &processedSizeLoc));
122 if (processedSizeLoc == 0)
123 break;
124 processedSize += processedSizeLoc;
126 UInt32 endPos = bufferPos + processedSize;
128 if (endPos < 5)
130 // change it
131 for (bufferPos = 0; bufferPos < endPos; bufferPos++)
133 Byte b = _buffer[bufferPos];
134 _mainStream.WriteByte(b);
135 if (b == 0xE8)
136 _statusE8Encoder[prevByte].Encode(&_rangeEncoder, 0);
137 else if (b == 0xE9)
138 _statusE9Encoder.Encode(&_rangeEncoder, 0);
139 else if (IsJcc(prevByte, b))
140 _statusJccEncoder.Encode(&_rangeEncoder, 0);
141 prevByte = b;
143 return Flush();
146 bufferPos = 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))
155 bufferPos++;
156 prevByte = b;
157 continue;
159 Byte nextByte = _buffer[bufferPos + 4];
160 UInt32 src =
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))
167 bool convert;
168 if (getSubStreamSize != NULL)
170 UInt64 currentPos = (nowPos64 + bufferPos);
171 while (subStreamEndPos < currentPos)
173 UInt64 subStreamSize;
174 HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize);
175 if (result == S_OK)
177 subStreamStartPos = subStreamEndPos;
178 subStreamEndPos += subStreamSize;
179 subStreamIndex++;
181 else if (result == S_FALSE || result == E_NOTIMPL)
183 getSubStreamSize.Release();
184 subStreamStartPos = 0;
185 subStreamEndPos = subStreamStartPos - 1;
187 else
188 return result;
190 if (getSubStreamSize == NULL)
192 if (sizeIsDefined)
193 convert = (dest < inSize);
194 else
195 convert = Test86MSByte(nextByte);
197 else if (subStreamEndPos - subStreamStartPos > kDefaultLimit)
198 convert = Test86MSByte(nextByte);
199 else
201 UInt64 dest64 = (currentPos + 5) + Int64(Int32(src));
202 convert = (dest64 >= subStreamStartPos && dest64 < subStreamEndPos);
205 else if (sizeIsDefined)
206 convert = (dest < inSize);
207 else
208 convert = Test86MSByte(nextByte);
209 if (convert)
211 if (b == 0xE8)
212 _statusE8Encoder[prevByte].Encode(&_rangeEncoder, 1);
213 else if (b == 0xE9)
214 _statusE9Encoder.Encode(&_rangeEncoder, 1);
215 else
216 _statusJccEncoder.Encode(&_rangeEncoder, 1);
218 bufferPos += 5;
219 if (b == 0xE8)
221 _callStream.WriteByte((Byte)(dest >> 24));
222 _callStream.WriteByte((Byte)(dest >> 16));
223 _callStream.WriteByte((Byte)(dest >> 8));
224 _callStream.WriteByte((Byte)(dest));
226 else
228 _jumpStream.WriteByte((Byte)(dest >> 24));
229 _jumpStream.WriteByte((Byte)(dest >> 16));
230 _jumpStream.WriteByte((Byte)(dest >> 8));
231 _jumpStream.WriteByte((Byte)(dest));
233 prevByte = nextByte;
235 else
237 if (b == 0xE8)
238 _statusE8Encoder[prevByte].Encode(&_rangeEncoder, 0);
239 else if (b == 0xE9)
240 _statusE9Encoder.Encode(&_rangeEncoder, 0);
241 else
242 _statusJccEncoder.Encode(&_rangeEncoder, 0);
243 bufferPos++;
244 prevByte = b;
247 nowPos += bufferPos;
248 nowPos64 += bufferPos;
250 if (progress != NULL)
252 RINOK(progress->SetRatioInfo(&nowPos64, NULL));
255 UInt32 i = 0;
256 while(bufferPos < endPos)
257 _buffer[i++] = _buffer[bufferPos++];
258 bufferPos = i;
262 STDMETHODIMP CBCJ2_x86_Encoder::Code(ISequentialInStream **inStreams,
263 const UInt64 **inSizes,
264 UInt32 numInStreams,
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; }
279 #endif
281 HRESULT CBCJ2_x86_Decoder::CodeReal(ISequentialInStream **inStreams,
282 const UInt64 **inSizes,
283 UInt32 numInStreams,
284 ISequentialOutStream **outStreams,
285 const UInt64 **outSizes,
286 UInt32 numOutStreams,
287 ICompressProgressInfo *progress)
289 if (numInStreams != 4 || numOutStreams != 1)
290 return E_INVALIDARG;
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();
310 _callStream.Init();
311 _jumpStream.Init();
312 _rangeDecoder.Init();
313 _outStream.Init();
315 for (int i = 0; i < 256; i++)
316 _statusE8Decoder[i].Init();
317 _statusE9Decoder.Init();
318 _statusJccDecoder.Init();
320 CCoderReleaser releaser(this);
322 Byte prevByte = 0;
323 UInt32 processedBytes = 0;
324 while(true)
326 if (processedBytes > (1 << 20) && progress != NULL)
328 UInt64 nowPos64 = _outStream.GetProcessedSize();
329 RINOK(progress->SetRatioInfo(NULL, &nowPos64));
330 processedBytes = 0;
332 processedBytes++;
333 Byte b;
334 if (!_mainInStream.ReadByte(b))
335 return Flush();
336 _outStream.WriteByte(b);
337 if (b != 0xE8 && b != 0xE9 && !IsJcc(prevByte, b))
339 prevByte = b;
340 continue;
342 bool status;
343 if (b == 0xE8)
344 status = (_statusE8Decoder[prevByte].Decode(&_rangeDecoder) == 1);
345 else if (b == 0xE9)
346 status = (_statusE9Decoder.Decode(&_rangeDecoder) == 1);
347 else
348 status = (_statusJccDecoder.Decode(&_rangeDecoder) == 1);
349 if (status)
351 UInt32 src;
352 if (b == 0xE8)
354 Byte b0;
355 if(!_callStream.ReadByte(b0))
356 return S_FALSE;
357 src = ((UInt32)b0) << 24;
358 if(!_callStream.ReadByte(b0))
359 return S_FALSE;
360 src |= ((UInt32)b0) << 16;
361 if(!_callStream.ReadByte(b0))
362 return S_FALSE;
363 src |= ((UInt32)b0) << 8;
364 if(!_callStream.ReadByte(b0))
365 return S_FALSE;
366 src |= ((UInt32)b0);
368 else
370 Byte b0;
371 if(!_jumpStream.ReadByte(b0))
372 return S_FALSE;
373 src = ((UInt32)b0) << 24;
374 if(!_jumpStream.ReadByte(b0))
375 return S_FALSE;
376 src |= ((UInt32)b0) << 16;
377 if(!_jumpStream.ReadByte(b0))
378 return S_FALSE;
379 src |= ((UInt32)b0) << 8;
380 if(!_jumpStream.ReadByte(b0))
381 return S_FALSE;
382 src |= ((UInt32)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);
390 processedBytes += 4;
392 else
393 prevByte = b;
397 STDMETHODIMP CBCJ2_x86_Decoder::Code(ISequentialInStream **inStreams,
398 const UInt64 **inSizes,
399 UInt32 numInStreams,
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; }