(root)/
gcc-13.2.0/
zlib/
contrib/
iostream3/
zfstream.h
       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  */
      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 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
     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  // Insertor 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