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