2 * A C++ I/O streams interface to the zlib gz* functions
4 * by Ludwig Schwardt <schwardt@sun.ac.za>
5 * original version by Kevin Ruland <kevin@rodin.wustl.edu>
7 * This version is standard-compliant and compatible with gcc 3.x.
13 #include <istream> // not iostream, since we don't need cin/cout
17 /*****************************************************************************/
20 * @brief Gzipped file stream buffer class.
22 * This class implements basic_filebuf for gzipped files. It doesn't yet support
23 * seeking (allowed by zlib but slow/limited), putback and read/write access
24 * (tricky). Otherwise, it attempts to be a drop-in replacement for the standard
27 class gzfilebuf : public std::streambuf
30 // Default constructor.
38 * @brief Set compression level and strategy on the fly.
39 * @param comp_level Compression level (see zlib.h for allowed values)
40 * @param comp_strategy Compression strategy (see zlib.h for allowed values)
41 * @return Z_OK on success, Z_STREAM_ERROR otherwise.
43 * Unfortunately, these parameters cannot be modified separately, as the
44 * previous zfstream version assumed. Since the strategy is seldom changed,
45 * it can default and setcompression(level) then becomes like the old
46 * setcompressionlevel(level).
49 setcompression(int comp_level,
50 int comp_strategy = Z_DEFAULT_STRATEGY);
53 * @brief Check if file is open.
54 * @return True if file is open.
57 is_open() const { return (file != NULL); }
60 * @brief Open gzipped file.
61 * @param name File name.
62 * @param mode Open mode flags.
63 * @return @c this on success, NULL on failure.
66 open(const char* name,
67 std::ios_base::openmode mode);
70 * @brief Attach to already open gzipped file.
71 * @param fd File descriptor.
72 * @param mode Open mode flags.
73 * @return @c this on success, NULL on failure.
77 std::ios_base::openmode mode);
80 * @brief Close gzipped file.
81 * @return @c this on success, NULL on failure.
88 * @brief Convert ios open mode int to mode string used by zlib.
89 * @return True if valid mode flag combination.
92 open_mode(std::ios_base::openmode mode,
96 * @brief Number of characters available in stream buffer.
97 * @return Number of characters.
99 * This indicates number of characters in get area of stream buffer.
100 * These characters can be read without accessing the gzipped file.
102 virtual std::streamsize
106 * @brief Fill get area from gzipped file.
107 * @return First character in get area on success, EOF on error.
109 * This actually reads characters from gzipped file to stream
110 * buffer. Always buffered.
116 * @brief Write put area to gzipped file.
117 * @param c Extra character to add to buffer contents.
118 * @return Non-EOF on success, EOF on error.
120 * This actually writes characters in stream buffer to
121 * gzipped file. With unbuffered output this is done one
122 * character at a time.
125 overflow(int_type c = traits_type::eof());
128 * @brief Installs external stream buffer.
129 * @param p Pointer to char buffer.
130 * @param n Size of external buffer.
131 * @return @c this on success, NULL on failure.
133 * Call setbuf(0,0) to enable unbuffered output.
135 virtual std::streambuf*
140 * @brief Flush stream buffer to file.
141 * @return 0 on success, -1 on error.
143 * This calls underflow(EOF) to do the job.
149 // Some future enhancements
151 // virtual int_type uflow();
152 // virtual int_type pbackfail(int_type c = traits_type::eof());
154 // seekoff(off_type off,
155 // std::ios_base::seekdir way,
156 // std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out);
158 // seekpos(pos_type sp,
159 // std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out);
163 * @brief Allocate internal buffer.
165 * This function is safe to call multiple times. It will ensure
166 * that a proper internal buffer exists if it is required. If the
167 * buffer already exists or is external, the buffer pointers will be
168 * reset to their original state.
174 * @brief Destroy internal buffer.
176 * This function is safe to call multiple times. It will ensure
177 * that the internal buffer is deallocated if it exists. In any
178 * case, it will also reset the buffer pointers.
184 * Underlying file pointer.
189 * Mode in which file was opened.
191 std::ios_base::openmode io_mode;
194 * @brief True if this object owns file descriptor.
196 * This makes the class responsible for closing the file
202 * @brief Stream buffer.
204 * For simplicity this remains allocated on the free store for the
205 * entire life span of the gzfilebuf object, unless replaced by setbuf.
210 * @brief Stream buffer size.
212 * Defaults to system default buffer size (typically 8192 bytes).
213 * Modified by setbuf.
215 std::streamsize buffer_size;
218 * @brief True if this object owns stream buffer.
220 * This makes the class responsible for deleting the buffer
226 /*****************************************************************************/
229 * @brief Gzipped file input stream class.
231 * This class implements ifstream for gzipped files. Seeking and putback
232 * is not supported yet.
234 class gzifstream : public std::istream
237 // Default constructor
241 * @brief Construct stream on gzipped file to be opened.
242 * @param name File name.
243 * @param mode Open mode flags (forced to contain ios::in).
246 gzifstream(const char* name,
247 std::ios_base::openmode mode = std::ios_base::in);
250 * @brief Construct stream on already open gzipped file.
251 * @param fd File descriptor.
252 * @param mode Open mode flags (forced to contain ios::in).
256 std::ios_base::openmode mode = std::ios_base::in);
259 * Obtain underlying stream buffer.
263 { return const_cast<gzfilebuf*>(&sb); }
266 * @brief Check if file is open.
267 * @return True if file is open.
270 is_open() { return sb.is_open(); }
273 * @brief Open gzipped file.
274 * @param name File name.
275 * @param mode Open mode flags (forced to contain ios::in).
277 * Stream will be in state good() if file opens successfully;
278 * otherwise in state fail(). This differs from the behavior of
279 * ifstream, which never sets the state to good() and therefore
280 * won't allow you to reuse the stream for a second file unless
281 * you manually clear() the state. The choice is a matter of
285 open(const char* name,
286 std::ios_base::openmode mode = std::ios_base::in);
289 * @brief Attach to already open gzipped file.
290 * @param fd File descriptor.
291 * @param mode Open mode flags (forced to contain ios::in).
293 * Stream will be in state good() if attach succeeded; otherwise
298 std::ios_base::openmode mode = std::ios_base::in);
301 * @brief Close gzipped file.
303 * Stream will be in state fail() if close failed.
310 * Underlying stream buffer.
315 /*****************************************************************************/
318 * @brief Gzipped file output stream class.
320 * This class implements ofstream for gzipped files. Seeking and putback
321 * is not supported yet.
323 class gzofstream : public std::ostream
326 // Default constructor
330 * @brief Construct stream on gzipped file to be opened.
331 * @param name File name.
332 * @param mode Open mode flags (forced to contain ios::out).
335 gzofstream(const char* name,
336 std::ios_base::openmode mode = std::ios_base::out);
339 * @brief Construct stream on already open gzipped file.
340 * @param fd File descriptor.
341 * @param mode Open mode flags (forced to contain ios::out).
345 std::ios_base::openmode mode = std::ios_base::out);
348 * Obtain underlying stream buffer.
352 { return const_cast<gzfilebuf*>(&sb); }
355 * @brief Check if file is open.
356 * @return True if file is open.
359 is_open() { return sb.is_open(); }
362 * @brief Open gzipped file.
363 * @param name File name.
364 * @param mode Open mode flags (forced to contain ios::out).
366 * Stream will be in state good() if file opens successfully;
367 * otherwise in state fail(). This differs from the behavior of
368 * ofstream, which never sets the state to good() and therefore
369 * won't allow you to reuse the stream for a second file unless
370 * you manually clear() the state. The choice is a matter of
374 open(const char* name,
375 std::ios_base::openmode mode = std::ios_base::out);
378 * @brief Attach to already open gzipped file.
379 * @param fd File descriptor.
380 * @param mode Open mode flags (forced to contain ios::out).
382 * Stream will be in state good() if attach succeeded; otherwise
387 std::ios_base::openmode mode = std::ios_base::out);
390 * @brief Close gzipped file.
392 * Stream will be in state fail() if close failed.
399 * Underlying stream buffer.
404 /*****************************************************************************/
407 * @brief Gzipped file output stream manipulator class.
409 * This class defines a two-argument manipulator for gzofstream. It is used
410 * as base for the setcompression(int,int) manipulator.
412 template<typename T1, typename T2>
416 // Allows insertor to peek at internals
417 template <typename Ta, typename Tb>
419 operator<<(gzofstream&,
420 const gzomanip2<Ta,Tb>&);
423 gzomanip2(gzofstream& (*f)(gzofstream&, T1, T2),
427 // Underlying manipulator function
429 (*func)(gzofstream&, T1, T2);
431 // Arguments for manipulator function
436 /*****************************************************************************/
438 // Manipulator function thunks through to stream buffer
440 setcompression(gzofstream &gzs, int l, int s = Z_DEFAULT_STRATEGY)
442 (gzs.rdbuf())->setcompression(l, s);
446 // Manipulator constructor stores arguments
447 template<typename T1, typename T2>
449 gzomanip2<T1,T2>::gzomanip2(gzofstream &(*f)(gzofstream &, T1, T2),
452 : func(f), val1(v1), val2(v2)
455 // Insertor applies underlying manipulator function to stream
456 template<typename T1, typename T2>
458 operator<<(gzofstream& s, const gzomanip2<T1,T2>& m)
459 { return (*m.func)(s, m.val1, m.val2); }
461 // Insert this onto stream to simplify setting of compression level
462 inline gzomanip2<int,int>
463 setcompression(int l, int s = Z_DEFAULT_STRATEGY)
464 { return gzomanip2<int,int>(&setcompression, l, s); }