Upload 2.0.2
[physicsfs] / lzma / CPP / 7zip / Common / FilterCoder.cpp
1 // FilterCoder.cpp
2
3 #include "StdAfx.h"
4
5 #include "FilterCoder.h"
6 extern "C" 
7
8 #include "../../../C/Alloc.h"
9 }
10 #include "../../Common/Defs.h"
11 #include "StreamUtils.h"
12
13 static const UInt32 kBufferSize = 1 << 17;
14
15 CFilterCoder::CFilterCoder()
16
17   _buffer = (Byte *)::MidAlloc(kBufferSize); 
18 }
19
20 CFilterCoder::~CFilterCoder() 
21
22   ::MidFree(_buffer); 
23 }
24
25 HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 size)
26 {
27   if (_outSizeIsDefined)
28   {
29     UInt64 remSize = _outSize - _nowPos64;
30     if (size > remSize)
31       size = (UInt32)remSize;
32   }
33   UInt32 processedSize = 0;
34   RINOK(WriteStream(outStream, _buffer, size, &processedSize));
35   if (size != processedSize)
36     return E_FAIL;
37   _nowPos64 += processedSize;
38   return S_OK;
39 }
40
41
42 STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream,
43       ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize,
44       ICompressProgressInfo *progress)
45 {
46   RINOK(Init());
47   UInt32 bufferPos = 0;
48   _outSizeIsDefined = (outSize != 0);
49   if (_outSizeIsDefined)
50     _outSize = *outSize;
51
52   while(NeedMore())
53   {
54     UInt32 processedSize;
55     
56     // Change it: It can be optimized using ReadPart
57     RINOK(ReadStream(inStream, _buffer + bufferPos, kBufferSize - bufferPos, &processedSize));
58     
59     UInt32 endPos = bufferPos + processedSize;
60
61     bufferPos = Filter->Filter(_buffer, endPos);
62     if (bufferPos > endPos)
63     {
64       for (; endPos< bufferPos; endPos++)
65         _buffer[endPos] = 0;
66       bufferPos = Filter->Filter(_buffer, endPos);
67     }
68
69     if (bufferPos == 0)
70     {
71       if (endPos > 0)
72         return WriteWithLimit(outStream, endPos);
73       return S_OK;
74     }
75     RINOK(WriteWithLimit(outStream, bufferPos));
76     if (progress != NULL)
77     {
78       RINOK(progress->SetRatioInfo(&_nowPos64, &_nowPos64));
79     }
80     UInt32 i = 0;
81     while(bufferPos < endPos)
82       _buffer[i++] = _buffer[bufferPos++];
83     bufferPos = i;
84   }
85   return S_OK;
86 }
87
88 // #ifdef _ST_MODE
89 STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream)
90 {
91   _bufferPos = 0;
92   _outStream = outStream;
93   return Init();
94 }
95
96 STDMETHODIMP CFilterCoder::ReleaseOutStream()
97 {
98   _outStream.Release();
99   return S_OK;
100 };
101
102
103 STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize)
104 {
105   UInt32 processedSizeTotal = 0;
106   while(size > 0)
107   {
108     UInt32 sizeMax = kBufferSize - _bufferPos;
109     UInt32 sizeTemp = size;
110     if (sizeTemp > sizeMax)
111       sizeTemp = sizeMax;
112     memmove(_buffer + _bufferPos, data, sizeTemp);
113     size -= sizeTemp;
114     processedSizeTotal += sizeTemp;
115     data = (const Byte *)data + sizeTemp;
116     UInt32 endPos = _bufferPos + sizeTemp;
117     _bufferPos = Filter->Filter(_buffer, endPos);
118     if (_bufferPos == 0)
119     {
120       _bufferPos = endPos;
121       break;
122     }
123     if (_bufferPos > endPos)
124     {
125       if (size != 0)
126         return E_FAIL;
127       break;
128     }
129     RINOK(WriteWithLimit(_outStream, _bufferPos));
130     UInt32 i = 0;
131     while(_bufferPos < endPos)
132       _buffer[i++] = _buffer[_bufferPos++];
133     _bufferPos = i;
134   }
135   if (processedSize != NULL)
136     *processedSize = processedSizeTotal;
137   return S_OK;
138 }
139
140 STDMETHODIMP CFilterCoder::Flush()
141 {
142   if (_bufferPos != 0)
143   {
144     UInt32 endPos = Filter->Filter(_buffer, _bufferPos);
145     if (endPos > _bufferPos)
146     {
147       for (; _bufferPos < endPos; _bufferPos++)
148         _buffer[_bufferPos] = 0;
149       if (Filter->Filter(_buffer, endPos) != endPos)
150         return E_FAIL;
151     }
152     UInt32 processedSize;
153     RINOK(WriteStream(_outStream, _buffer, _bufferPos, &processedSize));
154     if (_bufferPos != processedSize)
155       return E_FAIL;
156     _bufferPos = 0;
157   }
158   CMyComPtr<IOutStreamFlush> flush;
159   _outStream.QueryInterface(IID_IOutStreamFlush, &flush);
160   if (flush)
161     return  flush->Flush();
162   return S_OK;
163 }
164
165
166 STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream)
167 {
168   _convertedPosBegin = _convertedPosEnd = _bufferPos = 0;
169   _inStream = inStream;
170   return Init();
171 }
172
173 STDMETHODIMP CFilterCoder::ReleaseInStream()
174 {
175   _inStream.Release();
176   return S_OK;
177 };
178
179 STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
180 {
181   UInt32 processedSizeTotal = 0;
182   while(size > 0)
183   {
184     if (_convertedPosBegin != _convertedPosEnd)
185     {
186       UInt32 sizeTemp = MyMin(size, _convertedPosEnd - _convertedPosBegin);
187       memmove(data, _buffer + _convertedPosBegin, sizeTemp);
188       _convertedPosBegin += sizeTemp;
189       data = (void *)((Byte *)data + sizeTemp);
190       size -= sizeTemp;
191       processedSizeTotal += sizeTemp;
192       break;
193     }
194     int i;
195     for (i = 0; _convertedPosEnd + i < _bufferPos; i++)
196       _buffer[i] = _buffer[i + _convertedPosEnd];
197     _bufferPos = i;
198     _convertedPosBegin = _convertedPosEnd = 0;
199     UInt32 processedSizeTemp;
200     UInt32 size0 = kBufferSize - _bufferPos;
201     // Optimize it:
202     RINOK(ReadStream(_inStream, _buffer + _bufferPos, size0, &processedSizeTemp));
203     _bufferPos = _bufferPos + processedSizeTemp;
204     _convertedPosEnd = Filter->Filter(_buffer, _bufferPos);
205     if (_convertedPosEnd == 0)
206     {
207       if (_bufferPos == 0)
208         break;
209       else
210       {
211         _convertedPosEnd = _bufferPos; // check it
212         continue;
213       }
214     }
215     if (_convertedPosEnd > _bufferPos)
216     {
217       for (; _bufferPos < _convertedPosEnd; _bufferPos++)
218         _buffer[_bufferPos] = 0;
219       _convertedPosEnd = Filter->Filter(_buffer, _bufferPos);
220     }
221   }
222   if (processedSize != NULL)
223     *processedSize = processedSizeTotal;
224   return S_OK;
225 }
226
227 // #endif // _ST_MODE
228
229 #ifndef _NO_CRYPTO
230 STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size)
231 {
232   return _setPassword->CryptoSetPassword(data, size);
233 }
234 #endif
235
236 #ifndef EXTRACT_ONLY
237 STDMETHODIMP CFilterCoder::SetCoderProperties(const PROPID *propIDs, 
238       const PROPVARIANT *properties, UInt32 numProperties)
239 {
240   return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties);
241 }
242
243 STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream)
244 {
245   return _writeCoderProperties->WriteCoderProperties(outStream);
246 }
247
248 /*
249 STDMETHODIMP CFilterCoder::ResetSalt()
250 {
251   return _CryptoResetSalt->ResetSalt();
252 }
253 */
254
255 STDMETHODIMP CFilterCoder::ResetInitVector()
256 {
257   return _CryptoResetInitVector->ResetInitVector();
258 }
259 #endif
260
261 STDMETHODIMP CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size)
262 {
263   return _setDecoderProperties->SetDecoderProperties2(data, size);
264 }