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 && _zstr.next_out)
180 {
181 int rc = deflate(&_zstr, Z_SYNC_FLUSH);
182 if (rc != Z_OK) throw IOException(zError(rc));
183 _pOstr->write(_buffer, DEFLATE_BUFFER_SIZE - _zstr.avail_out);
184 if (!_pOstr->good()) throw IOException(zError(rc));
185 while (_zstr.avail_out == 0)
186 {
187 _zstr.next_out = (unsigned char*) _buffer;
188 _zstr.avail_out = DEFLATE_BUFFER_SIZE;
189 rc = deflate(&_zstr, Z_SYNC_FLUSH);
190 if (rc != Z_OK) throw IOException(zError(rc));
191 _pOstr->write(_buffer, DEFLATE_BUFFER_SIZE - _zstr.avail_out);
192 if (!_pOstr->good()) throw IOException(zError(rc));
193 };
194 _zstr.next_out = (unsigned char*) _buffer;
195 _zstr.avail_out = DEFLATE_BUFFER_SIZE;
196 }
197 return 0;
198}
199
200
201int DeflatingStreamBuf::readFromDevice(char* buffer, std::streamsize length)
202{
203 if (!_pIstr) return 0;
204 if (_zstr.avail_in == 0 && !_eof)
205 {
206 int n = 0;
207 if (_pIstr->good())
208 {
209 _pIstr->read(_buffer, DEFLATE_BUFFER_SIZE);
210 n = static_cast<int>(_pIstr->gcount());
211 }
212 if (n > 0)
213 {
214 _zstr.next_in = (unsigned char*) _buffer;
215 _zstr.avail_in = n;
216 }
217 else
218 {
219 _zstr.next_in = 0;
220 _zstr.avail_in = 0;
221 _eof = true;
222 }
223 }
224 _zstr.next_out = (unsigned char*) buffer;
225 _zstr.avail_out = static_cast<unsigned>(length);
226 for (;;)
227 {
228 int rc = deflate(&_zstr, _eof ? Z_FINISH : Z_NO_FLUSH);
229 if (_eof && rc == Z_STREAM_END)
230 {
231 _pIstr = 0;
232 return static_cast<int>(length) - _zstr.avail_out;
233 }
234 if (rc != Z_OK) throw IOException(zError(rc));
235 if (_zstr.avail_out == 0)
236 {
237 return static_cast<int>(length);
238 }
239 if (_zstr.avail_in == 0)
240 {
241 int n = 0;
242 if (_pIstr->good())
243 {
244 _pIstr->read(_buffer, DEFLATE_BUFFER_SIZE);
245 n = static_cast<int>(_pIstr->gcount());
246 }
247 if (n > 0)
248 {
249 _zstr.next_in = (unsigned char*) _buffer;
250 _zstr.avail_in = n;
251 }
252 else
253 {
254 _zstr.next_in = 0;
255 _zstr.avail_in = 0;
256 _eof = true;
257 }
258 }
259 }
260}
261
262
263int DeflatingStreamBuf::writeToDevice(const char* buffer, std::streamsize length)
264{
265 if (length == 0 || !_pOstr) return 0;
266
267 _zstr.next_in = (unsigned char*) buffer;
268 _zstr.avail_in = static_cast<unsigned>(length);
269 _zstr.next_out = (unsigned char*) _buffer;
270 _zstr.avail_out = DEFLATE_BUFFER_SIZE;
271 for (;;)
272 {
273 int rc = deflate(&_zstr, Z_NO_FLUSH);
274 if (rc != Z_OK) throw IOException(zError(rc));
275 if (_zstr.avail_out == 0)
276 {
277 _pOstr->write(_buffer, DEFLATE_BUFFER_SIZE);
278 if (!_pOstr->good()) throw IOException(zError(rc));
279 _zstr.next_out = (unsigned char*) _buffer;
280 _zstr.avail_out = DEFLATE_BUFFER_SIZE;
281 }
282 if (_zstr.avail_in == 0)
283 {
284 _pOstr->write(_buffer, DEFLATE_BUFFER_SIZE - _zstr.avail_out);
285 if (!_pOstr->good()) throw IOException(zError(rc));
286 _zstr.next_out = (unsigned char*) _buffer;
287 _zstr.avail_out = DEFLATE_BUFFER_SIZE;
288 break;
289 }
290 }
291 return static_cast<int>(length);
292}
293
294
295DeflatingIOS::DeflatingIOS(std::ostream& ostr, DeflatingStreamBuf::StreamType type, int level):
296 _buf(ostr, type, level)
297{
298 poco_ios_init(&_buf);
299}
300
301
302DeflatingIOS::DeflatingIOS(std::ostream& ostr, int windowBits, int level):
303 _buf(ostr, windowBits, level)
304{
305 poco_ios_init(&_buf);
306}
307
308
309DeflatingIOS::DeflatingIOS(std::istream& istr, DeflatingStreamBuf::StreamType type, int level):
310 _buf(istr, type, level)
311{
312 poco_ios_init(&_buf);
313}
314
315
316DeflatingIOS::DeflatingIOS(std::istream& istr, int windowBits, int level):
317 _buf(istr, windowBits, level)
318{
319 poco_ios_init(&_buf);
320}
321
322
323DeflatingIOS::~DeflatingIOS()
324{
325}
326
327
328DeflatingStreamBuf* DeflatingIOS::rdbuf()
329{
330 return &_buf;
331}
332
333
334DeflatingOutputStream::DeflatingOutputStream(std::ostream& ostr, DeflatingStreamBuf::StreamType type, int level):
335 std::ostream(&_buf),
336 DeflatingIOS(ostr, type, level)
337{
338}
339
340
341DeflatingOutputStream::DeflatingOutputStream(std::ostream& ostr, int windowBits, int level):
342 std::ostream(&_buf),
343 DeflatingIOS(ostr, windowBits, level)
344{
345}
346
347
348DeflatingOutputStream::~DeflatingOutputStream()
349{
350}
351
352
353int DeflatingOutputStream::close()
354{
355 return _buf.close();
356}
357
358
359int DeflatingOutputStream::sync()
360{
361 return _buf.pubsync();
362}
363
364
365DeflatingInputStream::DeflatingInputStream(std::istream& istr, DeflatingStreamBuf::StreamType type, int level):
366 std::istream(&_buf),
367 DeflatingIOS(istr, type, level)
368{
369}
370
371
372DeflatingInputStream::DeflatingInputStream(std::istream& istr, int windowBits, int level):
373 std::istream(&_buf),
374 DeflatingIOS(istr, windowBits, level)
375{
376}
377
378
379DeflatingInputStream::~DeflatingInputStream()
380{
381}
382
383
384} // namespace Poco
385