Fossil SCM

fossil-scm / compat / zlib / contrib / iostream3 / zfstream.h
Blame History Raw 467 lines
1
/*
2
* A C++ I/O streams interface to the zlib gz* functions
3
*
4
* by Ludwig Schwardt <[email protected]>
5
* original version by Kevin Ruland <[email protected]>
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
*/
27
class gzfilebuf : public std::streambuf
28
{
29
public:
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
86
protected:
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
161
private:
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
*/
234
class gzifstream : public std::istream
235
{
236
public:
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
308
private:
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
*/
323
class gzofstream : public std::ostream
324
{
325
public:
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
397
private:
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
*/
412
template<typename T1, typename T2>
413
class gzomanip2
414
{
415
public:
416
// Allows inserter 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
439
inline gzofstream&
440
setcompression(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
447
template<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
// Inserter applies underlying manipulator function to stream
456
template<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
462
inline gzomanip2<int,int>
463
setcompression(int l, int s = Z_DEFAULT_STRATEGY)
464
{ return gzomanip2<int,int>(&setcompression, l, s); }
465
466
#endif // ZFSTREAM_H
467

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button