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/gzstream.h"
00030 
00031 #include <iostream>
00032 #include <string.h>  // for memcpy
00033 
00034 #ifdef GZSTREAM_NAMESPACE
00035 namespace GZSTREAM_NAMESPACE {
00036 #endif
00037 
00038 // ----------------------------------------------------------------------------
00039 // Internal classes to implement gzstream. See header file for user classes.
00040 // ----------------------------------------------------------------------------
00041 
00042 // --------------------------------------
00043 // class gzstreambuf:
00044 // --------------------------------------
00045 
00046 gzstreambuf* gzstreambuf::open( const char* name, int open_mode) {
00047     if ( is_open())
00048         return (gzstreambuf*)0;
00049     mode = open_mode;
00050     // no append nor read/write mode
00051     if ((mode & std::ios::ate) || (mode & std::ios::app)
00052         || ((mode & std::ios::in) && (mode & std::ios::out)))
00053         return (gzstreambuf*)0;
00054     char  fmode[10];
00055     char* fmodeptr = fmode;
00056     if ( mode & std::ios::in)
00057         *fmodeptr++ = 'r';
00058     else if ( mode & std::ios::out)
00059         *fmodeptr++ = 'w';
00060     *fmodeptr++ = 'b';
00061     *fmodeptr = '\0';
00062     file = gzopen( name, fmode);
00063     if (file == 0)
00064         return (gzstreambuf*)0;
00065     opened = 1;
00066     return this;
00067 }
00068 
00069 gzstreambuf * gzstreambuf::close() {
00070     if ( is_open()) {
00071         sync();
00072         opened = 0;
00073         if ( gzclose( file) == Z_OK)
00074             return this;
00075     }
00076     return (gzstreambuf*)0;
00077 }
00078 
00079 int gzstreambuf::underflow() { // used for input buffer only
00080     if ( gptr() && ( gptr() < egptr()))
00081         return * reinterpret_cast<unsigned char *>( gptr());
00082 
00083     if ( ! (mode & std::ios::in) || ! opened)
00084         return EOF;
00085     // Josuttis' implementation of inbuf
00086     int n_putback = gptr() - eback();
00087     if ( n_putback > 4)
00088         n_putback = 4;
00089     memcpy( buffer + (4 - n_putback), gptr() - n_putback, n_putback);
00090 
00091     int num = gzread( file, buffer+4, bufferSize-4);
00092     if (num <= 0) // ERROR or EOF
00093         return EOF;
00094 
00095     // reset buffer pointers
00096     setg( buffer + (4 - n_putback),   // beginning of putback area
00097           buffer + 4,                 // read position
00098           buffer + 4 + num);          // end of buffer
00099 
00100     // return next character
00101     return * reinterpret_cast<unsigned char *>( gptr());    
00102 }
00103 
00104 int gzstreambuf::flush_buffer() {
00105     // Separate the writing of the buffer from overflow() and
00106     // sync() operation.
00107     int w = pptr() - pbase();
00108     if ( gzwrite( file, pbase(), w) != w)
00109         return EOF;
00110     pbump( -w);
00111     return w;
00112 }
00113 
00114 int gzstreambuf::overflow( int c) { // used for output buffer only
00115     if ( ! ( mode & std::ios::out) || ! opened)
00116         return EOF;
00117     if (c != EOF) {
00118         *pptr() = c;
00119         pbump(1);
00120     }
00121     if ( flush_buffer() == EOF)
00122         return EOF;
00123     return c;
00124 }
00125 
00126 int gzstreambuf::sync() {
00127     // Changed to use flush_buffer() instead of overflow( EOF)
00128     // which caused improper behavior with std::endl and flush(),
00129     // bug reported by Vincent Ricard.
00130     if ( pptr() && pptr() > pbase()) {
00131         if ( flush_buffer() == EOF)
00132             return -1;
00133     }
00134     return 0;
00135 }
00136 
00137 // --------------------------------------
00138 // class gzstreambase:
00139 // --------------------------------------
00140 
00141 gzstreambase::gzstreambase( const char* name, int mode) {
00142     init( &buf);
00143     open( name, mode);
00144 }
00145 
00146 gzstreambase::~gzstreambase() {
00147     buf.close();
00148 }
00149 
00150 void gzstreambase::open( const char* name, int open_mode) {
00151     if ( ! buf.open( name, open_mode))
00152         clear( rdstate() | std::ios::badbit);
00153 }
00154 
00155 void gzstreambase::close() {
00156     if ( buf.is_open())
00157         if ( ! buf.close())
00158             clear( rdstate() | std::ios::badbit);
00159 }
00160 
00161 #ifdef GZSTREAM_NAMESPACE
00162 } // namespace GZSTREAM_NAMESPACE
00163 #endif
00164 
00165 // ============================================================================
00166 // EOF //