gzstream.cpp

Go to the documentation of this file.
00001 // ============================================================================
00002 // gzstream, C++ iostream classes wrapping the zlib compression library.
00003 // Copyright (C) 2001  Deepak Bandyopadhyay, Lutz Kettner
00004 //
00005 // This library is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 //
00010 // This library is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with this library; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 // ============================================================================
00019 //
00020 // File          : gzstream.C
00021 // Revision      : $Revision: 1.1 $
00022 // Revision_date : $Date: 2007/09/05 21:34:54 $
00023 // Author(s)     : Deepak Bandyopadhyay, Lutz Kettner
00024 // 
00025 // Standard streambuf implementation following Nicolai Josuttis, "The 
00026 // Standard C++ Library".
00027 // ============================================================================
00028 
00029 #include <gzstream.h>
00030 #include <iostream>
00031 #include <string.h>  // for memcpy
00032 
00033 #ifdef GZSTREAM_NAMESPACE
00034 namespace GZSTREAM_NAMESPACE {
00035 #endif
00036 
00037 // ----------------------------------------------------------------------------
00038 // Internal classes to implement gzstream. See header file for user classes.
00039 // ----------------------------------------------------------------------------
00040 
00041 // --------------------------------------
00042 // class gzstreambuf:
00043 // --------------------------------------
00044 
00045 gzstreambuf* gzstreambuf::open( const char* name, int open_mode) {
00046     if ( is_open())
00047         return (gzstreambuf*)0;
00048     mode = open_mode;
00049     // no append nor read/write mode
00050     if ((mode & std::ios::ate) || (mode & std::ios::app)
00051         || ((mode & std::ios::in) && (mode & std::ios::out)))
00052         return (gzstreambuf*)0;
00053     char  fmode[10];
00054     char* fmodeptr = fmode;
00055     if ( mode & std::ios::in)
00056         *fmodeptr++ = 'r';
00057     else if ( mode & std::ios::out)
00058         *fmodeptr++ = 'w';
00059     *fmodeptr++ = 'b';
00060     *fmodeptr = '\0';
00061     file = gzopen( name, fmode);
00062     if (file == 0)
00063         return (gzstreambuf*)0;
00064     opened = 1;
00065     return this;
00066 }
00067 
00068 gzstreambuf * gzstreambuf::close() {
00069     if ( is_open()) {
00070         sync();
00071         opened = 0;
00072         if ( gzclose( file) == Z_OK)
00073             return this;
00074     }
00075     return (gzstreambuf*)0;
00076 }
00077 
00078 int gzstreambuf::underflow() { // used for input buffer only
00079     if ( gptr() && ( gptr() < egptr()))
00080         return * reinterpret_cast<unsigned char *>( gptr());
00081 
00082     if ( ! (mode & std::ios::in) || ! opened)
00083         return EOF;
00084     // Josuttis' implementation of inbuf
00085     int n_putback = gptr() - eback();
00086     if ( n_putback > 4)
00087         n_putback = 4;
00088     memcpy( buffer + (4 - n_putback), gptr() - n_putback, n_putback);
00089 
00090     int num = gzread( file, buffer+4, bufferSize-4);
00091     if (num <= 0) // ERROR or EOF
00092         return EOF;
00093 
00094     // reset buffer pointers
00095     setg( buffer + (4 - n_putback),   // beginning of putback area
00096           buffer + 4,                 // read position
00097           buffer + 4 + num);          // end of buffer
00098 
00099     // return next character
00100     return * reinterpret_cast<unsigned char *>( gptr());    
00101 }
00102 
00103 int gzstreambuf::flush_buffer() {
00104     // Separate the writing of the buffer from overflow() and
00105     // sync() operation.
00106     int w = pptr() - pbase();
00107     if ( gzwrite( file, pbase(), w) != w)
00108         return EOF;
00109     pbump( -w);
00110     return w;
00111 }
00112 
00113 int gzstreambuf::overflow( int c) { // used for output buffer only
00114     if ( ! ( mode & std::ios::out) || ! opened)
00115         return EOF;
00116     if (c != EOF) {
00117         *pptr() = c;
00118         pbump(1);
00119     }
00120     if ( flush_buffer() == EOF)
00121         return EOF;
00122     return c;
00123 }
00124 
00125 int gzstreambuf::sync() {
00126     // Changed to use flush_buffer() instead of overflow( EOF)
00127     // which caused improper behavior with std::endl and flush(),
00128     // bug reported by Vincent Ricard.
00129     if ( pptr() && pptr() > pbase()) {
00130         if ( flush_buffer() == EOF)
00131             return -1;
00132     }
00133     return 0;
00134 }
00135 
00136 // --------------------------------------
00137 // class gzstreambase:
00138 // --------------------------------------
00139 
00140 gzstreambase::gzstreambase( const char* name, int mode) {
00141     init( &buf);
00142     open( name, mode);
00143 }
00144 
00145 gzstreambase::~gzstreambase() {
00146     buf.close();
00147 }
00148 
00149 void gzstreambase::open( const char* name, int open_mode) {
00150     if ( ! buf.open( name, open_mode))
00151         clear( rdstate() | std::ios::badbit);
00152 }
00153 
00154 void gzstreambase::close() {
00155     if ( buf.is_open())
00156         if ( ! buf.close())
00157             clear( rdstate() | std::ios::badbit);
00158 }
00159 
00160 #ifdef GZSTREAM_NAMESPACE
00161 } // namespace GZSTREAM_NAMESPACE
00162 #endif
00163 
00164 // ============================================================================
00165 // EOF //