~ubuntu-branches/ubuntu/gutsy/poco/gutsy

« back to all changes in this revision

Viewing changes to Foundation/src/InflatingStream.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Krzysztof Burghardt
  • Date: 2007-04-27 18:33:48 UTC
  • Revision ID: james.westby@ubuntu.com-20070427183348-xgnpct0qd6a2ip34
Tags: upstream-1.2.9
ImportĀ upstreamĀ versionĀ 1.2.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// InflatingStream.cpp
 
3
//
 
4
// $Id: //poco/1.2/Foundation/src/InflatingStream.cpp#1 $
 
5
//
 
6
// Library: Foundation
 
7
// Package: Streams
 
8
// Module:  ZLibStream
 
9
//
 
10
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
 
11
// and Contributors.
 
12
//
 
13
// Permission is hereby granted, free of charge, to any person or organization
 
14
// obtaining a copy of the software and accompanying documentation covered by
 
15
// this license (the "Software") to use, reproduce, display, distribute,
 
16
// execute, and transmit the Software, and to prepare derivative works of the
 
17
// Software, and to permit third-parties to whom the Software is furnished to
 
18
// do so, all subject to the following:
 
19
// 
 
20
// The copyright notices in the Software and this entire statement, including
 
21
// the above license grant, this restriction and the following disclaimer,
 
22
// must be included in all copies of the Software, in whole or in part, and
 
23
// all derivative works of the Software, unless such copies or derivative
 
24
// works are solely in the form of machine-executable object code generated by
 
25
// a source language processor.
 
26
// 
 
27
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
28
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
29
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
 
30
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
 
31
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 
32
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 
33
// DEALINGS IN THE SOFTWARE.
 
34
//
 
35
 
 
36
 
 
37
#include "Poco/InflatingStream.h"
 
38
#include "Poco/Exception.h"
 
39
 
 
40
 
 
41
namespace Poco {
 
42
 
 
43
 
 
44
InflatingStreamBuf::InflatingStreamBuf(std::istream& istr, StreamType type): 
 
45
        BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::in),
 
46
        _pIstr(&istr),
 
47
        _pOstr(0),
 
48
        _eof(false)
 
49
{
 
50
        _zstr.zalloc    = Z_NULL;
 
51
        _zstr.zfree     = Z_NULL;
 
52
        _zstr.opaque    = Z_NULL;
 
53
        _zstr.next_in   = 0;
 
54
        _zstr.avail_in  = 0;
 
55
        _zstr.next_out  = 0;
 
56
        _zstr.avail_out = 0;
 
57
 
 
58
        int rc = inflateInit2(&_zstr, 15 + (type == STREAM_GZIP ? 16 : 0));
 
59
        if (rc != Z_OK) throw IOException(zError(rc)); 
 
60
 
 
61
        _buffer = new char[INFLATE_BUFFER_SIZE];
 
62
}
 
63
 
 
64
 
 
65
InflatingStreamBuf::InflatingStreamBuf(std::ostream& ostr, StreamType type): 
 
66
        BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::out),
 
67
        _pIstr(0),
 
68
        _pOstr(&ostr),
 
69
        _eof(false)
 
70
{
 
71
        _zstr.zalloc    = Z_NULL;
 
72
        _zstr.zfree     = Z_NULL;
 
73
        _zstr.opaque    = Z_NULL;
 
74
        _zstr.next_in   = 0;
 
75
        _zstr.avail_in  = 0;
 
76
        _zstr.next_out  = 0;
 
77
        _zstr.avail_out = 0;
 
78
 
 
79
        int rc = inflateInit2(&_zstr, 15 + (type == STREAM_GZIP ? 16 : 0));
 
80
        if (rc != Z_OK) throw IOException(zError(rc));
 
81
 
 
82
        _buffer = new char[INFLATE_BUFFER_SIZE];
 
83
}
 
84
 
 
85
 
 
86
InflatingStreamBuf::~InflatingStreamBuf()
 
87
{
 
88
        try
 
89
        {
 
90
                close();
 
91
        }
 
92
        catch (...)
 
93
        {
 
94
        }
 
95
        delete [] _buffer;
 
96
}
 
97
 
 
98
 
 
99
int InflatingStreamBuf::close()
 
100
{
 
101
        sync();
 
102
        if (_pIstr || _pOstr)
 
103
        {
 
104
                int rc = inflateEnd(&_zstr);
 
105
                if (rc != Z_OK) throw IOException(zError(rc));
 
106
                _pIstr = 0;
 
107
                _pOstr = 0;
 
108
        }
 
109
        return 0;
 
110
}
 
111
 
 
112
 
 
113
int InflatingStreamBuf::readFromDevice(char* buffer, std::streamsize length)
 
114
{
 
115
        if (_eof || !_pIstr) return 0;
 
116
 
 
117
        if (_zstr.avail_in == 0)
 
118
        {
 
119
                int n = 0;
 
120
                if (_pIstr->good())
 
121
                {
 
122
                        _pIstr->read(_buffer, INFLATE_BUFFER_SIZE);
 
123
                        n = _pIstr->gcount();
 
124
                }
 
125
                if (n == 0) return 0;
 
126
                _zstr.next_in   = (unsigned char*) _buffer;
 
127
                _zstr.avail_in  = n;
 
128
        }
 
129
        _zstr.next_out  = (unsigned char*) buffer;
 
130
        _zstr.avail_out = length;
 
131
        for (;;)
 
132
        {
 
133
                int rc = inflate(&_zstr, Z_NO_FLUSH);
 
134
                if (rc == Z_STREAM_END)
 
135
                {
 
136
                        _eof = true;
 
137
                        return length - _zstr.avail_out;
 
138
                }
 
139
                if (rc != Z_OK) throw IOException(zError(rc));
 
140
                if (_zstr.avail_out == 0)
 
141
                        return length;
 
142
                if (_zstr.avail_in == 0)
 
143
                {
 
144
                        int n = 0;
 
145
                        if (_pIstr->good())
 
146
                        {
 
147
                                _pIstr->read(_buffer, INFLATE_BUFFER_SIZE);
 
148
                                n = _pIstr->gcount();
 
149
                        }
 
150
                        if (n > 0)
 
151
                        {
 
152
                                _zstr.next_in  = (unsigned char*) _buffer;
 
153
                                _zstr.avail_in = n;
 
154
                        }
 
155
                }
 
156
        }
 
157
}
 
158
 
 
159
 
 
160
int InflatingStreamBuf::writeToDevice(const char* buffer, std::streamsize length)
 
161
{
 
162
        if (length == 0 || !_pOstr) return 0;
 
163
        
 
164
        _zstr.next_in   = (unsigned char*) buffer;
 
165
        _zstr.avail_in  = length;
 
166
        _zstr.next_out  = (unsigned char*) _buffer;
 
167
        _zstr.avail_out = INFLATE_BUFFER_SIZE;
 
168
        for (;;)
 
169
        {
 
170
                int rc = inflate(&_zstr, Z_NO_FLUSH);
 
171
                if (rc == Z_STREAM_END)
 
172
                {
 
173
                        _pOstr->write(_buffer, INFLATE_BUFFER_SIZE - _zstr.avail_out);
 
174
                        if (!_pOstr->good()) throw IOException(zError(rc));
 
175
                        break;
 
176
                }
 
177
                if (rc != Z_OK) throw IOException(zError(rc)); 
 
178
                if (_zstr.avail_out == 0)
 
179
                {
 
180
                        _pOstr->write(_buffer, INFLATE_BUFFER_SIZE);
 
181
                        if (!_pOstr->good()) throw IOException(zError(rc));
 
182
                        _zstr.next_out  = (unsigned char*) _buffer;
 
183
                        _zstr.avail_out = INFLATE_BUFFER_SIZE;
 
184
                }
 
185
                if (_zstr.avail_in == 0)
 
186
                {
 
187
                        _pOstr->write(_buffer, INFLATE_BUFFER_SIZE - _zstr.avail_out);
 
188
                        if (!_pOstr->good()) throw IOException(zError(rc)); 
 
189
                        _zstr.next_out  = (unsigned char*) _buffer;
 
190
                        _zstr.avail_out = INFLATE_BUFFER_SIZE;
 
191
                        break;
 
192
                }
 
193
        }
 
194
        return length;
 
195
}
 
196
 
 
197
 
 
198
InflatingIOS::InflatingIOS(std::ostream& ostr, InflatingStreamBuf::StreamType type):
 
199
        _buf(ostr, type)
 
200
{
 
201
        poco_ios_init(&_buf);
 
202
}
 
203
 
 
204
 
 
205
InflatingIOS::InflatingIOS(std::istream& istr, InflatingStreamBuf::StreamType type):
 
206
        _buf(istr, type)
 
207
{
 
208
        poco_ios_init(&_buf);
 
209
}
 
210
 
 
211
 
 
212
InflatingIOS::~InflatingIOS()
 
213
{
 
214
}
 
215
 
 
216
 
 
217
InflatingStreamBuf* InflatingIOS::rdbuf()
 
218
{
 
219
        return &_buf;
 
220
}
 
221
 
 
222
 
 
223
InflatingOutputStream::InflatingOutputStream(std::ostream& ostr, InflatingStreamBuf::StreamType type):
 
224
        InflatingIOS(ostr, type),
 
225
        std::ostream(&_buf)
 
226
{
 
227
}
 
228
 
 
229
 
 
230
InflatingOutputStream::~InflatingOutputStream()
 
231
{
 
232
}
 
233
 
 
234
 
 
235
int InflatingOutputStream::close()
 
236
{
 
237
        return _buf.close();
 
238
}
 
239
 
 
240
 
 
241
InflatingInputStream::InflatingInputStream(std::istream& istr, InflatingStreamBuf::StreamType type):
 
242
        InflatingIOS(istr, type),
 
243
        std::istream(&_buf)
 
244
{
 
245
}
 
246
 
 
247
 
 
248
InflatingInputStream::~InflatingInputStream()
 
249
{
 
250
}
 
251
 
 
252
 
 
253
} // namespace Poco