gzstream.cpp

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

Generated on Mon Feb 6 14:01:21 2006 for SCT DAQ/DCS Software - C++ by  doxygen 1.4.6