~ubuntu-branches/ubuntu/precise/p7zip/precise-updates

« back to all changes in this revision

Viewing changes to CPP/7zip/Compress/LZMA/LZMADecoder.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Mohammed Adnène Trojette
  • Date: 2009-02-14 20:12:27 UTC
  • mfrom: (1.1.11 upstream) (2.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20090214201227-go63qxm9ozfdma60
Tags: 4.65~dfsg.1-1
* New upstream release.
* Remove wx2.8 Build-Depends added by mistakes (7zG is not yet
  intended to be built).
* Use dh_clean without -k.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// LZMADecoder.cpp
2
 
 
3
 
#include "StdAfx.h"
4
 
 
5
 
#include "LZMADecoder.h"
6
 
#include "../../../Common/Defs.h"
7
 
#include "../../Common/StreamUtils.h"
8
 
 
9
 
extern "C"
10
 
{
11
 
  #include "../../../../C/Alloc.h"
12
 
}
13
 
 
14
 
static HRESULT SResToHRESULT(SRes res)
15
 
{
16
 
  switch(res)
17
 
  {
18
 
    case SZ_OK: return S_OK;
19
 
    case SZ_ERROR_MEM: return E_OUTOFMEMORY;
20
 
    case SZ_ERROR_PARAM: return E_INVALIDARG;
21
 
    // case SZ_ERROR_PROGRESS: return E_ABORT;
22
 
    case SZ_ERROR_DATA: return S_FALSE;
23
 
  }
24
 
  return E_FAIL;
25
 
}
26
 
 
27
 
namespace NCompress {
28
 
namespace NLZMA {
29
 
 
30
 
static const UInt32 kInBufSize = 1 << 20;
31
 
 
32
 
CDecoder::CDecoder(): _inBuf(0), _outSizeDefined(false)
33
 
{
34
 
  LzmaDec_Construct(&_state);
35
 
}
36
 
 
37
 
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
38
 
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
39
 
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
40
 
 
41
 
CDecoder::~CDecoder()
42
 
{
43
 
  LzmaDec_Free(&_state, &g_Alloc);
44
 
  MyFree(_inBuf);
45
 
}
46
 
 
47
 
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size)
48
 
{
49
 
  RINOK(SResToHRESULT(LzmaDec_Allocate(&_state, prop, size, &g_Alloc)));
50
 
 
51
 
  if (_inBuf == 0)
52
 
  {
53
 
    _inBuf = (Byte *)MyAlloc(kInBufSize);
54
 
    if (_inBuf == 0)
55
 
      return E_OUTOFMEMORY;
56
 
  }
57
 
 
58
 
  return S_OK;
59
 
}
60
 
 
61
 
STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) { *value = _inSizeProcessed; return S_OK; }
62
 
STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; }
63
 
STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; }
64
 
 
65
 
STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
66
 
{
67
 
  _outSizeDefined = (outSize != NULL);
68
 
  if (_outSizeDefined)
69
 
    _outSize = *outSize;
70
 
 
71
 
  LzmaDec_Init(&_state);
72
 
  
73
 
  _inPos = _inSize = 0;
74
 
  _inSizeProcessed = _outSizeProcessed = 0;
75
 
  return S_OK;
76
 
}
77
 
 
78
 
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream,
79
 
    ISequentialOutStream *outStream, const UInt64 * /* inSize */, 
80
 
    const UInt64 *outSize, ICompressProgressInfo *progress)
81
 
{
82
 
  if (_inBuf == 0)
83
 
    return S_FALSE; 
84
 
  SetOutStreamSize(outSize);
85
 
 
86
 
  for (;;)
87
 
  {
88
 
    if (_inPos == _inSize)
89
 
    {
90
 
      _inPos = _inSize = 0;
91
 
      RINOK(inStream->Read(_inBuf, kInBufSize, &_inSize));
92
 
    }
93
 
 
94
 
    SizeT dicPos = _state.dicPos;
95
 
    SizeT curSize = _state.dicBufSize - dicPos;
96
 
    const UInt32 kStepSize = ((UInt32)1 << 22);
97
 
    if (curSize > kStepSize)
98
 
      curSize = (SizeT)kStepSize;
99
 
    
100
 
    ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
101
 
    if (_outSizeDefined)
102
 
    {
103
 
      const UInt64 rem = _outSize - _outSizeProcessed;
104
 
      if (rem < curSize)
105
 
      {
106
 
        curSize = (SizeT)rem;
107
 
        /* 
108
 
        // finishMode = LZMA_FINISH_END;
109
 
        we can't use LZMA_FINISH_END here to allow partial decoding
110
 
        */
111
 
      }
112
 
    }
113
 
 
114
 
    SizeT inSizeProcessed = _inSize - _inPos;
115
 
    ELzmaStatus status;
116
 
    SRes res = LzmaDec_DecodeToDic(&_state, dicPos + curSize, _inBuf + _inPos, &inSizeProcessed, finishMode, &status);
117
 
 
118
 
    _inPos += (UInt32)inSizeProcessed;
119
 
    _inSizeProcessed += inSizeProcessed;
120
 
    SizeT outSizeProcessed = _state.dicPos - dicPos;
121
 
    _outSizeProcessed += outSizeProcessed;
122
 
 
123
 
    bool finished = (inSizeProcessed == 0 && outSizeProcessed == 0);
124
 
    bool stopDecoding = (_outSizeDefined && _outSizeProcessed >= _outSize);
125
 
 
126
 
    if (res != 0 || _state.dicPos == _state.dicBufSize || finished || stopDecoding)
127
 
    {
128
 
      HRESULT res2 = WriteStream(outStream, _state.dic, _state.dicPos);
129
 
      if (res != 0)
130
 
        return S_FALSE;
131
 
      RINOK(res2);
132
 
      if (stopDecoding)
133
 
        return S_OK;
134
 
      if (finished)
135
 
        return (status == LZMA_STATUS_FINISHED_WITH_MARK ? S_OK : S_FALSE);
136
 
    }
137
 
    if (_state.dicPos == _state.dicBufSize)
138
 
      _state.dicPos = 0;
139
 
 
140
 
    if (progress != NULL)
141
 
    {
142
 
      RINOK(progress->SetRatioInfo(&_inSizeProcessed, &_outSizeProcessed));
143
 
    }
144
 
  } 
145
 
}
146
 
 
147
 
#ifndef NO_READ_FROM_CODER
148
 
 
149
 
STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)
150
 
{
151
 
  if (processedSize)
152
 
    *processedSize = 0;
153
 
  do
154
 
  {
155
 
    if (_inPos == _inSize)
156
 
    {
157
 
      _inPos = _inSize = 0;
158
 
      RINOK(_inStream->Read(_inBuf, kInBufSize, &_inSize));
159
 
    }
160
 
    {
161
 
      SizeT inProcessed = _inSize - _inPos;
162
 
 
163
 
      if (_outSizeDefined)
164
 
      {
165
 
        const UInt64 rem = _outSize - _outSizeProcessed;
166
 
        if (rem < size)
167
 
          size = (UInt32)rem;
168
 
      }
169
 
 
170
 
      SizeT outProcessed = size;
171
 
      ELzmaStatus status;
172
 
      SRes res = LzmaDec_DecodeToBuf(&_state, (Byte *)data, &outProcessed, 
173
 
          _inBuf + _inPos, &inProcessed, LZMA_FINISH_ANY, &status);
174
 
      _inPos += (UInt32)inProcessed;
175
 
      _inSizeProcessed += inProcessed;
176
 
      _outSizeProcessed += outProcessed;
177
 
      size -= (UInt32)outProcessed;
178
 
      data = (Byte *)data + outProcessed;
179
 
      if (processedSize)
180
 
        *processedSize += (UInt32)outProcessed;
181
 
      RINOK(SResToHRESULT(res));
182
 
      if (inProcessed == 0 && outProcessed == 0)
183
 
        return S_OK;
184
 
    }
185
 
  }
186
 
  while (size != 0);
187
 
  return S_OK;
188
 
}
189
 
 
190
 
#endif
191
 
 
192
 
}}