xref: /minix3/common/dist/zlib/contrib/iostream2/zstream.h (revision 44bedb31d842b4b0444105519bcf929a69fe2dc1)
1*44bedb31SLionel Sambuc /*	$NetBSD: zstream.h,v 1.1.1.1 2006/01/14 20:10:54 christos Exp $	*/
2*44bedb31SLionel Sambuc 
3*44bedb31SLionel Sambuc /*
4*44bedb31SLionel Sambuc  *
5*44bedb31SLionel Sambuc  * Copyright (c) 1997
6*44bedb31SLionel Sambuc  * Christian Michelsen Research AS
7*44bedb31SLionel Sambuc  * Advanced Computing
8*44bedb31SLionel Sambuc  * Fantoftvegen 38, 5036 BERGEN, Norway
9*44bedb31SLionel Sambuc  * http://www.cmr.no
10*44bedb31SLionel Sambuc  *
11*44bedb31SLionel Sambuc  * Permission to use, copy, modify, distribute and sell this software
12*44bedb31SLionel Sambuc  * and its documentation for any purpose is hereby granted without fee,
13*44bedb31SLionel Sambuc  * provided that the above copyright notice appear in all copies and
14*44bedb31SLionel Sambuc  * that both that copyright notice and this permission notice appear
15*44bedb31SLionel Sambuc  * in supporting documentation.  Christian Michelsen Research AS makes no
16*44bedb31SLionel Sambuc  * representations about the suitability of this software for any
17*44bedb31SLionel Sambuc  * purpose.  It is provided "as is" without express or implied warranty.
18*44bedb31SLionel Sambuc  *
19*44bedb31SLionel Sambuc  */
20*44bedb31SLionel Sambuc 
21*44bedb31SLionel Sambuc #ifndef ZSTREAM__H
22*44bedb31SLionel Sambuc #define ZSTREAM__H
23*44bedb31SLionel Sambuc 
24*44bedb31SLionel Sambuc /*
25*44bedb31SLionel Sambuc  * zstream.h - C++ interface to the 'zlib' general purpose compression library
26*44bedb31SLionel Sambuc  * Id: zstream.h 1.1 1997-06-25 12:00:56+02 tyge Exp tyge
27*44bedb31SLionel Sambuc  */
28*44bedb31SLionel Sambuc 
29*44bedb31SLionel Sambuc #include <strstream.h>
30*44bedb31SLionel Sambuc #include <string.h>
31*44bedb31SLionel Sambuc #include <stdio.h>
32*44bedb31SLionel Sambuc #include "zlib.h"
33*44bedb31SLionel Sambuc 
34*44bedb31SLionel Sambuc #if defined(_WIN32)
35*44bedb31SLionel Sambuc #   include <fcntl.h>
36*44bedb31SLionel Sambuc #   include <io.h>
37*44bedb31SLionel Sambuc #   define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
38*44bedb31SLionel Sambuc #else
39*44bedb31SLionel Sambuc #   define SET_BINARY_MODE(file)
40*44bedb31SLionel Sambuc #endif
41*44bedb31SLionel Sambuc 
42*44bedb31SLionel Sambuc class zstringlen {
43*44bedb31SLionel Sambuc public:
44*44bedb31SLionel Sambuc     zstringlen(class izstream&);
45*44bedb31SLionel Sambuc     zstringlen(class ozstream&, const char*);
value()46*44bedb31SLionel Sambuc     size_t value() const { return val.word; }
47*44bedb31SLionel Sambuc private:
48*44bedb31SLionel Sambuc     struct Val { unsigned char byte; size_t word; } val;
49*44bedb31SLionel Sambuc };
50*44bedb31SLionel Sambuc 
51*44bedb31SLionel Sambuc //  ----------------------------- izstream -----------------------------
52*44bedb31SLionel Sambuc 
53*44bedb31SLionel Sambuc class izstream
54*44bedb31SLionel Sambuc {
55*44bedb31SLionel Sambuc     public:
izstream()56*44bedb31SLionel Sambuc         izstream() : m_fp(0) {}
izstream(FILE * fp)57*44bedb31SLionel Sambuc         izstream(FILE* fp) : m_fp(0) { open(fp); }
izstream(const char * name)58*44bedb31SLionel Sambuc         izstream(const char* name) : m_fp(0) { open(name); }
~izstream()59*44bedb31SLionel Sambuc         ~izstream() { close(); }
60*44bedb31SLionel Sambuc 
61*44bedb31SLionel Sambuc         /* Opens a gzip (.gz) file for reading.
62*44bedb31SLionel Sambuc          * open() can be used to read a file which is not in gzip format;
63*44bedb31SLionel Sambuc          * in this case read() will directly read from the file without
64*44bedb31SLionel Sambuc          * decompression. errno can be checked to distinguish two error
65*44bedb31SLionel Sambuc          * cases (if errno is zero, the zlib error is Z_MEM_ERROR).
66*44bedb31SLionel Sambuc          */
open(const char * name)67*44bedb31SLionel Sambuc         void open(const char* name) {
68*44bedb31SLionel Sambuc             if (m_fp) close();
69*44bedb31SLionel Sambuc             m_fp = ::gzopen(name, "rb");
70*44bedb31SLionel Sambuc         }
71*44bedb31SLionel Sambuc 
open(FILE * fp)72*44bedb31SLionel Sambuc         void open(FILE* fp) {
73*44bedb31SLionel Sambuc             SET_BINARY_MODE(fp);
74*44bedb31SLionel Sambuc             if (m_fp) close();
75*44bedb31SLionel Sambuc             m_fp = ::gzdopen(fileno(fp), "rb");
76*44bedb31SLionel Sambuc         }
77*44bedb31SLionel Sambuc 
78*44bedb31SLionel Sambuc         /* Flushes all pending input if necessary, closes the compressed file
79*44bedb31SLionel Sambuc          * and deallocates all the (de)compression state. The return value is
80*44bedb31SLionel Sambuc          * the zlib error number (see function error() below).
81*44bedb31SLionel Sambuc          */
close()82*44bedb31SLionel Sambuc         int close() {
83*44bedb31SLionel Sambuc             int r = ::gzclose(m_fp);
84*44bedb31SLionel Sambuc             m_fp = 0; return r;
85*44bedb31SLionel Sambuc         }
86*44bedb31SLionel Sambuc 
87*44bedb31SLionel Sambuc         /* Binary read the given number of bytes from the compressed file.
88*44bedb31SLionel Sambuc          */
read(void * buf,size_t len)89*44bedb31SLionel Sambuc         int read(void* buf, size_t len) {
90*44bedb31SLionel Sambuc             return ::gzread(m_fp, buf, len);
91*44bedb31SLionel Sambuc         }
92*44bedb31SLionel Sambuc 
93*44bedb31SLionel Sambuc         /* Returns the error message for the last error which occurred on the
94*44bedb31SLionel Sambuc          * given compressed file. errnum is set to zlib error number. If an
95*44bedb31SLionel Sambuc          * error occurred in the file system and not in the compression library,
96*44bedb31SLionel Sambuc          * errnum is set to Z_ERRNO and the application may consult errno
97*44bedb31SLionel Sambuc          * to get the exact error code.
98*44bedb31SLionel Sambuc          */
error(int * errnum)99*44bedb31SLionel Sambuc         const char* error(int* errnum) {
100*44bedb31SLionel Sambuc             return ::gzerror(m_fp, errnum);
101*44bedb31SLionel Sambuc         }
102*44bedb31SLionel Sambuc 
fp()103*44bedb31SLionel Sambuc         gzFile fp() { return m_fp; }
104*44bedb31SLionel Sambuc 
105*44bedb31SLionel Sambuc     private:
106*44bedb31SLionel Sambuc         gzFile m_fp;
107*44bedb31SLionel Sambuc };
108*44bedb31SLionel Sambuc 
109*44bedb31SLionel Sambuc /*
110*44bedb31SLionel Sambuc  * Binary read the given (array of) object(s) from the compressed file.
111*44bedb31SLionel Sambuc  * If the input file was not in gzip format, read() copies the objects number
112*44bedb31SLionel Sambuc  * of bytes into the buffer.
113*44bedb31SLionel Sambuc  * returns the number of uncompressed bytes actually read
114*44bedb31SLionel Sambuc  * (0 for end of file, -1 for error).
115*44bedb31SLionel Sambuc  */
116*44bedb31SLionel Sambuc template <class T, class Items>
read(izstream & zs,T * x,Items items)117*44bedb31SLionel Sambuc inline int read(izstream& zs, T* x, Items items) {
118*44bedb31SLionel Sambuc     return ::gzread(zs.fp(), x, items*sizeof(T));
119*44bedb31SLionel Sambuc }
120*44bedb31SLionel Sambuc 
121*44bedb31SLionel Sambuc /*
122*44bedb31SLionel Sambuc  * Binary input with the '>' operator.
123*44bedb31SLionel Sambuc  */
124*44bedb31SLionel Sambuc template <class T>
125*44bedb31SLionel Sambuc inline izstream& operator>(izstream& zs, T& x) {
126*44bedb31SLionel Sambuc     ::gzread(zs.fp(), &x, sizeof(T));
127*44bedb31SLionel Sambuc     return zs;
128*44bedb31SLionel Sambuc }
129*44bedb31SLionel Sambuc 
130*44bedb31SLionel Sambuc 
zstringlen(izstream & zs)131*44bedb31SLionel Sambuc inline zstringlen::zstringlen(izstream& zs) {
132*44bedb31SLionel Sambuc     zs > val.byte;
133*44bedb31SLionel Sambuc     if (val.byte == 255) zs > val.word;
134*44bedb31SLionel Sambuc     else val.word = val.byte;
135*44bedb31SLionel Sambuc }
136*44bedb31SLionel Sambuc 
137*44bedb31SLionel Sambuc /*
138*44bedb31SLionel Sambuc  * Read length of string + the string with the '>' operator.
139*44bedb31SLionel Sambuc  */
140*44bedb31SLionel Sambuc inline izstream& operator>(izstream& zs, char* x) {
141*44bedb31SLionel Sambuc     zstringlen len(zs);
142*44bedb31SLionel Sambuc     ::gzread(zs.fp(), x, len.value());
143*44bedb31SLionel Sambuc     x[len.value()] = '\0';
144*44bedb31SLionel Sambuc     return zs;
145*44bedb31SLionel Sambuc }
146*44bedb31SLionel Sambuc 
read_string(izstream & zs)147*44bedb31SLionel Sambuc inline char* read_string(izstream& zs) {
148*44bedb31SLionel Sambuc     zstringlen len(zs);
149*44bedb31SLionel Sambuc     char* x = new char[len.value()+1];
150*44bedb31SLionel Sambuc     ::gzread(zs.fp(), x, len.value());
151*44bedb31SLionel Sambuc     x[len.value()] = '\0';
152*44bedb31SLionel Sambuc     return x;
153*44bedb31SLionel Sambuc }
154*44bedb31SLionel Sambuc 
155*44bedb31SLionel Sambuc // ----------------------------- ozstream -----------------------------
156*44bedb31SLionel Sambuc 
157*44bedb31SLionel Sambuc class ozstream
158*44bedb31SLionel Sambuc {
159*44bedb31SLionel Sambuc     public:
ozstream()160*44bedb31SLionel Sambuc         ozstream() : m_fp(0), m_os(0) {
161*44bedb31SLionel Sambuc         }
162*44bedb31SLionel Sambuc         ozstream(FILE* fp, int level = Z_DEFAULT_COMPRESSION)
163*44bedb31SLionel Sambuc             : m_fp(0), m_os(0) {
164*44bedb31SLionel Sambuc             open(fp, level);
165*44bedb31SLionel Sambuc         }
166*44bedb31SLionel Sambuc         ozstream(const char* name, int level = Z_DEFAULT_COMPRESSION)
167*44bedb31SLionel Sambuc             : m_fp(0), m_os(0) {
168*44bedb31SLionel Sambuc             open(name, level);
169*44bedb31SLionel Sambuc         }
~ozstream()170*44bedb31SLionel Sambuc         ~ozstream() {
171*44bedb31SLionel Sambuc             close();
172*44bedb31SLionel Sambuc         }
173*44bedb31SLionel Sambuc 
174*44bedb31SLionel Sambuc         /* Opens a gzip (.gz) file for writing.
175*44bedb31SLionel Sambuc          * The compression level parameter should be in 0..9
176*44bedb31SLionel Sambuc          * errno can be checked to distinguish two error cases
177*44bedb31SLionel Sambuc          * (if errno is zero, the zlib error is Z_MEM_ERROR).
178*44bedb31SLionel Sambuc          */
179*44bedb31SLionel Sambuc         void open(const char* name, int level = Z_DEFAULT_COMPRESSION) {
180*44bedb31SLionel Sambuc             char mode[4] = "wb\0";
181*44bedb31SLionel Sambuc             if (level != Z_DEFAULT_COMPRESSION) mode[2] = '0'+level;
182*44bedb31SLionel Sambuc             if (m_fp) close();
183*44bedb31SLionel Sambuc             m_fp = ::gzopen(name, mode);
184*44bedb31SLionel Sambuc         }
185*44bedb31SLionel Sambuc 
186*44bedb31SLionel Sambuc         /* open from a FILE pointer.
187*44bedb31SLionel Sambuc          */
188*44bedb31SLionel Sambuc         void open(FILE* fp, int level = Z_DEFAULT_COMPRESSION) {
189*44bedb31SLionel Sambuc             SET_BINARY_MODE(fp);
190*44bedb31SLionel Sambuc             char mode[4] = "wb\0";
191*44bedb31SLionel Sambuc             if (level != Z_DEFAULT_COMPRESSION) mode[2] = '0'+level;
192*44bedb31SLionel Sambuc             if (m_fp) close();
193*44bedb31SLionel Sambuc             m_fp = ::gzdopen(fileno(fp), mode);
194*44bedb31SLionel Sambuc         }
195*44bedb31SLionel Sambuc 
196*44bedb31SLionel Sambuc         /* Flushes all pending output if necessary, closes the compressed file
197*44bedb31SLionel Sambuc          * and deallocates all the (de)compression state. The return value is
198*44bedb31SLionel Sambuc          * the zlib error number (see function error() below).
199*44bedb31SLionel Sambuc          */
close()200*44bedb31SLionel Sambuc         int close() {
201*44bedb31SLionel Sambuc             if (m_os) {
202*44bedb31SLionel Sambuc                 ::gzwrite(m_fp, m_os->str(), m_os->pcount());
203*44bedb31SLionel Sambuc                 delete[] m_os->str(); delete m_os; m_os = 0;
204*44bedb31SLionel Sambuc             }
205*44bedb31SLionel Sambuc             int r = ::gzclose(m_fp); m_fp = 0; return r;
206*44bedb31SLionel Sambuc         }
207*44bedb31SLionel Sambuc 
208*44bedb31SLionel Sambuc         /* Binary write the given number of bytes into the compressed file.
209*44bedb31SLionel Sambuc          */
write(const void * buf,size_t len)210*44bedb31SLionel Sambuc         int write(const void* buf, size_t len) {
211*44bedb31SLionel Sambuc             return ::gzwrite(m_fp, (voidp) buf, len);
212*44bedb31SLionel Sambuc         }
213*44bedb31SLionel Sambuc 
214*44bedb31SLionel Sambuc         /* Flushes all pending output into the compressed file. The parameter
215*44bedb31SLionel Sambuc          * _flush is as in the deflate() function. The return value is the zlib
216*44bedb31SLionel Sambuc          * error number (see function gzerror below). flush() returns Z_OK if
217*44bedb31SLionel Sambuc          * the flush_ parameter is Z_FINISH and all output could be flushed.
218*44bedb31SLionel Sambuc          * flush() should be called only when strictly necessary because it can
219*44bedb31SLionel Sambuc          * degrade compression.
220*44bedb31SLionel Sambuc          */
flush(int _flush)221*44bedb31SLionel Sambuc         int flush(int _flush) {
222*44bedb31SLionel Sambuc             os_flush();
223*44bedb31SLionel Sambuc             return ::gzflush(m_fp, _flush);
224*44bedb31SLionel Sambuc         }
225*44bedb31SLionel Sambuc 
226*44bedb31SLionel Sambuc         /* Returns the error message for the last error which occurred on the
227*44bedb31SLionel Sambuc          * given compressed file. errnum is set to zlib error number. If an
228*44bedb31SLionel Sambuc          * error occurred in the file system and not in the compression library,
229*44bedb31SLionel Sambuc          * errnum is set to Z_ERRNO and the application may consult errno
230*44bedb31SLionel Sambuc          * to get the exact error code.
231*44bedb31SLionel Sambuc          */
error(int * errnum)232*44bedb31SLionel Sambuc         const char* error(int* errnum) {
233*44bedb31SLionel Sambuc             return ::gzerror(m_fp, errnum);
234*44bedb31SLionel Sambuc         }
235*44bedb31SLionel Sambuc 
fp()236*44bedb31SLionel Sambuc         gzFile fp() { return m_fp; }
237*44bedb31SLionel Sambuc 
os()238*44bedb31SLionel Sambuc         ostream& os() {
239*44bedb31SLionel Sambuc             if (m_os == 0) m_os = new ostrstream;
240*44bedb31SLionel Sambuc             return *m_os;
241*44bedb31SLionel Sambuc         }
242*44bedb31SLionel Sambuc 
os_flush()243*44bedb31SLionel Sambuc         void os_flush() {
244*44bedb31SLionel Sambuc             if (m_os && m_os->pcount()>0) {
245*44bedb31SLionel Sambuc                 ostrstream* oss = new ostrstream;
246*44bedb31SLionel Sambuc                 oss->fill(m_os->fill());
247*44bedb31SLionel Sambuc                 oss->flags(m_os->flags());
248*44bedb31SLionel Sambuc                 oss->precision(m_os->precision());
249*44bedb31SLionel Sambuc                 oss->width(m_os->width());
250*44bedb31SLionel Sambuc                 ::gzwrite(m_fp, m_os->str(), m_os->pcount());
251*44bedb31SLionel Sambuc                 delete[] m_os->str(); delete m_os; m_os = oss;
252*44bedb31SLionel Sambuc             }
253*44bedb31SLionel Sambuc         }
254*44bedb31SLionel Sambuc 
255*44bedb31SLionel Sambuc     private:
256*44bedb31SLionel Sambuc         gzFile m_fp;
257*44bedb31SLionel Sambuc         ostrstream* m_os;
258*44bedb31SLionel Sambuc };
259*44bedb31SLionel Sambuc 
260*44bedb31SLionel Sambuc /*
261*44bedb31SLionel Sambuc  * Binary write the given (array of) object(s) into the compressed file.
262*44bedb31SLionel Sambuc  * returns the number of uncompressed bytes actually written
263*44bedb31SLionel Sambuc  * (0 in case of error).
264*44bedb31SLionel Sambuc  */
265*44bedb31SLionel Sambuc template <class T, class Items>
write(ozstream & zs,const T * x,Items items)266*44bedb31SLionel Sambuc inline int write(ozstream& zs, const T* x, Items items) {
267*44bedb31SLionel Sambuc     return ::gzwrite(zs.fp(), (voidp) x, items*sizeof(T));
268*44bedb31SLionel Sambuc }
269*44bedb31SLionel Sambuc 
270*44bedb31SLionel Sambuc /*
271*44bedb31SLionel Sambuc  * Binary output with the '<' operator.
272*44bedb31SLionel Sambuc  */
273*44bedb31SLionel Sambuc template <class T>
274*44bedb31SLionel Sambuc inline ozstream& operator<(ozstream& zs, const T& x) {
275*44bedb31SLionel Sambuc     ::gzwrite(zs.fp(), (voidp) &x, sizeof(T));
276*44bedb31SLionel Sambuc     return zs;
277*44bedb31SLionel Sambuc }
278*44bedb31SLionel Sambuc 
zstringlen(ozstream & zs,const char * x)279*44bedb31SLionel Sambuc inline zstringlen::zstringlen(ozstream& zs, const char* x) {
280*44bedb31SLionel Sambuc     val.byte = 255;  val.word = ::strlen(x);
281*44bedb31SLionel Sambuc     if (val.word < 255) zs < (val.byte = val.word);
282*44bedb31SLionel Sambuc     else zs < val;
283*44bedb31SLionel Sambuc }
284*44bedb31SLionel Sambuc 
285*44bedb31SLionel Sambuc /*
286*44bedb31SLionel Sambuc  * Write length of string + the string with the '<' operator.
287*44bedb31SLionel Sambuc  */
288*44bedb31SLionel Sambuc inline ozstream& operator<(ozstream& zs, const char* x) {
289*44bedb31SLionel Sambuc     zstringlen len(zs, x);
290*44bedb31SLionel Sambuc     ::gzwrite(zs.fp(), (voidp) x, len.value());
291*44bedb31SLionel Sambuc     return zs;
292*44bedb31SLionel Sambuc }
293*44bedb31SLionel Sambuc 
294*44bedb31SLionel Sambuc #ifdef _MSC_VER
295*44bedb31SLionel Sambuc inline ozstream& operator<(ozstream& zs, char* const& x) {
296*44bedb31SLionel Sambuc     return zs < (const char*) x;
297*44bedb31SLionel Sambuc }
298*44bedb31SLionel Sambuc #endif
299*44bedb31SLionel Sambuc 
300*44bedb31SLionel Sambuc /*
301*44bedb31SLionel Sambuc  * Ascii write with the << operator;
302*44bedb31SLionel Sambuc  */
303*44bedb31SLionel Sambuc template <class T>
304*44bedb31SLionel Sambuc inline ostream& operator<<(ozstream& zs, const T& x) {
305*44bedb31SLionel Sambuc     zs.os_flush();
306*44bedb31SLionel Sambuc     return zs.os() << x;
307*44bedb31SLionel Sambuc }
308*44bedb31SLionel Sambuc 
309*44bedb31SLionel Sambuc #endif
310