Home | History | Annotate | Line # | Download | only in iostream3
zfstream.h revision 1.1.1.2.14.2
      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  christos     // Allows insertor 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  christos // Insertor 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