Annotation of elwix/tools/oldlzma/SRC/7zip/Compress/Branch/x86_2.cpp, revision 1.1.1.1
1.1 misho 1: // x86_2.cpp
2:
3: #include "StdAfx.h"
4: #include "x86_2.h"
5:
6: #include "../../../Common/Alloc.h"
7:
8: static const int kBufferSize = 1 << 17;
9:
10: inline bool IsJcc(Byte b0, Byte b1)
11: {
12: return (b0 == 0x0F && (b1 & 0xF0) == 0x80);
13: }
14:
15: #ifndef EXTRACT_ONLY
16:
17: static bool inline Test86MSByte(Byte b)
18: {
19: return (b == 0 || b == 0xFF);
20: }
21:
22: bool CBCJ2_x86_Encoder::Create()
23: {
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)
33: {
34: _buffer = (Byte *)BigAlloc(kBufferSize);
35: if (_buffer == 0)
36: return false;
37: }
38: return true;
39: }
40:
41: CBCJ2_x86_Encoder::~CBCJ2_x86_Encoder()
42: {
43: BigFree(_buffer);
44: }
45:
46: HRESULT CBCJ2_x86_Encoder::Flush()
47: {
48: RINOK(_mainStream.Flush());
49: RINOK(_callStream.Flush());
50: RINOK(_jumpStream.Flush());
51: _rangeEncoder.FlushData();
52: return _rangeEncoder.FlushStream();
53: }
54:
55: const UInt32 kDefaultLimit = (1 << 24);
56:
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)
64: {
65: if (numInStreams != 1 || numOutStreams != 4)
66: return E_INVALIDARG;
67:
68: if (!Create())
69: return E_OUTOFMEMORY;
70:
71: bool sizeIsDefined = false;
72: UInt64 inSize;
73: if (inSizes != NULL)
74: if (inSizes[0] != NULL)
75: {
76: inSize = *inSizes[0];
77: if (inSize <= kDefaultLimit)
78: sizeIsDefined = true;
79: }
80:
81: ISequentialInStream *inStream = inStreams[0];
82:
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);
96:
97: CMyComPtr<ICompressGetSubStreamSize> getSubStreamSize;
98: {
99: inStream->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize);
100: }
101:
102: UInt32 nowPos = 0;
103: UInt64 nowPos64 = 0;
104: UInt32 bufferPos = 0;
105: UInt32 processedSize;
106:
107: Byte prevByte = 0;
108:
109: UInt64 subStreamIndex = 0;
110: UInt64 subStreamStartPos = 0;
111: UInt64 subStreamEndPos = 0;
112:
113: while(true)
114: {
115: UInt32 size = kBufferSize - bufferPos;
116: RINOK(inStream->Read(_buffer + bufferPos, size, &processedSize));
117: UInt32 endPos = bufferPos + processedSize;
118:
119: if (endPos < 5)
120: {
121: // change it
122: for (bufferPos = 0; bufferPos < endPos; bufferPos++)
123: {
124: Byte b = _buffer[bufferPos];
125: _mainStream.WriteByte(b);
126: if (b == 0xE8)
127: _statusE8Encoder[prevByte].Encode(&_rangeEncoder, 0);
128: else if (b == 0xE9)
129: _statusE9Encoder.Encode(&_rangeEncoder, 0);
130: else if (IsJcc(prevByte, b))
131: _statusJccEncoder.Encode(&_rangeEncoder, 0);
132: prevByte = b;
133: }
134: return Flush();
135: }
136:
137: bufferPos = 0;
138:
139: UInt32 limit = endPos - 5;
140: while(bufferPos <= limit)
141: {
142: Byte b = _buffer[bufferPos];
143: _mainStream.WriteByte(b);
144: if (b != 0xE8 && b != 0xE9 && !IsJcc(prevByte, b))
145: {
146: bufferPos++;
147: prevByte = b;
148: continue;
149: }
150: Byte nextByte = _buffer[bufferPos + 4];
151: UInt32 src =
152: (UInt32(nextByte) << 24) |
153: (UInt32(_buffer[bufferPos + 3]) << 16) |
154: (UInt32(_buffer[bufferPos + 2]) << 8) |
155: (_buffer[bufferPos + 1]);
156: UInt32 dest = (nowPos + bufferPos + 5) + src;
157: // if (Test86MSByte(nextByte))
158: bool convert;
159: if (getSubStreamSize != NULL)
160: {
161: UInt64 currentPos = (nowPos64 + bufferPos);
162: while (subStreamEndPos < currentPos)
163: {
164: UInt64 subStreamSize;
165: HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize);
166: if (result == S_OK)
167: {
168: subStreamStartPos = subStreamEndPos;
169: subStreamEndPos += subStreamSize;
170: subStreamIndex++;
171: }
172: else if (result == S_FALSE || result == E_NOTIMPL)
173: {
174: getSubStreamSize.Release();
175: subStreamStartPos = 0;
176: subStreamEndPos = subStreamStartPos - 1;
177: }
178: else
179: return result;
180: }
181: if (getSubStreamSize == NULL)
182: {
183: if (sizeIsDefined)
184: convert = (dest < inSize);
185: else
186: convert = Test86MSByte(nextByte);
187: }
188: else if (subStreamEndPos - subStreamStartPos > kDefaultLimit)
189: convert = Test86MSByte(nextByte);
190: else
191: {
192: UInt64 dest64 = (currentPos + 5) + Int64(Int32(src));
193: convert = (dest64 >= subStreamStartPos && dest64 < subStreamEndPos);
194: }
195: }
196: else if (sizeIsDefined)
197: convert = (dest < inSize);
198: else
199: convert = Test86MSByte(nextByte);
200: if (convert)
201: {
202: if (b == 0xE8)
203: _statusE8Encoder[prevByte].Encode(&_rangeEncoder, 1);
204: else if (b == 0xE9)
205: _statusE9Encoder.Encode(&_rangeEncoder, 1);
206: else
207: _statusJccEncoder.Encode(&_rangeEncoder, 1);
208:
209: bufferPos += 5;
210: if (b == 0xE8)
211: {
212: _callStream.WriteByte((Byte)(dest >> 24));
213: _callStream.WriteByte((Byte)(dest >> 16));
214: _callStream.WriteByte((Byte)(dest >> 8));
215: _callStream.WriteByte((Byte)(dest));
216: }
217: else
218: {
219: _jumpStream.WriteByte((Byte)(dest >> 24));
220: _jumpStream.WriteByte((Byte)(dest >> 16));
221: _jumpStream.WriteByte((Byte)(dest >> 8));
222: _jumpStream.WriteByte((Byte)(dest));
223: }
224: prevByte = nextByte;
225: }
226: else
227: {
228: if (b == 0xE8)
229: _statusE8Encoder[prevByte].Encode(&_rangeEncoder, 0);
230: else if (b == 0xE9)
231: _statusE9Encoder.Encode(&_rangeEncoder, 0);
232: else
233: _statusJccEncoder.Encode(&_rangeEncoder, 0);
234: bufferPos++;
235: prevByte = b;
236: }
237: }
238: nowPos += bufferPos;
239: nowPos64 += bufferPos;
240:
241: if (progress != NULL)
242: {
243: RINOK(progress->SetRatioInfo(&nowPos64, NULL));
244: }
245:
246: UInt32 i = 0;
247: while(bufferPos < endPos)
248: _buffer[i++] = _buffer[bufferPos++];
249: bufferPos = i;
250: }
251: }
252:
253: STDMETHODIMP CBCJ2_x86_Encoder::Code(ISequentialInStream **inStreams,
254: const UInt64 **inSizes,
255: UInt32 numInStreams,
256: ISequentialOutStream **outStreams,
257: const UInt64 **outSizes,
258: UInt32 numOutStreams,
259: ICompressProgressInfo *progress)
260: {
261: try
262: {
263: return CodeReal(inStreams, inSizes, numInStreams,
264: outStreams, outSizes,numOutStreams, progress);
265: }
266: catch(const COutBufferException &e) { return e.ErrorCode; }
267: catch(...) { return S_FALSE; }
268: }
269:
270: #endif
271:
272: HRESULT CBCJ2_x86_Decoder::CodeReal(ISequentialInStream **inStreams,
273: const UInt64 **inSizes,
274: UInt32 numInStreams,
275: ISequentialOutStream **outStreams,
276: const UInt64 **outSizes,
277: UInt32 numOutStreams,
278: ICompressProgressInfo *progress)
279: {
280: if (numInStreams != 4 || numOutStreams != 1)
281: return E_INVALIDARG;
282:
283: if (!_mainInStream.Create(1 << 16))
284: return E_OUTOFMEMORY;
285: if (!_callStream.Create(1 << 20))
286: return E_OUTOFMEMORY;
287: if (!_jumpStream.Create(1 << 16))
288: return E_OUTOFMEMORY;
289: if (!_rangeDecoder.Create(1 << 20))
290: return E_OUTOFMEMORY;
291: if (!_outStream.Create(1 << 16))
292: return E_OUTOFMEMORY;
293:
294: _mainInStream.SetStream(inStreams[0]);
295: _callStream.SetStream(inStreams[1]);
296: _jumpStream.SetStream(inStreams[2]);
297: _rangeDecoder.SetStream(inStreams[3]);
298: _outStream.SetStream(outStreams[0]);
299:
300: _mainInStream.Init();
301: _callStream.Init();
302: _jumpStream.Init();
303: _rangeDecoder.Init();
304: _outStream.Init();
305:
306: for (int i = 0; i < 256; i++)
307: _statusE8Decoder[i].Init();
308: _statusE9Decoder.Init();
309: _statusJccDecoder.Init();
310:
311: CCoderReleaser releaser(this);
312:
313: Byte prevByte = 0;
314: UInt32 processedBytes = 0;
315: while(true)
316: {
317: if (processedBytes > (1 << 20) && progress != NULL)
318: {
319: UInt64 nowPos64 = _outStream.GetProcessedSize();
320: RINOK(progress->SetRatioInfo(NULL, &nowPos64));
321: processedBytes = 0;
322: }
323: processedBytes++;
324: Byte b;
325: if (!_mainInStream.ReadByte(b))
326: return Flush();
327: _outStream.WriteByte(b);
328: if (b != 0xE8 && b != 0xE9 && !IsJcc(prevByte, b))
329: {
330: prevByte = b;
331: continue;
332: }
333: bool status;
334: if (b == 0xE8)
335: status = (_statusE8Decoder[prevByte].Decode(&_rangeDecoder) == 1);
336: else if (b == 0xE9)
337: status = (_statusE9Decoder.Decode(&_rangeDecoder) == 1);
338: else
339: status = (_statusJccDecoder.Decode(&_rangeDecoder) == 1);
340: if (status)
341: {
342: UInt32 src;
343: if (b == 0xE8)
344: {
345: Byte b0;
346: if(!_callStream.ReadByte(b0))
347: return S_FALSE;
348: src = ((UInt32)b0) << 24;
349: if(!_callStream.ReadByte(b0))
350: return S_FALSE;
351: src |= ((UInt32)b0) << 16;
352: if(!_callStream.ReadByte(b0))
353: return S_FALSE;
354: src |= ((UInt32)b0) << 8;
355: if(!_callStream.ReadByte(b0))
356: return S_FALSE;
357: src |= ((UInt32)b0);
358: }
359: else
360: {
361: Byte b0;
362: if(!_jumpStream.ReadByte(b0))
363: return S_FALSE;
364: src = ((UInt32)b0) << 24;
365: if(!_jumpStream.ReadByte(b0))
366: return S_FALSE;
367: src |= ((UInt32)b0) << 16;
368: if(!_jumpStream.ReadByte(b0))
369: return S_FALSE;
370: src |= ((UInt32)b0) << 8;
371: if(!_jumpStream.ReadByte(b0))
372: return S_FALSE;
373: src |= ((UInt32)b0);
374: }
375: UInt32 dest = src - (UInt32(_outStream.GetProcessedSize()) + 4) ;
376: _outStream.WriteByte((Byte)(dest));
377: _outStream.WriteByte((Byte)(dest >> 8));
378: _outStream.WriteByte((Byte)(dest >> 16));
379: _outStream.WriteByte((Byte)(dest >> 24));
380: prevByte = (dest >> 24);
381: processedBytes += 4;
382: }
383: else
384: prevByte = b;
385: }
386: }
387:
388: STDMETHODIMP CBCJ2_x86_Decoder::Code(ISequentialInStream **inStreams,
389: const UInt64 **inSizes,
390: UInt32 numInStreams,
391: ISequentialOutStream **outStreams,
392: const UInt64 **outSizes,
393: UInt32 numOutStreams,
394: ICompressProgressInfo *progress)
395: {
396: try
397: {
398: return CodeReal(inStreams, inSizes, numInStreams,
399: outStreams, outSizes,numOutStreams, progress);
400: }
401: catch(const COutBufferException &e) { return e.ErrorCode; }
402: catch(...) { return S_FALSE; }
403: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>