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
11 namespace NCompress {
12 namespace 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
SResToHRESULT_Code(SRes res)20 static 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
Decode(ISequentialInStream * seqInStream,ISequentialOutStream * outStream,const UInt64 * outSizeLimit,bool finishStream,ICompressProgressInfo * progress)34 HRESULT CDecoder::Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream,
35 const UInt64 *outSizeLimit, bool finishStream, ICompressProgressInfo *progress)
36 {
37 MainDecodeSRes = S_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 _7ZIP_ST
54 {
55 props.numThreads = 1;
56 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 _7ZIP_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;
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
Code(ISequentialInStream * inStream,ISequentialOutStream * outStream,const UInt64 *,const UInt64 * outSize,ICompressProgressInfo * progress)116 HRESULT 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
SetFinishMode(UInt32 finishMode)122 STDMETHODIMP CComDecoder::SetFinishMode(UInt32 finishMode)
123 {
124 _finishStream = (finishMode != 0);
125 return S_OK;
126 }
127
GetInStreamProcessedSize(UInt64 * value)128 STDMETHODIMP CComDecoder::GetInStreamProcessedSize(UInt64 *value)
129 {
130 *value = Stat.InSize;
131 return S_OK;
132 }
133
134 #ifndef _7ZIP_ST
135
SetNumberOfThreads(UInt32 numThreads)136 STDMETHODIMP CComDecoder::SetNumberOfThreads(UInt32 numThreads)
137 {
138 _numThreads = numThreads;
139 return S_OK;
140 }
141
SetMemLimit(UInt64 memUsage)142 STDMETHODIMP CComDecoder::SetMemLimit(UInt64 memUsage)
143 {
144 _memUsage = memUsage;
145 return S_OK;
146 }
147
148 #endif
149
150 }}
151