1// XzDecoder.cpp 2 3#include "StdAfx.h" 4 5#include "../../../C/Alloc.h" 6 7#include "../Common/CWrappers.h" 8 9#include "XzDecoder.h" 10 11namespace NCompress { 12namespace NXz { 13 14#define RET_IF_WRAP_ERROR_CONFIRMED(wrapRes, sRes, sResErrorCode) \ 15 if (wrapRes != S_OK && sRes == sResErrorCode) return wrapRes; 16 17#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \ 18 if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes; 19 20static HRESULT SResToHRESULT_Code(SRes res) throw() 21{ 22 if (res < 0) 23 return res; 24 switch (res) 25 { 26 case SZ_OK: return S_OK; 27 case SZ_ERROR_MEM: return E_OUTOFMEMORY; 28 case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL; 29 } 30 return S_FALSE; 31} 32 33 34HRESULT CDecoder::Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, 35 const UInt64 *outSizeLimit, bool finishStream, ICompressProgressInfo *progress) 36{ 37 MainDecodeSRes = SZ_OK; 38 MainDecodeSRes_wasUsed = false; 39 XzStatInfo_Clear(&Stat); 40 41 if (!xz) 42 { 43 xz = XzDecMt_Create(&g_Alloc, &g_MidAlloc); 44 if (!xz) 45 return E_OUTOFMEMORY; 46 } 47 48 CXzDecMtProps props; 49 XzDecMtProps_Init(&props); 50 51 int isMT = False; 52 53 #ifndef Z7_ST 54 { 55 props.numThreads = 1; 56 const UInt32 numThreads = _numThreads; 57 58 if (_tryMt && numThreads > 1) 59 { 60 size_t memUsage = (size_t)_memUsage; 61 if (memUsage != _memUsage) 62 memUsage = (size_t)0 - 1; 63 props.memUseMax = memUsage; 64 isMT = (numThreads > 1); 65 } 66 67 props.numThreads = numThreads; 68 } 69 #endif 70 71 CSeqInStreamWrap inWrap; 72 CSeqOutStreamWrap outWrap; 73 CCompressProgressWrap progressWrap; 74 75 inWrap.Init(seqInStream); 76 outWrap.Init(outStream); 77 progressWrap.Init(progress); 78 79 SRes res = XzDecMt_Decode(xz, 80 &props, 81 outSizeLimit, finishStream, 82 &outWrap.vt, 83 &inWrap.vt, 84 &Stat, 85 &isMT, 86 progress ? &progressWrap.vt : NULL); 87 88 MainDecodeSRes = res; 89 90 #ifndef Z7_ST 91 // _tryMt = isMT; 92 #endif 93 94 RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE) 95 RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS) 96 RET_IF_WRAP_ERROR_CONFIRMED(inWrap.Res, res, SZ_ERROR_READ) 97 98 // return E_OUTOFMEMORY; // for debug check 99 100 MainDecodeSRes_wasUsed = true; 101 102 if (res == SZ_OK && finishStream) 103 { 104 /* 105 if (inSize && *inSize != Stat.PhySize) 106 res = SZ_ERROR_DATA; 107 */ 108 if (outSizeLimit && *outSizeLimit != outWrap.Processed) 109 res = SZ_ERROR_DATA; 110 } 111 112 return SResToHRESULT_Code(res); 113} 114 115 116Z7_COM7F_IMF(CComDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, 117 const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)) 118{ 119 return Decode(inStream, outStream, outSize, _finishStream, progress); 120} 121 122Z7_COM7F_IMF(CComDecoder::SetFinishMode(UInt32 finishMode)) 123{ 124 _finishStream = (finishMode != 0); 125 return S_OK; 126} 127 128Z7_COM7F_IMF(CComDecoder::GetInStreamProcessedSize(UInt64 *value)) 129{ 130 *value = Stat.InSize; 131 return S_OK; 132} 133 134#ifndef Z7_ST 135 136Z7_COM7F_IMF(CComDecoder::SetNumberOfThreads(UInt32 numThreads)) 137{ 138 _numThreads = numThreads; 139 return S_OK; 140} 141 142Z7_COM7F_IMF(CComDecoder::SetMemLimit(UInt64 memUsage)) 143{ 144 _memUsage = memUsage; 145 return S_OK; 146} 147 148#endif 149 150}} 151