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 default: break;
30 }
31 return S_FALSE;
32 }
33
34
Decode(ISequentialInStream * seqInStream,ISequentialOutStream * outStream,const UInt64 * outSizeLimit,bool finishStream,ICompressProgressInfo * progress)35 HRESULT CDecoder::Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream,
36 const UInt64 *outSizeLimit, bool finishStream, ICompressProgressInfo *progress)
37 {
38 MainDecodeSRes = SZ_OK;
39 MainDecodeSRes_wasUsed = false;
40 XzStatInfo_Clear(&Stat);
41
42 if (!xz)
43 {
44 xz = XzDecMt_Create(&g_Alloc, &g_MidAlloc);
45 if (!xz)
46 return E_OUTOFMEMORY;
47 }
48
49 CXzDecMtProps props;
50 XzDecMtProps_Init(&props);
51
52 int isMT = False;
53
54 #ifndef Z7_ST
55 {
56 props.numThreads = 1;
57 const UInt32 numThreads = _numThreads;
58
59 if (_tryMt && numThreads > 1)
60 {
61 size_t memUsage = (size_t)_memUsage;
62 if (memUsage != _memUsage)
63 memUsage = (size_t)0 - 1;
64 props.memUseMax = memUsage;
65 isMT = (numThreads > 1);
66 }
67
68 props.numThreads = numThreads;
69 }
70 #endif
71
72 CSeqInStreamWrap inWrap;
73 CSeqOutStreamWrap outWrap;
74 CCompressProgressWrap progressWrap;
75
76 inWrap.Init(seqInStream);
77 outWrap.Init(outStream);
78 progressWrap.Init(progress);
79
80 SRes res = XzDecMt_Decode(xz,
81 &props,
82 outSizeLimit, finishStream,
83 &outWrap.vt,
84 &inWrap.vt,
85 &Stat,
86 &isMT,
87 progress ? &progressWrap.vt : NULL);
88
89 MainDecodeSRes = res;
90
91 #ifndef Z7_ST
92 // _tryMt = isMT;
93 #endif
94
95 RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE)
96 RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS)
97 RET_IF_WRAP_ERROR_CONFIRMED(inWrap.Res, res, SZ_ERROR_READ)
98
99 // return E_OUTOFMEMORY; // for debug check
100
101 MainDecodeSRes_wasUsed = true;
102
103 if (res == SZ_OK && finishStream)
104 {
105 /*
106 if (inSize && *inSize != Stat.PhySize)
107 res = SZ_ERROR_DATA;
108 */
109 if (outSizeLimit && *outSizeLimit != outWrap.Processed)
110 res = SZ_ERROR_DATA;
111 }
112
113 return SResToHRESULT_Code(res);
114 }
115
116
Z7_COM7F_IMF(CComDecoder::Code (ISequentialInStream * inStream,ISequentialOutStream * outStream,const UInt64 *,const UInt64 * outSize,ICompressProgressInfo * progress))117 Z7_COM7F_IMF(CComDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
118 const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress))
119 {
120 return Decode(inStream, outStream, outSize, _finishStream, progress);
121 }
122
Z7_COM7F_IMF(CComDecoder::SetFinishMode (UInt32 finishMode))123 Z7_COM7F_IMF(CComDecoder::SetFinishMode(UInt32 finishMode))
124 {
125 _finishStream = (finishMode != 0);
126 return S_OK;
127 }
128
Z7_COM7F_IMF(CComDecoder::GetInStreamProcessedSize (UInt64 * value))129 Z7_COM7F_IMF(CComDecoder::GetInStreamProcessedSize(UInt64 *value))
130 {
131 *value = Stat.InSize;
132 return S_OK;
133 }
134
135 #ifndef Z7_ST
136
Z7_COM7F_IMF(CComDecoder::SetNumberOfThreads (UInt32 numThreads))137 Z7_COM7F_IMF(CComDecoder::SetNumberOfThreads(UInt32 numThreads))
138 {
139 _numThreads = numThreads;
140 return S_OK;
141 }
142
Z7_COM7F_IMF(CComDecoder::SetMemLimit (UInt64 memUsage))143 Z7_COM7F_IMF(CComDecoder::SetMemLimit(UInt64 memUsage))
144 {
145 _memUsage = memUsage;
146 return S_OK;
147 }
148
149 #endif
150
151 }}
152