Annotation of elwix/tools/oldlzma/SRC/7zip/Compress/Branch/x86_2.cpp, revision 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>