annotate src/zlib-1.2.8/contrib/iostream3/zfstream.h @ 128:5b4145a0d408

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