source: Vago/zlib-1.2.8/contrib/iostream3/zfstream.h@ 1089

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