Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

gzstream.h

00001 /* 24 November 2001 James A. Bednar (jbednar@cs.utexas.edu)
00002    Modified to put all functions into the class to avoid having to link with gzstream.C.
00003 */
00004 // ============================================================================
00005 // gzstream, C++ iostream classes wrapping the zlib compression library.
00006 // Copyright (C) 2001  Deepak Bandyopadhyay, Lutz Kettner
00007 //
00008 // This library is free software; you can redistribute it and/or
00009 // modify it under the terms of the GNU Lesser General Public
00010 // License as published by the Free Software Foundation; either
00011 // version 2.1 of the License, or (at your option) any later version.
00012 //
00013 // This library is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016 // Lesser General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU Lesser General Public
00019 // License along with this library; if not, write to the Free Software
00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021 // ============================================================================
00022 //
00023 // File          : gzstream.h
00024 // Revision      : $Revision: 1.1 $
00025 // Revision_date : $Date: 2001/11/25 01:31:47 $
00026 // Author(s)     : Deepak Bandyopadhyay, Lutz Kettner
00027 // 
00028 // Standard streambuf implementation following Nicolai Josuttis, "The 
00029 // Standard C++ Library".
00030 // ============================================================================
00031 
00032 #ifndef GZSTREAM_H
00033 #define GZSTREAM_H 1
00034 
00035 // standard C++ with new header file names and std:: namespace
00036 #include <iostream>
00037 #include <fstream>
00038 #include <zlib.h>
00039 #include <string.h>  // for memcpy
00040 
00041 #ifdef GZSTREAM_NAMESPACE
00042 namespace GZSTREAM_NAMESPACE {
00043 #endif
00044 
00045 // ----------------------------------------------------------------------------
00046 // Internal classes to implement gzstream. See below for user classes.
00047 // ----------------------------------------------------------------------------
00048 
00049 class gzstreambuf : public std::streambuf {
00050 private:
00051     static const int bufferSize = 47+256;    // size of data buff
00052     // totals 512 bytes under g++ for igzstream at the end.
00053 
00054     gzFile           file;               // file handle for compressed file
00055     char             buffer[bufferSize]; // data buffer
00056     char             opened;             // open/close state of stream
00057     int              mode;               // I/O mode
00058 
00059 public:
00060     gzstreambuf() : opened(0) {
00061         setp( buffer, buffer + (bufferSize-1));
00062         setg( buffer + 4,     // beginning of putback area
00063               buffer + 4,     // read position
00064               buffer + 4);    // end position      
00065         // ASSERT: both input & output capabilities will not be used together
00066     }
00067     int is_open() { return opened; }
00068     ~gzstreambuf() { close(); }
00069 
00070     gzstreambuf* open( const char* name, int open_mode) {
00071         if ( is_open())
00072             return (gzstreambuf*)0;
00073         mode = open_mode;
00074         // no append nor read/write mode
00075         if ((mode & std::ios::ate) || (mode & std::ios::app)
00076             || ((mode & std::ios::in) && (mode & std::ios::out)))
00077             return (gzstreambuf*)0;
00078         char  fmode[10];
00079         char* fmodeptr = fmode;
00080         if ( mode & std::ios::in)
00081             *fmodeptr++ = 'r';
00082         else if ( mode & std::ios::out)
00083             *fmodeptr++ = 'w';
00084         *fmodeptr++ = 'b';
00085         *fmodeptr = '\0';
00086         file = gzopen( name, fmode);
00087         if (file == 0)
00088             return (gzstreambuf*)0;
00089         opened = 1;
00090         return this;
00091     }
00092     
00093     gzstreambuf * close() {
00094         if ( is_open()) {
00095             sync();
00096             opened = 0;
00097             if ( gzclose( file) == Z_OK)
00098                 return this;
00099         }
00100         return (gzstreambuf*)0;
00101     }
00102     
00103     int underflow() { // used for input buffer only
00104         if ( gptr() && ( gptr() < egptr()))
00105             return * reinterpret_cast<unsigned char *>( gptr());
00106     
00107         if ( ! (mode & std::ios::in) || ! opened)
00108             return EOF;
00109         // Josuttis' implementation of inbuf
00110         int n_putback = gptr() - eback();
00111         if ( n_putback > 4)
00112             n_putback = 4;
00113         memcpy( buffer + (4 - n_putback), gptr() - n_putback, n_putback);
00114     
00115         int num = gzread( file, buffer+4, bufferSize-4);
00116         if (num <= 0) // ERROR or EOF
00117             return EOF;
00118     
00119         // reset buffer pointers
00120         setg( buffer + (4 - n_putback),   // beginning of putback area
00121               buffer + 4,                 // read position
00122               buffer + 4 + num);          // end of buffer
00123     
00124         // return next character
00125         return * reinterpret_cast<unsigned char *>( gptr());    
00126     }
00127     
00128     int overflow( int c) { // used for output buffer only
00129         if ( ! ( mode & std::ios::out) || ! opened)
00130             return EOF;
00131         int w = pptr() - pbase();
00132         if (c != EOF) {
00133             *pptr() = c;
00134             ++w;
00135         }
00136         if ( gzwrite( file, pbase(), w)) {
00137             setp( pbase(), epptr() - 1);
00138             return c;
00139         } else
00140             return EOF;
00141     }
00142     
00143     int sync() {
00144         if ( pptr() && pptr() > pbase()) {
00145             int c = overflow( EOF);
00146             if ( c == EOF)
00147                 return -1;
00148         }
00149         return 0;
00150     }
00151 };
00152 
00153 class gzstreambase : virtual public std::ios {
00154 protected:
00155     gzstreambuf buf;
00156 public:
00157     gzstreambase() { init(&buf); }
00158 
00159     gzstreambase( const char* name, int mode) {
00160         init( &buf);
00161         open( name, mode);
00162     }
00163     
00164     ~gzstreambase() {
00165         buf.close();
00166     }
00167     
00168     void open( const char* name, int open_mode) {
00169         if ( ! buf.open( name, open_mode))
00170             clear( rdstate() & std::ios::badbit);
00171     }
00172     
00173     void close() {
00174         if ( buf.is_open())
00175             if ( ! buf.close())
00176                 clear( rdstate() & std::ios::badbit);
00177     }
00178 
00179     gzstreambuf* rdbuf() { return &buf; }
00180 };
00181 
00182 // ----------------------------------------------------------------------------
00183 // User classes. Use igzstream and ogzstream analogously to ifstream and
00184 // ofstream respectively. They read and write files based on the gz* 
00185 // function interface of the zlib. Files are compatible with gzip compression.
00186 // ----------------------------------------------------------------------------
00187 
00188 class igzstream : public gzstreambase, public std::istream {
00189 public:
00190     igzstream() : std::istream( &buf) {} 
00191     igzstream( const char* name, int open_mode = std::ios::in)
00192         : gzstreambase( name, open_mode), std::istream( &buf) {}  
00193     gzstreambuf* rdbuf() { return gzstreambase::rdbuf(); }
00194     void open( const char* name, int open_mode = std::ios::in) {
00195         gzstreambase::open( name, open_mode);
00196     }
00197 };
00198 
00199 class ogzstream : public gzstreambase, public std::ostream {
00200 public:
00201     ogzstream() : std::ostream( &buf) {}
00202     ogzstream( const char* name, int mode = std::ios::out)
00203         : gzstreambase( name, mode), std::ostream( &buf) {}  
00204     gzstreambuf* rdbuf() { return gzstreambase::rdbuf(); }
00205     void open( const char* name, int open_mode = std::ios::out) {
00206         gzstreambase::open( name, open_mode);
00207     }
00208 };
00209 
00210 #ifdef GZSTREAM_NAMESPACE
00211 } // namespace GZSTREAM_NAMESPACE
00212 #endif
00213 
00214 #endif // GZSTREAM_H
00215 // ============================================================================
00216 // EOF //
00217 

Generated on Mon Jan 20 02:35:44 2003 for RF-LISSOM by doxygen1.3-rc2