1//
2// DeflatingStream.cpp
3//
4// Library: Foundation
5// Package: Streams
6// Module: ZLibStream
7//
8// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
9// and Contributors.
10//
11// SPDX-License-Identifier: BSL-1.0
12//
13
14
15#include "Poco/DeflatingStream.h"
16#include "Poco/Exception.h"
17
18
19namespace Poco {
20
21
22DeflatingStreamBuf::DeflatingStreamBuf(std::istream& istr, StreamType type, int level):
23 BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::in),
24 _pIstr(&istr),
25 _pOstr(0),
26 _eof(false)
27{
28 _zstr.next_in = 0;
29 _zstr.avail_in = 0;
30 _zstr.total_in = 0;
31 _zstr.next_out = 0;
32 _zstr.avail_out = 0;
33 _zstr.total_out = 0;
34 _zstr.msg = 0;
35 _zstr.state = 0;
36 _zstr.zalloc = Z_NULL;
37 _zstr.zfree = Z_NULL;
38 _zstr.opaque = Z_NULL;
39 _zstr.data_type = 0;
40 _zstr.adler = 0;
41 _zstr.reserved = 0;
42
43 _buffer = new char[DEFLATE_BUFFER_SIZE];
44
45 int rc = deflateInit2(&_zstr, level, Z_DEFLATED, 15 + (type == STREAM_GZIP ? 16 : 0), 8, Z_DEFAULT_STRATEGY);
46 if (rc != Z_OK)
47 {
48 delete [] _buffer;
49 throw IOException(zError(rc));
50 }
51}
52
53
54DeflatingStreamBuf::DeflatingStreamBuf(std::istream& istr, int windowBits, int level):
55 BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::in),
56 _pIstr(&istr),
57 _pOstr(0),
58 _eof(false)
59{
60 _zstr.zalloc = Z_NULL;
61 _zstr.zfree = Z_NULL;
62 _zstr.opaque = Z_NULL;
63 _zstr.next_in = 0;
64 _zstr.avail_in = 0;
65 _zstr.next_out = 0;
66 _zstr.avail_out = 0;
67
68 _buffer = new char[DEFLATE_BUFFER_SIZE];
69
70 int rc = deflateInit2(&_zstr, level, Z_DEFLATED, windowBits, 8, Z_DEFAULT_STRATEGY);
71 if (rc != Z_OK)
72 {
73 delete [] _buffer;
74 throw IOException(zError(rc));
75 }
76}
77
78
79DeflatingStreamBuf::DeflatingStreamBuf(std::ostream& ostr, StreamType type, int level):
80 BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::out),
81 _pIstr(0),
82 _pOstr(&ostr),
83 _eof(false)
84{
85 _zstr.zalloc = Z_NULL;
86 _zstr.zfree = Z_NULL;
87 _zstr.opaque = Z_NULL;
88 _zstr.next_in = 0;
89 _zstr.avail_in = 0;
90 _zstr.next_out = 0;
91 _zstr.avail_out = 0;
92
93 _buffer = new char[DEFLATE_BUFFER_SIZE];
94
95 int rc = deflateInit2(&_zstr, level, Z_DEFLATED, 15 + (type == STREAM_GZIP ? 16 : 0), 8, Z_DEFAULT_STRATEGY);
96 if (rc != Z_OK)
97 {
98 delete [] _buffer;
99 throw IOException(zError(rc));
100 }
101}
102
103
104DeflatingStreamBuf::DeflatingStreamBuf(std::ostream& ostr, int windowBits, int level):
105 BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::out),
106 _pIstr(0),
107 _pOstr(&ostr),
108 _eof(false)
109{
110 _zstr.zalloc = Z_NULL;
111 _zstr.zfree = Z_NULL;
112 _zstr.opaque = Z_NULL;
113 _zstr.next_in = 0;
114 _zstr.avail_in = 0;
115 _zstr.next_out = 0;
116 _zstr.avail_out = 0;
117
118 _buffer = new char[DEFLATE_BUFFER_SIZE];
119
120 int rc = deflateInit2(&_zstr, level, Z_DEFLATED, windowBits, 8, Z_DEFAULT_STRATEGY);
121 if (rc != Z_OK)
122 {
123 delete [] _buffer;
124 throw IOException(zError(rc));
125 }
126}
127
128
129DeflatingStreamBuf::~DeflatingStreamBuf()
130{
131 try
132 {
133 close();
134 }
135 catch (...)
136 {
137 }
138 delete [] _buffer;
139 deflateEnd(&_zstr);
140}
141
142
143int DeflatingStreamBuf::close()
144{
145 BufferedStreamBuf::sync();
146 _pIstr = 0;
147 if (_pOstr)
148 {
149 if (_zstr.next_out)
150 {
151 int rc = deflate(&_zstr, Z_FINISH);
152 if (rc != Z_OK && rc != Z_STREAM_END) throw IOException(zError(rc));
153 _pOstr->write(_buffer, DEFLATE_BUFFER_SIZE - _zstr.avail_out);
154 if (!_pOstr->good()) throw IOException(zError(rc));
155 _zstr.next_out = (unsigned char*) _buffer;
156 _zstr.avail_out = DEFLATE_BUFFER_SIZE;
157 while (rc != Z_STREAM_END)
158 {
159 rc = deflate(&_zstr, Z_FINISH);
160 if (rc != Z_OK && rc != Z_STREAM_END) throw IOException(zError(rc));
161 _pOstr->write(_buffer, DEFLATE_BUFFER_SIZE - _zstr.avail_out);
162 if (!_pOstr->good()) throw IOException(zError(rc));
163 _zstr.next_out = (unsigned char*) _buffer;
164 _zstr.avail_out = DEFLATE_BUFFER_SIZE;
165 }
166 }
167 _pOstr->flush();
168 _pOstr = 0;
169 }
170 return 0;
171}
172
173
174int DeflatingStreamBuf::sync()
175{
176 if (BufferedStreamBuf::sync())
177 return -1;
178
179 if (_pOstr)
180 {
181 if (_zstr.next_out)
182 {
183 int rc = deflate(&_zstr, Z_SYNC_FLUSH);
184 if (rc != Z_OK) throw IOException(zError(rc));
185 _pOstr->write(_buffer, DEFLATE_BUFFER_SIZE - _zstr.avail_out);
186 if (!_pOstr->good()) throw IOException(zError(rc));
187 while (_zstr.avail_out == 0)
188 {
189 _zstr.next_out = (unsigned char*) _buffer;
190 _zstr.avail_out = DEFLATE_BUFFER_SIZE;
191 rc = deflate(&_zstr, Z_SYNC_FLUSH);
192 if (rc != Z_OK) throw IOException(zError(rc));
193 _pOstr->write(_buffer, DEFLATE_BUFFER_SIZE - _zstr.avail_out);
194 if (!_pOstr->good()) throw IOException(zError(rc));
195 };
196 _zstr.next_out = (unsigned char*) _buffer;
197 _zstr.avail_out = DEFLATE_BUFFER_SIZE;
198 }
199 // NOTE: This breaks the Zip library and causes corruption in some files.
200 // See GH #1828
201 // _pOstr->flush();
202 }
203 return 0;
204}
205
206
207int DeflatingStreamBuf::readFromDevice(char* buffer, std::streamsize length)
208{
209 if (!_pIstr) return 0;
210 if (_zstr.avail_in == 0 && !_eof)
211 {
212 int n = 0;
213 if (_pIstr->good())
214 {
215 _pIstr->read(_buffer, DEFLATE_BUFFER_SIZE);
216 n = static_cast<int>(_pIstr->gcount());
217 }
218 if (n > 0)
219 {
220 _zstr.next_in = (unsigned char*) _buffer;
221 _zstr.avail_in = n;
222 }
223 else
224 {
225 _zstr.next_in = 0;
226 _zstr.avail_in = 0;
227 _eof = true;
228 }
229 }
230 _zstr.next_out = (unsigned char*) buffer;
231 _zstr.avail_out = static_cast<unsigned>(length);
232 for (;;)
233 {
234 int rc = deflate(&_zstr, _eof ? Z_FINISH : Z_NO_FLUSH);
235 if (_eof && rc == Z_STREAM_END)
236 {
237 _pIstr = 0;
238 return static_cast<int>(length) - _zstr.avail_out;
239 }
240 if (rc != Z_OK) throw IOException(zError(rc));
241 if (_zstr.avail_out == 0)
242 {
243 return static_cast<int>(length);
244 }
245 if (_zstr.avail_in == 0)
246 {
247 int n = 0;
248 if (_pIstr->good())
249 {
250 _pIstr->read(_buffer, DEFLATE_BUFFER_SIZE);
251 n = static_cast<int>(_pIstr->gcount());
252 }
253 if (n > 0)
254 {
255 _zstr.next_in = (unsigned char*) _buffer;
256 _zstr.avail_in = n;
257 }
258 else
259 {
260 _zstr.next_in = 0;
261 _zstr.avail_in = 0;
262 _eof = true;
263 }
264 }
265 }
266}
267
268
269int DeflatingStreamBuf::writeToDevice(const char* buffer, std::streamsize length)
270{
271 if (length == 0 || !_pOstr) return 0;
272
273 _zstr.next_in = (unsigned char*) buffer;
274 _zstr.avail_in = static_cast<unsigned>(length);
275 _zstr.next_out = (unsigned char*) _buffer;
276 _zstr.avail_out = DEFLATE_BUFFER_SIZE;
277 for (;;)
278 {
279 int rc = deflate(&_zstr, Z_NO_FLUSH);
280 if (rc != Z_OK) throw IOException(zError(rc));
281 if (_zstr.avail_out == 0)
282 {
283 _pOstr->write(_buffer, DEFLATE_BUFFER_SIZE);
284 if (!_pOstr->good()) throw IOException(zError(rc));
285 _zstr.next_out = (unsigned char*) _buffer;
286 _zstr.avail_out = DEFLATE_BUFFER_SIZE;
287 }
288 if (_zstr.avail_in == 0)
289 {
290 _pOstr->write(_buffer, DEFLATE_BUFFER_SIZE - _zstr.avail_out);
291 if (!_pOstr->good()) throw IOException(zError(rc));
292 _zstr.next_out = (unsigned char*) _buffer;
293 _zstr.avail_out = DEFLATE_BUFFER_SIZE;
294 break;
295 }
296 }
297 return static_cast<int>(length);
298}
299
300
301DeflatingIOS::DeflatingIOS(std::ostream& ostr, DeflatingStreamBuf::StreamType type, int level):
302 _buf(ostr, type, level)
303{
304 poco_ios_init(&_buf);
305}
306
307
308DeflatingIOS::DeflatingIOS(std::ostream& ostr, int windowBits, int level):
309 _buf(ostr, windowBits, level)
310{
311 poco_ios_init(&_buf);
312}
313
314
315DeflatingIOS::DeflatingIOS(std::istream& istr, DeflatingStreamBuf::StreamType type, int level):
316 _buf(istr, type, level)
317{
318 poco_ios_init(&_buf);
319}
320
321
322DeflatingIOS::DeflatingIOS(std::istream& istr, int windowBits, int level):
323 _buf(istr, windowBits, level)
324{
325 poco_ios_init(&_buf);
326}
327
328
329DeflatingIOS::~DeflatingIOS()
330{
331}
332
333
334DeflatingStreamBuf* DeflatingIOS::rdbuf()
335{
336 return &_buf;
337}
338
339
340DeflatingOutputStream::DeflatingOutputStream(std::ostream& ostr, DeflatingStreamBuf::StreamType type, int level):
341 std::ostream(&_buf),
342 DeflatingIOS(ostr, type, level)
343{
344}
345
346
347DeflatingOutputStream::DeflatingOutputStream(std::ostream& ostr, int windowBits, int level):
348 std::ostream(&_buf),
349 DeflatingIOS(ostr, windowBits, level)
350{
351}
352
353
354DeflatingOutputStream::~DeflatingOutputStream()
355{
356}
357
358
359int DeflatingOutputStream::close()
360{
361 return _buf.close();
362}
363
364
365int DeflatingOutputStream::sync()
366{
367 return _buf.pubsync();
368}
369
370
371DeflatingInputStream::DeflatingInputStream(std::istream& istr, DeflatingStreamBuf::StreamType type, int level):
372 std::istream(&_buf),
373 DeflatingIOS(istr, type, level)
374{
375}
376
377
378DeflatingInputStream::DeflatingInputStream(std::istream& istr, int windowBits, int level):
379 std::istream(&_buf),
380 DeflatingIOS(istr, windowBits, level)
381{
382}
383
384
385DeflatingInputStream::~DeflatingInputStream()
386{
387}
388
389
390} // namespace Poco
391