CPP 100
Gzstream.h Guest on 5th June 2020 10:37:30 AM
  1. // ============================================================================
  2. // gzstream, C++ iostream classes wrapping the zlib compression library.
  3. // Copyright (C) 2001  Deepak Bandyopadhyay, Lutz Kettner
  4. //
  5. // This library is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU Lesser General Public
  7. // License as published by the Free Software Foundation; either
  8. // version 2.1 of the License, or (at your option) any later version.
  9. //
  10. // This library is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13. // Lesser General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU Lesser General Public
  16. // License along with this library; if not, write to the Free Software
  17. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18. // ============================================================================
  19. //
  20. // File          : gzstream.h
  21. // Revision      : $Revision: 1.5 $
  22. // Revision_date : $Date: 2002/04/26 23:30:15 $
  23. // Author(s)     : Deepak Bandyopadhyay, Lutz Kettner
  24. //
  25. // Standard streambuf implementation following Nicolai Josuttis, "The
  26. // Standard C++ Library".
  27. // ============================================================================
  28.  
  29. #ifndef GZSTREAM_H
  30. #define GZSTREAM_H 1
  31.  
  32. // standard C++ with new header file names and std:: namespace
  33. #include <iostream>
  34. #include <fstream>
  35. #include <zlib.h>
  36. #include <string>
  37.  
  38. #ifdef GZSTREAM_NAMESPACE
  39. namespace GZSTREAM_NAMESPACE {
  40. #endif
  41.  
  42. // ----------------------------------------------------------------------------
  43. // Internal classes to implement gzstream. See below for user classes.
  44. // ----------------------------------------------------------------------------
  45.  
  46. class gzstreambuf : public std::streambuf {
  47. private:
  48.     static const int bufferSize = 47+256;    // size of data buff
  49.     // totals 512 bytes under g++ for igzstream at the end.
  50.  
  51.     gzFile           file;               // file handle for compressed file
  52.     char             buffer[bufferSize]; // data buffer
  53.     char             opened;             // open/close state of stream
  54.     int              mode;               // I/O mode
  55.  
  56.    
  57.     int flush_buffer() {
  58.         // Separate the writing of the buffer from overflow() and
  59.         // sync() operation.
  60.         int w = pptr() - pbase();
  61.         if ( gzwrite( file, pbase(), w) != w)
  62.             return EOF;
  63.         pbump( -w);
  64.         return w;
  65.     }
  66. public:
  67.     gzstreambuf() : opened(0) {
  68.         setp( buffer, buffer + (bufferSize-1));
  69.         setg( buffer + 4,     // beginning of putback area
  70.               buffer + 4,     // read position
  71.               buffer + 4);    // end position      
  72.         // ASSERT: both input & output capabilities will not be used together
  73.     }
  74.     int is_open() { return opened; }
  75.  
  76.     ~gzstreambuf() { close(); }
  77.     gzstreambuf* open( const char* name, int open_mode) {
  78.         if ( is_open())
  79.             return (gzstreambuf*)0;
  80.         mode = open_mode;
  81.         // no append nor read/write mode
  82.         if ((mode & std::ios::ate) || (mode & std::ios::app)
  83.             || ((mode & std::ios::in) && (mode & std::ios::out)))
  84.             return (gzstreambuf*)0;
  85.         char  fmode[10];
  86.         char* fmodeptr = fmode;
  87.         if ( mode & std::ios::in)
  88.             *fmodeptr++ = 'r';
  89.         else if ( mode & std::ios::out)
  90.             *fmodeptr++ = 'w';
  91.         *fmodeptr++ = 'b';
  92.         *fmodeptr = '\0';
  93.         file = gzopen( name, fmode);
  94.         if (file == 0)
  95.             return (gzstreambuf*)0;
  96.         opened = 1;
  97.         return this;
  98.     }
  99.    
  100.     gzstreambuf * close() {
  101.         if ( is_open()) {
  102.             sync();
  103.             opened = 0;
  104.             if ( gzclose( file) == Z_OK)
  105.                 return this;
  106.         }
  107.         return (gzstreambuf*)0;
  108.     }
  109.    
  110.     virtual int underflow() { // used for input buffer only
  111.         if ( gptr() && ( gptr() < egptr()))
  112.             return * reinterpret_cast<unsigned char *>( gptr());
  113.        
  114.         if ( ! (mode & std::ios::in) || ! opened)
  115.             return EOF;
  116.         // Josuttis' implementation of inbuf
  117.         int n_putback = gptr() - eback();
  118.         if ( n_putback > 4)
  119.             n_putback = 4;
  120.         memcpy( buffer + (4 - n_putback), gptr() - n_putback, n_putback);
  121.        
  122.         int num = gzread( file, buffer+4, bufferSize-4);
  123.         if (num <= 0) // ERROR or EOF
  124.             return EOF;
  125.        
  126.         // reset buffer pointers
  127.         setg( buffer + (4 - n_putback),   // beginning of putback area
  128.              buffer + 4,                 // read position
  129.              buffer + 4 + num);          // end of buffer
  130.        
  131.         // return next character
  132.         return * reinterpret_cast<unsigned char *>( gptr());    
  133.     }
  134.    
  135.     virtual int overflow( int c=EOF) { // used for output buffer only
  136.         if ( ! ( mode & std::ios::out) || ! opened)
  137.             return EOF;
  138.         if (c != EOF) {
  139.             *pptr() = c;
  140.             pbump(1);
  141.         }
  142.         if ( flush_buffer() == EOF)
  143.             return EOF;
  144.         return c;
  145.     }
  146.    
  147.     virtual int sync() {
  148.         // Changed to use flush_buffer() instead of overflow( EOF)
  149.         // which caused improper behavior with std::endl and flush(),
  150.         // bug reported by Vincent Ricard.
  151.         if ( pptr() && pptr() > pbase()) {
  152.             if ( flush_buffer() == EOF)
  153.                 return -1;
  154.         }
  155.         return 0;
  156.     }    
  157. };
  158.  
  159. class gzstreambase : virtual public std::ios {
  160. protected:
  161.     gzstreambuf buf;
  162. public:
  163.    
  164.     gzstreambase() { init(&buf); }
  165.     gzstreambase( const char* name, int mode) {
  166.         init( &buf);
  167.         open( name, mode);
  168.     }
  169.     ~gzstreambase() {
  170.         buf.close();
  171.     }
  172.     void open( const char* name, int open_mode) {
  173.         if ( ! buf.open( name, open_mode))
  174.             clear( rdstate() | std::ios::badbit);
  175.     }
  176.    
  177.     void close() {
  178.         if ( buf.is_open())
  179.             if ( ! buf.close())
  180.                 clear( rdstate() | std::ios::badbit);
  181.     }
  182.     gzstreambuf* rdbuf() { return &buf; }
  183. };
  184.  
  185. // ----------------------------------------------------------------------------
  186. // User classes. Use igzstream and ogzstream analogously to ifstream and
  187. // ofstream respectively. They read and write files based on the gz*
  188. // function interface of the zlib. Files are compatible with gzip compression.
  189. // ----------------------------------------------------------------------------
  190.  
  191. class igzstream : public gzstreambase, public std::istream {
  192. public:
  193.     igzstream() : std::istream( &buf) {}
  194.     igzstream( const char* name, int open_mode = std::ios::in)
  195.         : gzstreambase( name, open_mode), std::istream( &buf) {}  
  196.     gzstreambuf* rdbuf() { return gzstreambase::rdbuf(); }
  197.     void open( const char* name, int open_mode = std::ios::in) {
  198.         gzstreambase::open( name, open_mode);
  199.     }
  200. };
  201.  
  202. class ogzstream : public gzstreambase, public std::ostream {
  203. public:
  204.     ogzstream() : std::ostream( &buf) {}
  205.     ogzstream( const char* name, int mode = std::ios::out)
  206.         : gzstreambase( name, mode), std::ostream( &buf) {}  
  207.     gzstreambuf* rdbuf() { return gzstreambase::rdbuf(); }
  208.     void open( const char* name, int open_mode = std::ios::out) {
  209.         gzstreambase::open( name, open_mode);
  210.     }
  211. };
  212.  
  213. #ifdef GZSTREAM_NAMESPACE
  214. } // namespace GZSTREAM_NAMESPACE
  215. #endif
  216.  
  217. #endif // GZSTREAM_H
  218. // ============================================================================
  219. // EOF //

Paste is for source code and general debugging text.

Login or Register to edit, delete and keep track of your pastes and more.

Raw Paste

Login or Register to edit or fork this paste. It's free.