1 /* $NetBSD: zfstream.h,v 1.1.1.1 2006/01/14 20:10:54 christos Exp $ */
4 * A C++ I/O streams interface to the zlib gz* functions
6 * by Ludwig Schwardt <schwardt@sun.ac.za>
7 * original version by Kevin Ruland <kevin@rodin.wustl.edu>
9 * This version is standard-compliant and compatible with gcc 3.x.
15 #include <istream> // not iostream, since we don't need cin/cout
19 /*****************************************************************************/
22 * @brief Gzipped file stream buffer class.
24 * This class implements basic_filebuf for gzipped files. It doesn't yet support
25 * seeking (allowed by zlib but slow/limited), putback and read/write access
26 * (tricky). Otherwise, it attempts to be a drop-in replacement for the standard
29 class gzfilebuf
: public std::streambuf
32 // Default constructor.
40 * @brief Set compression level and strategy on the fly.
41 * @param comp_level Compression level (see zlib.h for allowed values)
42 * @param comp_strategy Compression strategy (see zlib.h for allowed values)
43 * @return Z_OK on success, Z_STREAM_ERROR otherwise.
45 * Unfortunately, these parameters cannot be modified separately, as the
46 * previous zfstream version assumed. Since the strategy is seldom changed,
47 * it can default and setcompression(level) then becomes like the old
48 * setcompressionlevel(level).
51 setcompression(int comp_level
,
52 int comp_strategy
= Z_DEFAULT_STRATEGY
);
55 * @brief Check if file is open.
56 * @return True if file is open.
59 is_open() const { return (file
!= NULL
); }
62 * @brief Open gzipped file.
63 * @param name File name.
64 * @param mode Open mode flags.
65 * @return @c this on success, NULL on failure.
68 open(const char* name
,
69 std::ios_base::openmode mode
);
72 * @brief Attach to already open gzipped file.
73 * @param fd File descriptor.
74 * @param mode Open mode flags.
75 * @return @c this on success, NULL on failure.
79 std::ios_base::openmode mode
);
82 * @brief Close gzipped file.
83 * @return @c this on success, NULL on failure.
90 * @brief Convert ios open mode int to mode string used by zlib.
91 * @return True if valid mode flag combination.
94 open_mode(std::ios_base::openmode mode
,
98 * @brief Number of characters available in stream buffer.
99 * @return Number of characters.
101 * This indicates number of characters in get area of stream buffer.
102 * These characters can be read without accessing the gzipped file.
104 virtual std::streamsize
108 * @brief Fill get area from gzipped file.
109 * @return First character in get area on success, EOF on error.
111 * This actually reads characters from gzipped file to stream
112 * buffer. Always buffered.
118 * @brief Write put area to gzipped file.
119 * @param c Extra character to add to buffer contents.
120 * @return Non-EOF on success, EOF on error.
122 * This actually writes characters in stream buffer to
123 * gzipped file. With unbuffered output this is done one
124 * character at a time.
127 overflow(int_type c
= traits_type::eof());
130 * @brief Installs external stream buffer.
131 * @param p Pointer to char buffer.
132 * @param n Size of external buffer.
133 * @return @c this on success, NULL on failure.
135 * Call setbuf(0,0) to enable unbuffered output.
137 virtual std::streambuf
*
142 * @brief Flush stream buffer to file.
143 * @return 0 on success, -1 on error.
145 * This calls underflow(EOF) to do the job.
151 // Some future enhancements
153 // virtual int_type uflow();
154 // virtual int_type pbackfail(int_type c = traits_type::eof());
156 // seekoff(off_type off,
157 // std::ios_base::seekdir way,
158 // std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out);
160 // seekpos(pos_type sp,
161 // std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out);
165 * @brief Allocate internal buffer.
167 * This function is safe to call multiple times. It will ensure
168 * that a proper internal buffer exists if it is required. If the
169 * buffer already exists or is external, the buffer pointers will be
170 * reset to their original state.
176 * @brief Destroy internal buffer.
178 * This function is safe to call multiple times. It will ensure
179 * that the internal buffer is deallocated if it exists. In any
180 * case, it will also reset the buffer pointers.
186 * Underlying file pointer.
191 * Mode in which file was opened.
193 std::ios_base::openmode io_mode
;
196 * @brief True if this object owns file descriptor.
198 * This makes the class responsible for closing the file
204 * @brief Stream buffer.
206 * For simplicity this remains allocated on the free store for the
207 * entire life span of the gzfilebuf object, unless replaced by setbuf.
212 * @brief Stream buffer size.
214 * Defaults to system default buffer size (typically 8192 bytes).
215 * Modified by setbuf.
217 std::streamsize buffer_size
;
220 * @brief True if this object owns stream buffer.
222 * This makes the class responsible for deleting the buffer
228 /*****************************************************************************/
231 * @brief Gzipped file input stream class.
233 * This class implements ifstream for gzipped files. Seeking and putback
234 * is not supported yet.
236 class gzifstream
: public std::istream
239 // Default constructor
243 * @brief Construct stream on gzipped file to be opened.
244 * @param name File name.
245 * @param mode Open mode flags (forced to contain ios::in).
248 gzifstream(const char* name
,
249 std::ios_base::openmode mode
= std::ios_base::in
);
252 * @brief Construct stream on already open gzipped file.
253 * @param fd File descriptor.
254 * @param mode Open mode flags (forced to contain ios::in).
258 std::ios_base::openmode mode
= std::ios_base::in
);
261 * Obtain underlying stream buffer.
265 { return const_cast<gzfilebuf
*>(&sb
); }
268 * @brief Check if file is open.
269 * @return True if file is open.
272 is_open() { return sb
.is_open(); }
275 * @brief Open gzipped file.
276 * @param name File name.
277 * @param mode Open mode flags (forced to contain ios::in).
279 * Stream will be in state good() if file opens successfully;
280 * otherwise in state fail(). This differs from the behavior of
281 * ifstream, which never sets the state to good() and therefore
282 * won't allow you to reuse the stream for a second file unless
283 * you manually clear() the state. The choice is a matter of
287 open(const char* name
,
288 std::ios_base::openmode mode
= std::ios_base::in
);
291 * @brief Attach to already open gzipped file.
292 * @param fd File descriptor.
293 * @param mode Open mode flags (forced to contain ios::in).
295 * Stream will be in state good() if attach succeeded; otherwise
300 std::ios_base::openmode mode
= std::ios_base::in
);
303 * @brief Close gzipped file.
305 * Stream will be in state fail() if close failed.
312 * Underlying stream buffer.
317 /*****************************************************************************/
320 * @brief Gzipped file output stream class.
322 * This class implements ofstream for gzipped files. Seeking and putback
323 * is not supported yet.
325 class gzofstream
: public std::ostream
328 // Default constructor
332 * @brief Construct stream on gzipped file to be opened.
333 * @param name File name.
334 * @param mode Open mode flags (forced to contain ios::out).
337 gzofstream(const char* name
,
338 std::ios_base::openmode mode
= std::ios_base::out
);
341 * @brief Construct stream on already open gzipped file.
342 * @param fd File descriptor.
343 * @param mode Open mode flags (forced to contain ios::out).
347 std::ios_base::openmode mode
= std::ios_base::out
);
350 * Obtain underlying stream buffer.
354 { return const_cast<gzfilebuf
*>(&sb
); }
357 * @brief Check if file is open.
358 * @return True if file is open.
361 is_open() { return sb
.is_open(); }
364 * @brief Open gzipped file.
365 * @param name File name.
366 * @param mode Open mode flags (forced to contain ios::out).
368 * Stream will be in state good() if file opens successfully;
369 * otherwise in state fail(). This differs from the behavior of
370 * ofstream, which never sets the state to good() and therefore
371 * won't allow you to reuse the stream for a second file unless
372 * you manually clear() the state. The choice is a matter of
376 open(const char* name
,
377 std::ios_base::openmode mode
= std::ios_base::out
);
380 * @brief Attach to already open gzipped file.
381 * @param fd File descriptor.
382 * @param mode Open mode flags (forced to contain ios::out).
384 * Stream will be in state good() if attach succeeded; otherwise
389 std::ios_base::openmode mode
= std::ios_base::out
);
392 * @brief Close gzipped file.
394 * Stream will be in state fail() if close failed.
401 * Underlying stream buffer.
406 /*****************************************************************************/
409 * @brief Gzipped file output stream manipulator class.
411 * This class defines a two-argument manipulator for gzofstream. It is used
412 * as base for the setcompression(int,int) manipulator.
414 template<typename T1
, typename T2
>
418 // Allows insertor to peek at internals
419 template <typename Ta
, typename Tb
>
421 operator<<(gzofstream
&,
422 const gzomanip2
<Ta
,Tb
>&);
425 gzomanip2(gzofstream
& (*f
)(gzofstream
&, T1
, T2
),
429 // Underlying manipulator function
431 (*func
)(gzofstream
&, T1
, T2
);
433 // Arguments for manipulator function
438 /*****************************************************************************/
440 // Manipulator function thunks through to stream buffer
442 setcompression(gzofstream
&gzs
, int l
, int s
= Z_DEFAULT_STRATEGY
)
444 (gzs
.rdbuf())->setcompression(l
, s
);
448 // Manipulator constructor stores arguments
449 template<typename T1
, typename T2
>
451 gzomanip2
<T1
,T2
>::gzomanip2(gzofstream
&(*f
)(gzofstream
&, T1
, T2
),
454 : func(f
), val1(v1
), val2(v2
)
457 // Insertor applies underlying manipulator function to stream
458 template<typename T1
, typename T2
>
460 operator<<(gzofstream
& s
, const gzomanip2
<T1
,T2
>& m
)
461 { return (*m
.func
)(s
, m
.val1
, m
.val2
); }
463 // Insert this onto stream to simplify setting of compression level
464 inline gzomanip2
<int,int>
465 setcompression(int l
, int s
= Z_DEFAULT_STRATEGY
)
466 { return gzomanip2
<int,int>(&setcompression
, l
, s
); }