blob: a2c31d2c48fdd85fa5994b9435a5ea2c93668a61 [file] [log] [blame]
Emeric Vigier2f625822012-08-06 11:09:52 -04001// Copyright (C) 1999-2005 Open Source Telecom Corporation.
2// Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
3//
4// This program is free software; you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation; either version 2 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program; if not, write to the Free Software
16// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17//
18// As a special exception, you may use this file as part of a free software
19// library without restriction. Specifically, if other files instantiate
20// templates or use macros or inline functions from this file, or you compile
21// this file and link it with other files to produce an executable, this
22// file does not by itself cause the resulting executable to be covered by
23// the GNU General Public License. This exception does not however
24// invalidate any other reasons why the executable file might be covered by
25// the GNU General Public License.
26//
27// This exception applies only to the code released under the name GNU
28// Common C++. If you copy code from other releases into a copy of GNU
29// Common C++, as the General Public License permits, the exception does
30// not apply to the code that you add in this way. To avoid misleading
31// anyone as to the status of such modified files, you must delete
32// this exception notice from them.
33//
34// If you write modifications of your own for GNU Common C++, it is your choice
35// whether to permit this exception to apply to your modifications.
36// If you do not wish that, delete this exception notice.
37//
38
39#ifdef HAVE_ZLIB_H
40
41#include <cc++/config.h>
42#ifdef CCXX_WITHOUT_EXTRAS
43#include <cc++/export.h>
44#endif
45#include <cc++/thread.h>
46#include <cc++/exception.h>
47#ifndef CCXX_WITHOUT_EXTRAS
48#include <cc++/export.h>
49#endif
50#include <cc++/zstream.h>
51#include <cerrno>
52#include <cstdlib>
53#include <cstdarg>
54#include <cstdio>
55
56#ifdef WIN32
57#include <io.h>
58#endif
59
60#ifdef CCXX_NAMESPACES
61namespace ost {
62using namespace std;
63#endif
64
65IZStream::IZStream(const char *name, size_t size, bool tf) :
66streambuf(),
67#ifdef HAVE_OLD_IOSTREAM
68istream(),
69#else
70istream((streambuf *)this),
71#endif
72bufsize(0), gbuf(NULL), fp(0)
73{
74#ifdef HAVE_OLD_IOSTREAM
75 init((streambuf *)this);
76#endif
77
78 throwflag = tf;
79 fp = ::gzopen(name, "rb");
80 if(!fp) {
81#ifdef COMMON_STD_EXCEPTION
82 if(Thread::getException() == Thread::throwException && throwflag)
83 throw IOZException(String(::gzerror(fp, NULL)));
84#endif
85 clear(ios::failbit | rdstate());
86 return;
87 }
88
89 allocate(size);
90}
91
92IZStream::IZStream(bool tf) :
93streambuf(),
94#ifdef HAVE_OLD_IOSTREAM
95istream(),
96#else
97istream((streambuf *)this),
98#endif
99bufsize(0), gbuf(NULL), fp(0)
100{
101#ifdef HAVE_OLD_IOSTREAM
102 init((streambuf *)this);
103#endif
104 throwflag = tf;
105}
106
107IZStream::~IZStream()
108{
109 close();
110}
111
112void IZStream::open(const char *name, size_t size)
113{
114 if(fp)
115 close();
116
117 fp = ::gzopen(name, "rb");
118 if(!fp) {
119#ifdef COMMON_STD_EXCEPTION
120 if(Thread::getException() == Thread::throwException && throwflag)
121 throw IOZException(String(::gzerror(fp, NULL)));
122#endif
123 clear(ios::failbit | rdstate());
124 return;
125 }
126 allocate(size);
127}
128
129void IZStream::close(void)
130{
131 if(gbuf)
132 delete[] gbuf;
133
134 ::gzclose(fp);
135 fp = 0;
136
137 gbuf = NULL;
138 bufsize = 0;
139 clear();
140}
141
142void IZStream::allocate(size_t size)
143{
144 if(size < 2) {
145 bufsize = 1;
146 gbuf = 0;
147 return;
148 }
149
150 gbuf = new char[size];
151 if(!gbuf)
152 return;
153 bufsize = size;
154 clear();
155
156#if (defined(__GNUC__) && (__GNUC__ < 3)) && !defined(WIN32) && !defined(STLPORT)
157 setb(gbuf, gbuf + size, 0);
158#endif
159 setg(gbuf, gbuf + size, gbuf + size);
160}
161
162int IZStream::doallocate()
163{
164 if(bufsize)
165 return 0;
166
167 allocate(1);
168 return 1;
169}
170
171bool IZStream::isOpen(void)
172{
173 if(fp)
174 return true;
175
176 return false;
177}
178
179int IZStream::uflow()
180{
181 int ret = underflow();
182
183 if (ret == EOF)
184 return EOF;
185
186 if (bufsize != 1)
187 gbump(1);
188
189 return ret;
190}
191
192int IZStream::underflow()
193{
194 ssize_t rlen = 1;
195 unsigned char ch;
196
197 if(bufsize == 1) {
198 rlen = ::gzread(fp, &ch, 1);
199 if(rlen < 1) {
200 if(rlen < 0)
201 clear(ios::failbit | rdstate());
202 return EOF;
203 }
204 return ch;
205 }
206
207 if(!gptr())
208 return EOF;
209
210 if(gptr() < egptr())
211 return (unsigned char)*gptr();
212
213 rlen = (ssize_t)((gbuf + bufsize) - eback());
214 rlen = ::gzread(fp, eback(), rlen);
215 if(rlen < 1) {
216 clear(ios::failbit | rdstate());
217 return EOF;
218 }
219
220 setg(eback(), eback(), eback() + rlen);
221 return (unsigned char) *gptr();
222}
223
224
225
226OZStream::OZStream(const char *name, int level, size_t size, bool tf) :
227streambuf(),
228#ifdef HAVE_OLD_IOSTREAM
229 ostream(),
230#else
231 ostream((streambuf *)this),
232#endif
233 bufsize(0),pbuf(NULL),fp(0) {
234 char mode[4];
235
236#ifdef HAVE_OLD_IOSTREAM
237 init((streambuf *)this);
238#endif
239
240 strcpy(mode, "wb\0");
241 if(level != Z_DEFAULT_COMPRESSION)
242 mode[2] = '0' + level;
243
244 throwflag = tf;
245 fp = ::gzopen(name, mode);
246 if(!fp) {
247#ifdef COMMON_STD_EXCEPTION
248 if(Thread::getException() == Thread::throwException && throwflag)
249 throw IOZException(String(::gzerror(fp, NULL)));
250#endif
251 clear(ios::failbit | rdstate());
252 return;
253 }
254
255 allocate(size);
256}
257
258OZStream::OZStream(bool tf) :
259streambuf(),
260#ifdef HAVE_OLD_IOSTREAM
261ostream(),
262#else
263ostream((streambuf *)this),
264#endif
265bufsize(0), pbuf(NULL), fp(0)
266{
267#ifdef HAVE_OLD_IOSTREAM
268 init((streambuf *)this);
269#endif
270 throwflag = tf;
271}
272
273OZStream::~OZStream()
274{
275 close();
276}
277
278void OZStream::open(const char *name, int level, size_t size)
279{
280 char mode[4];
281
282 if(fp)
283 close();
284
285 strcpy(mode, "wb\0");
286 if(level != Z_DEFAULT_COMPRESSION)
287 mode[2] = '0' + level;
288
289 fp = ::gzopen(name, mode);
290 if(!fp) {
291#ifdef COMMON_STD_EXCEPTION
292 if(Thread::getException() == Thread::throwException && throwflag)
293 throw IOZException(String(::gzerror(fp, NULL)));
294#endif
295 clear(ios::failbit | rdstate());
296 return;
297 }
298 allocate(size);
299}
300
301void OZStream::close(void)
302{
303 if(pbuf)
304 delete[] pbuf;
305
306 ::gzclose(fp);
307 fp = 0;
308
309 pbuf = NULL;
310 bufsize = 0;
311 clear();
312}
313
314void OZStream::allocate(size_t size)
315{
316 if(size < 2) {
317 bufsize = 1;
318 pbuf = 0;
319 return;
320 }
321
322 pbuf = new char[size];
323 if(!pbuf)
324 return;
325 bufsize = size;
326 clear();
327
328 setp(pbuf, pbuf + size);
329}
330
331int OZStream::doallocate()
332{
333 if(bufsize)
334 return 0;
335
336 allocate(1);
337 return 1;
338}
339
340bool OZStream::isOpen(void)
341{
342 if(fp)
343 return true;
344
345 return false;
346}
347
348int OZStream::overflow(int c)
349{
350 unsigned char ch;
351 ssize_t rlen, req;
352
353 if(bufsize == 1) {
354 if(c == EOF)
355 return 0;
356
357 ch = (unsigned char)(c);
358 rlen = ::gzwrite(fp, &ch, 1);
359 if(rlen < 1) {
360 if(rlen < 0)
361 clear(ios::failbit | rdstate());
362 return EOF;
363 }
364 else
365 return c;
366 }
367
368 if(!pbase())
369 return EOF;
370
371 req = (ssize_t)(pptr() - pbase());
372 if(req) {
373 rlen = ::gzwrite(fp, pbase(), req);
374 if(rlen < 1) {
375 if(rlen < 0)
376 clear(ios::failbit | rdstate());
377 return EOF;
378 }
379 req -= rlen;
380 }
381
382 // if write "partial", rebuffer remainder
383
384 if(req)
385 memmove(pbuf, pbuf + rlen, req);
386 setp(pbuf, pbuf + bufsize);
387 pbump(req);
388
389 if(c != EOF) {
390 *pptr() = (unsigned char)c;
391 pbump(1);
392 }
393 return c;
394}
395
396
397#ifdef CCXX_NAMESPACES
398}
399#endif
400
401#endif