zfstream.h revision 1.1.1.3 1 1.1 christos /*
2 1.1 christos * A C++ I/O streams interface to the zlib gz* functions
3 1.1 christos *
4 1.1 christos * by Ludwig Schwardt <schwardt (at) sun.ac.za>
5 1.1 christos * original version by Kevin Ruland <kevin (at) rodin.wustl.edu>
6 1.1 christos *
7 1.1 christos * This version is standard-compliant and compatible with gcc 3.x.
8 1.1 christos */
9 1.1 christos
10 1.1 christos #ifndef ZFSTREAM_H
11 1.1 christos #define ZFSTREAM_H
12 1.1 christos
13 1.1 christos #include <istream> // not iostream, since we don't need cin/cout
14 1.1 christos #include <ostream>
15 1.1 christos #include "zlib.h"
16 1.1 christos
17 1.1 christos /*****************************************************************************/
18 1.1 christos
19 1.1 christos /**
20 1.1 christos * @brief Gzipped file stream buffer class.
21 1.1 christos *
22 1.1 christos * This class implements basic_filebuf for gzipped files. It doesn't yet support
23 1.1 christos * seeking (allowed by zlib but slow/limited), putback and read/write access
24 1.1 christos * (tricky). Otherwise, it attempts to be a drop-in replacement for the standard
25 1.1 christos * file streambuf.
26 1.1 christos */
27 1.1 christos class gzfilebuf : public std::streambuf
28 1.1 christos {
29 1.1 christos public:
30 1.1 christos // Default constructor.
31 1.1 christos gzfilebuf();
32 1.1 christos
33 1.1 christos // Destructor.
34 1.1 christos virtual
35 1.1 christos ~gzfilebuf();
36 1.1 christos
37 1.1 christos /**
38 1.1 christos * @brief Set compression level and strategy on the fly.
39 1.1 christos * @param comp_level Compression level (see zlib.h for allowed values)
40 1.1 christos * @param comp_strategy Compression strategy (see zlib.h for allowed values)
41 1.1 christos * @return Z_OK on success, Z_STREAM_ERROR otherwise.
42 1.1 christos *
43 1.1 christos * Unfortunately, these parameters cannot be modified separately, as the
44 1.1 christos * previous zfstream version assumed. Since the strategy is seldom changed,
45 1.1 christos * it can default and setcompression(level) then becomes like the old
46 1.1 christos * setcompressionlevel(level).
47 1.1 christos */
48 1.1 christos int
49 1.1 christos setcompression(int comp_level,
50 1.1 christos int comp_strategy = Z_DEFAULT_STRATEGY);
51 1.1 christos
52 1.1 christos /**
53 1.1 christos * @brief Check if file is open.
54 1.1 christos * @return True if file is open.
55 1.1 christos */
56 1.1 christos bool
57 1.1 christos is_open() const { return (file != NULL); }
58 1.1 christos
59 1.1 christos /**
60 1.1 christos * @brief Open gzipped file.
61 1.1 christos * @param name File name.
62 1.1 christos * @param mode Open mode flags.
63 1.1 christos * @return @c this on success, NULL on failure.
64 1.1 christos */
65 1.1 christos gzfilebuf*
66 1.1 christos open(const char* name,
67 1.1 christos std::ios_base::openmode mode);
68 1.1 christos
69 1.1 christos /**
70 1.1 christos * @brief Attach to already open gzipped file.
71 1.1 christos * @param fd File descriptor.
72 1.1 christos * @param mode Open mode flags.
73 1.1 christos * @return @c this on success, NULL on failure.
74 1.1 christos */
75 1.1 christos gzfilebuf*
76 1.1 christos attach(int fd,
77 1.1 christos std::ios_base::openmode mode);
78 1.1 christos
79 1.1 christos /**
80 1.1 christos * @brief Close gzipped file.
81 1.1 christos * @return @c this on success, NULL on failure.
82 1.1 christos */
83 1.1 christos gzfilebuf*
84 1.1 christos close();
85 1.1 christos
86 1.1 christos protected:
87 1.1 christos /**
88 1.1 christos * @brief Convert ios open mode int to mode string used by zlib.
89 1.1 christos * @return True if valid mode flag combination.
90 1.1 christos */
91 1.1 christos bool
92 1.1 christos open_mode(std::ios_base::openmode mode,
93 1.1 christos char* c_mode) const;
94 1.1 christos
95 1.1 christos /**
96 1.1 christos * @brief Number of characters available in stream buffer.
97 1.1 christos * @return Number of characters.
98 1.1 christos *
99 1.1 christos * This indicates number of characters in get area of stream buffer.
100 1.1 christos * These characters can be read without accessing the gzipped file.
101 1.1 christos */
102 1.1 christos virtual std::streamsize
103 1.1 christos showmanyc();
104 1.1 christos
105 1.1 christos /**
106 1.1 christos * @brief Fill get area from gzipped file.
107 1.1 christos * @return First character in get area on success, EOF on error.
108 1.1 christos *
109 1.1 christos * This actually reads characters from gzipped file to stream
110 1.1 christos * buffer. Always buffered.
111 1.1 christos */
112 1.1 christos virtual int_type
113 1.1 christos underflow();
114 1.1 christos
115 1.1 christos /**
116 1.1 christos * @brief Write put area to gzipped file.
117 1.1 christos * @param c Extra character to add to buffer contents.
118 1.1 christos * @return Non-EOF on success, EOF on error.
119 1.1 christos *
120 1.1 christos * This actually writes characters in stream buffer to
121 1.1 christos * gzipped file. With unbuffered output this is done one
122 1.1 christos * character at a time.
123 1.1 christos */
124 1.1 christos virtual int_type
125 1.1 christos overflow(int_type c = traits_type::eof());
126 1.1 christos
127 1.1 christos /**
128 1.1 christos * @brief Installs external stream buffer.
129 1.1 christos * @param p Pointer to char buffer.
130 1.1 christos * @param n Size of external buffer.
131 1.1 christos * @return @c this on success, NULL on failure.
132 1.1 christos *
133 1.1 christos * Call setbuf(0,0) to enable unbuffered output.
134 1.1 christos */
135 1.1 christos virtual std::streambuf*
136 1.1 christos setbuf(char_type* p,
137 1.1 christos std::streamsize n);
138 1.1 christos
139 1.1 christos /**
140 1.1 christos * @brief Flush stream buffer to file.
141 1.1 christos * @return 0 on success, -1 on error.
142 1.1 christos *
143 1.1 christos * This calls underflow(EOF) to do the job.
144 1.1 christos */
145 1.1 christos virtual int
146 1.1 christos sync();
147 1.1 christos
148 1.1 christos //
149 1.1 christos // Some future enhancements
150 1.1 christos //
151 1.1 christos // virtual int_type uflow();
152 1.1 christos // virtual int_type pbackfail(int_type c = traits_type::eof());
153 1.1 christos // virtual pos_type
154 1.1 christos // seekoff(off_type off,
155 1.1 christos // std::ios_base::seekdir way,
156 1.1 christos // std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out);
157 1.1 christos // virtual pos_type
158 1.1 christos // seekpos(pos_type sp,
159 1.1 christos // std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out);
160 1.1 christos
161 1.1 christos private:
162 1.1 christos /**
163 1.1 christos * @brief Allocate internal buffer.
164 1.1 christos *
165 1.1 christos * This function is safe to call multiple times. It will ensure
166 1.1 christos * that a proper internal buffer exists if it is required. If the
167 1.1 christos * buffer already exists or is external, the buffer pointers will be
168 1.1 christos * reset to their original state.
169 1.1 christos */
170 1.1 christos void
171 1.1 christos enable_buffer();
172 1.1 christos
173 1.1 christos /**
174 1.1 christos * @brief Destroy internal buffer.
175 1.1 christos *
176 1.1 christos * This function is safe to call multiple times. It will ensure
177 1.1 christos * that the internal buffer is deallocated if it exists. In any
178 1.1 christos * case, it will also reset the buffer pointers.
179 1.1 christos */
180 1.1 christos void
181 1.1 christos disable_buffer();
182 1.1 christos
183 1.1 christos /**
184 1.1 christos * Underlying file pointer.
185 1.1 christos */
186 1.1 christos gzFile file;
187 1.1 christos
188 1.1 christos /**
189 1.1 christos * Mode in which file was opened.
190 1.1 christos */
191 1.1 christos std::ios_base::openmode io_mode;
192 1.1 christos
193 1.1 christos /**
194 1.1 christos * @brief True if this object owns file descriptor.
195 1.1 christos *
196 1.1 christos * This makes the class responsible for closing the file
197 1.1 christos * upon destruction.
198 1.1 christos */
199 1.1 christos bool own_fd;
200 1.1 christos
201 1.1 christos /**
202 1.1 christos * @brief Stream buffer.
203 1.1 christos *
204 1.1 christos * For simplicity this remains allocated on the free store for the
205 1.1 christos * entire life span of the gzfilebuf object, unless replaced by setbuf.
206 1.1 christos */
207 1.1 christos char_type* buffer;
208 1.1 christos
209 1.1 christos /**
210 1.1 christos * @brief Stream buffer size.
211 1.1 christos *
212 1.1 christos * Defaults to system default buffer size (typically 8192 bytes).
213 1.1 christos * Modified by setbuf.
214 1.1 christos */
215 1.1 christos std::streamsize buffer_size;
216 1.1 christos
217 1.1 christos /**
218 1.1 christos * @brief True if this object owns stream buffer.
219 1.1 christos *
220 1.1 christos * This makes the class responsible for deleting the buffer
221 1.1 christos * upon destruction.
222 1.1 christos */
223 1.1 christos bool own_buffer;
224 1.1 christos };
225 1.1 christos
226 1.1 christos /*****************************************************************************/
227 1.1 christos
228 1.1 christos /**
229 1.1 christos * @brief Gzipped file input stream class.
230 1.1 christos *
231 1.1 christos * This class implements ifstream for gzipped files. Seeking and putback
232 1.1 christos * is not supported yet.
233 1.1 christos */
234 1.1 christos class gzifstream : public std::istream
235 1.1 christos {
236 1.1 christos public:
237 1.1 christos // Default constructor
238 1.1 christos gzifstream();
239 1.1 christos
240 1.1 christos /**
241 1.1 christos * @brief Construct stream on gzipped file to be opened.
242 1.1 christos * @param name File name.
243 1.1 christos * @param mode Open mode flags (forced to contain ios::in).
244 1.1 christos */
245 1.1 christos explicit
246 1.1 christos gzifstream(const char* name,
247 1.1 christos std::ios_base::openmode mode = std::ios_base::in);
248 1.1 christos
249 1.1 christos /**
250 1.1 christos * @brief Construct stream on already open gzipped file.
251 1.1 christos * @param fd File descriptor.
252 1.1 christos * @param mode Open mode flags (forced to contain ios::in).
253 1.1 christos */
254 1.1 christos explicit
255 1.1 christos gzifstream(int fd,
256 1.1 christos std::ios_base::openmode mode = std::ios_base::in);
257 1.1 christos
258 1.1 christos /**
259 1.1 christos * Obtain underlying stream buffer.
260 1.1 christos */
261 1.1 christos gzfilebuf*
262 1.1 christos rdbuf() const
263 1.1 christos { return const_cast<gzfilebuf*>(&sb); }
264 1.1 christos
265 1.1 christos /**
266 1.1 christos * @brief Check if file is open.
267 1.1 christos * @return True if file is open.
268 1.1 christos */
269 1.1 christos bool
270 1.1 christos is_open() { return sb.is_open(); }
271 1.1 christos
272 1.1 christos /**
273 1.1 christos * @brief Open gzipped file.
274 1.1 christos * @param name File name.
275 1.1 christos * @param mode Open mode flags (forced to contain ios::in).
276 1.1 christos *
277 1.1 christos * Stream will be in state good() if file opens successfully;
278 1.1 christos * otherwise in state fail(). This differs from the behavior of
279 1.1 christos * ifstream, which never sets the state to good() and therefore
280 1.1 christos * won't allow you to reuse the stream for a second file unless
281 1.1 christos * you manually clear() the state. The choice is a matter of
282 1.1 christos * convenience.
283 1.1 christos */
284 1.1 christos void
285 1.1 christos open(const char* name,
286 1.1 christos std::ios_base::openmode mode = std::ios_base::in);
287 1.1 christos
288 1.1 christos /**
289 1.1 christos * @brief Attach to already open gzipped file.
290 1.1 christos * @param fd File descriptor.
291 1.1 christos * @param mode Open mode flags (forced to contain ios::in).
292 1.1 christos *
293 1.1 christos * Stream will be in state good() if attach succeeded; otherwise
294 1.1 christos * in state fail().
295 1.1 christos */
296 1.1 christos void
297 1.1 christos attach(int fd,
298 1.1 christos std::ios_base::openmode mode = std::ios_base::in);
299 1.1 christos
300 1.1 christos /**
301 1.1 christos * @brief Close gzipped file.
302 1.1 christos *
303 1.1 christos * Stream will be in state fail() if close failed.
304 1.1 christos */
305 1.1 christos void
306 1.1 christos close();
307 1.1 christos
308 1.1 christos private:
309 1.1 christos /**
310 1.1 christos * Underlying stream buffer.
311 1.1 christos */
312 1.1 christos gzfilebuf sb;
313 1.1 christos };
314 1.1 christos
315 1.1 christos /*****************************************************************************/
316 1.1 christos
317 1.1 christos /**
318 1.1 christos * @brief Gzipped file output stream class.
319 1.1 christos *
320 1.1 christos * This class implements ofstream for gzipped files. Seeking and putback
321 1.1 christos * is not supported yet.
322 1.1 christos */
323 1.1 christos class gzofstream : public std::ostream
324 1.1 christos {
325 1.1 christos public:
326 1.1 christos // Default constructor
327 1.1 christos gzofstream();
328 1.1 christos
329 1.1 christos /**
330 1.1 christos * @brief Construct stream on gzipped file to be opened.
331 1.1 christos * @param name File name.
332 1.1 christos * @param mode Open mode flags (forced to contain ios::out).
333 1.1 christos */
334 1.1 christos explicit
335 1.1 christos gzofstream(const char* name,
336 1.1 christos std::ios_base::openmode mode = std::ios_base::out);
337 1.1 christos
338 1.1 christos /**
339 1.1 christos * @brief Construct stream on already open gzipped file.
340 1.1 christos * @param fd File descriptor.
341 1.1 christos * @param mode Open mode flags (forced to contain ios::out).
342 1.1 christos */
343 1.1 christos explicit
344 1.1 christos gzofstream(int fd,
345 1.1 christos std::ios_base::openmode mode = std::ios_base::out);
346 1.1 christos
347 1.1 christos /**
348 1.1 christos * Obtain underlying stream buffer.
349 1.1 christos */
350 1.1 christos gzfilebuf*
351 1.1 christos rdbuf() const
352 1.1 christos { return const_cast<gzfilebuf*>(&sb); }
353 1.1 christos
354 1.1 christos /**
355 1.1 christos * @brief Check if file is open.
356 1.1 christos * @return True if file is open.
357 1.1 christos */
358 1.1 christos bool
359 1.1 christos is_open() { return sb.is_open(); }
360 1.1 christos
361 1.1 christos /**
362 1.1 christos * @brief Open gzipped file.
363 1.1 christos * @param name File name.
364 1.1 christos * @param mode Open mode flags (forced to contain ios::out).
365 1.1 christos *
366 1.1 christos * Stream will be in state good() if file opens successfully;
367 1.1 christos * otherwise in state fail(). This differs from the behavior of
368 1.1 christos * ofstream, which never sets the state to good() and therefore
369 1.1 christos * won't allow you to reuse the stream for a second file unless
370 1.1 christos * you manually clear() the state. The choice is a matter of
371 1.1 christos * convenience.
372 1.1 christos */
373 1.1 christos void
374 1.1 christos open(const char* name,
375 1.1 christos std::ios_base::openmode mode = std::ios_base::out);
376 1.1 christos
377 1.1 christos /**
378 1.1 christos * @brief Attach to already open gzipped file.
379 1.1 christos * @param fd File descriptor.
380 1.1 christos * @param mode Open mode flags (forced to contain ios::out).
381 1.1 christos *
382 1.1 christos * Stream will be in state good() if attach succeeded; otherwise
383 1.1 christos * in state fail().
384 1.1 christos */
385 1.1 christos void
386 1.1 christos attach(int fd,
387 1.1 christos std::ios_base::openmode mode = std::ios_base::out);
388 1.1 christos
389 1.1 christos /**
390 1.1 christos * @brief Close gzipped file.
391 1.1 christos *
392 1.1 christos * Stream will be in state fail() if close failed.
393 1.1 christos */
394 1.1 christos void
395 1.1 christos close();
396 1.1 christos
397 1.1 christos private:
398 1.1 christos /**
399 1.1 christos * Underlying stream buffer.
400 1.1 christos */
401 1.1 christos gzfilebuf sb;
402 1.1 christos };
403 1.1 christos
404 1.1 christos /*****************************************************************************/
405 1.1 christos
406 1.1 christos /**
407 1.1 christos * @brief Gzipped file output stream manipulator class.
408 1.1 christos *
409 1.1 christos * This class defines a two-argument manipulator for gzofstream. It is used
410 1.1 christos * as base for the setcompression(int,int) manipulator.
411 1.1 christos */
412 1.1 christos template<typename T1, typename T2>
413 1.1 christos class gzomanip2
414 1.1 christos {
415 1.1 christos public:
416 1.1.1.3 christos // Allows inserter to peek at internals
417 1.1 christos template <typename Ta, typename Tb>
418 1.1 christos friend gzofstream&
419 1.1 christos operator<<(gzofstream&,
420 1.1 christos const gzomanip2<Ta,Tb>&);
421 1.1 christos
422 1.1 christos // Constructor
423 1.1 christos gzomanip2(gzofstream& (*f)(gzofstream&, T1, T2),
424 1.1 christos T1 v1,
425 1.1 christos T2 v2);
426 1.1 christos private:
427 1.1 christos // Underlying manipulator function
428 1.1 christos gzofstream&
429 1.1 christos (*func)(gzofstream&, T1, T2);
430 1.1 christos
431 1.1 christos // Arguments for manipulator function
432 1.1 christos T1 val1;
433 1.1 christos T2 val2;
434 1.1 christos };
435 1.1 christos
436 1.1 christos /*****************************************************************************/
437 1.1 christos
438 1.1 christos // Manipulator function thunks through to stream buffer
439 1.1 christos inline gzofstream&
440 1.1 christos setcompression(gzofstream &gzs, int l, int s = Z_DEFAULT_STRATEGY)
441 1.1 christos {
442 1.1 christos (gzs.rdbuf())->setcompression(l, s);
443 1.1 christos return gzs;
444 1.1 christos }
445 1.1 christos
446 1.1 christos // Manipulator constructor stores arguments
447 1.1 christos template<typename T1, typename T2>
448 1.1 christos inline
449 1.1 christos gzomanip2<T1,T2>::gzomanip2(gzofstream &(*f)(gzofstream &, T1, T2),
450 1.1 christos T1 v1,
451 1.1 christos T2 v2)
452 1.1 christos : func(f), val1(v1), val2(v2)
453 1.1 christos { }
454 1.1 christos
455 1.1.1.3 christos // Inserter applies underlying manipulator function to stream
456 1.1 christos template<typename T1, typename T2>
457 1.1 christos inline gzofstream&
458 1.1 christos operator<<(gzofstream& s, const gzomanip2<T1,T2>& m)
459 1.1 christos { return (*m.func)(s, m.val1, m.val2); }
460 1.1 christos
461 1.1 christos // Insert this onto stream to simplify setting of compression level
462 1.1 christos inline gzomanip2<int,int>
463 1.1 christos setcompression(int l, int s = Z_DEFAULT_STRATEGY)
464 1.1 christos { return gzomanip2<int,int>(&setcompression, l, s); }
465 1.1 christos
466 1.1 christos #endif // ZFSTREAM_H
467