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