Mercurial > vba-linux
comparison src/win32/7zip/7z/CPP/7zip/Compress/PpmdDecoder.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:8ced16adf2e1 | 1:f9f4f1b99eed |
---|---|
1 // PpmdDecoder.cpp | |
2 | |
3 #include "StdAfx.h" | |
4 | |
5 #include "Common/Defs.h" | |
6 #include "Windows/Defs.h" | |
7 | |
8 #include "PpmdDecoder.h" | |
9 | |
10 namespace NCompress { | |
11 namespace NPpmd { | |
12 | |
13 const int kLenIdFinished = -1; | |
14 const int kLenIdNeedInit = -2; | |
15 | |
16 STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size) | |
17 { | |
18 if (size < 5) | |
19 return E_INVALIDARG; | |
20 _order = properties[0]; | |
21 _usedMemorySize = 0; | |
22 for (int i = 0; i < 4; i++) | |
23 _usedMemorySize += ((UInt32)(properties[1 + i])) << (i * 8); | |
24 | |
25 if (_usedMemorySize > kMaxMemBlockSize) | |
26 return E_NOTIMPL; | |
27 | |
28 if (!_rangeDecoder.Create(1 << 20)) | |
29 return E_OUTOFMEMORY; | |
30 if (!_info.SubAllocator.StartSubAllocator(_usedMemorySize)) | |
31 return E_OUTOFMEMORY; | |
32 | |
33 return S_OK; | |
34 } | |
35 | |
36 class CDecoderFlusher | |
37 { | |
38 CDecoder *_coder; | |
39 public: | |
40 bool NeedFlush; | |
41 CDecoderFlusher(CDecoder *coder): _coder(coder), NeedFlush(true) {} | |
42 ~CDecoderFlusher() | |
43 { | |
44 if (NeedFlush) | |
45 _coder->Flush(); | |
46 _coder->ReleaseStreams(); | |
47 } | |
48 }; | |
49 | |
50 HRESULT CDecoder::CodeSpec(UInt32 size, Byte *memStream) | |
51 { | |
52 if (_outSizeDefined) | |
53 { | |
54 const UInt64 rem = _outSize - _processedSize; | |
55 if (size > rem) | |
56 size = (UInt32)rem; | |
57 } | |
58 const UInt32 startSize = size; | |
59 | |
60 if (_remainLen == kLenIdFinished) | |
61 return S_OK; | |
62 if (_remainLen == kLenIdNeedInit) | |
63 { | |
64 _rangeDecoder.Init(); | |
65 _remainLen = 0; | |
66 _info.MaxOrder = 0; | |
67 _info.StartModelRare(_order); | |
68 } | |
69 while (size != 0) | |
70 { | |
71 int symbol = _info.DecodeSymbol(&_rangeDecoder); | |
72 if (symbol < 0) | |
73 { | |
74 _remainLen = kLenIdFinished; | |
75 break; | |
76 } | |
77 if (memStream != 0) | |
78 *memStream++ = (Byte)symbol; | |
79 else | |
80 _outStream.WriteByte((Byte)symbol); | |
81 size--; | |
82 } | |
83 _processedSize += startSize - size; | |
84 return S_OK; | |
85 } | |
86 | |
87 STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, | |
88 const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) | |
89 { | |
90 if (!_outStream.Create(1 << 20)) | |
91 return E_OUTOFMEMORY; | |
92 | |
93 SetInStream(inStream); | |
94 _outStream.SetStream(outStream); | |
95 SetOutStreamSize(outSize); | |
96 CDecoderFlusher flusher(this); | |
97 | |
98 for (;;) | |
99 { | |
100 _processedSize = _outStream.GetProcessedSize(); | |
101 UInt32 curSize = (1 << 18); | |
102 RINOK(CodeSpec(curSize, NULL)); | |
103 if (_remainLen == kLenIdFinished) | |
104 break; | |
105 if (progress != NULL) | |
106 { | |
107 UInt64 inSize = _rangeDecoder.GetProcessedSize(); | |
108 RINOK(progress->SetRatioInfo(&inSize, &_processedSize)); | |
109 } | |
110 if (_outSizeDefined) | |
111 if (_outStream.GetProcessedSize() >= _outSize) | |
112 break; | |
113 } | |
114 flusher.NeedFlush = false; | |
115 return Flush(); | |
116 } | |
117 | |
118 #ifdef _NO_EXCEPTIONS | |
119 | |
120 #define PPMD_TRY_BEGIN | |
121 #define PPMD_TRY_END | |
122 | |
123 #else | |
124 | |
125 #define PPMD_TRY_BEGIN try { | |
126 #define PPMD_TRY_END } \ | |
127 catch(const CInBufferException &e) { return e.ErrorCode; } \ | |
128 catch(const COutBufferException &e) { return e.ErrorCode; } \ | |
129 catch(...) { return S_FALSE; } | |
130 | |
131 #endif | |
132 | |
133 | |
134 STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, | |
135 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) | |
136 { | |
137 PPMD_TRY_BEGIN | |
138 return CodeReal(inStream, outStream, inSize, outSize, progress); | |
139 PPMD_TRY_END | |
140 } | |
141 | |
142 STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) | |
143 { | |
144 _rangeDecoder.SetStream(inStream); | |
145 return S_OK; | |
146 } | |
147 | |
148 STDMETHODIMP CDecoder::ReleaseInStream() | |
149 { | |
150 _rangeDecoder.ReleaseStream(); | |
151 return S_OK; | |
152 } | |
153 | |
154 STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) | |
155 { | |
156 _outSizeDefined = (outSize != NULL); | |
157 if (_outSizeDefined) | |
158 _outSize = *outSize; | |
159 _processedSize = 0; | |
160 _remainLen = kLenIdNeedInit; | |
161 _outStream.Init(); | |
162 return S_OK; | |
163 } | |
164 | |
165 #ifndef NO_READ_FROM_CODER | |
166 | |
167 STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) | |
168 { | |
169 PPMD_TRY_BEGIN | |
170 if (processedSize) | |
171 *processedSize = 0; | |
172 const UInt64 startPos = _processedSize; | |
173 RINOK(CodeSpec(size, (Byte *)data)); | |
174 if (processedSize) | |
175 *processedSize = (UInt32)(_processedSize - startPos); | |
176 return Flush(); | |
177 PPMD_TRY_END | |
178 } | |
179 | |
180 #endif | |
181 | |
182 }} |