zfstream.h
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:12k
源码类别:

通讯编程

开发平台:

Visual C++

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