gz_stream.hh

00001 // Copyright (C) 2001, 2002, 2003, 2004  EPITA Research and Development Laboratory
00002 //
00003 // This file is part of the Olena Library.  This library is free
00004 // software; you can redistribute it and/or modify it under the terms
00005 // of the GNU General Public License version 2 as published by the
00006 // Free Software Foundation.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU General Public License
00014 // along with this library; see the file COPYING.  If not, write to
00015 // the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
00016 // MA 02111-1307, USA.
00017 //
00018 // As a special exception, you may use this file as part of a free
00019 // software library without restriction.  Specifically, if other files
00020 // instantiate templates or use macros or inline functions from this
00021 // file, or you compile this file and link it with other files to
00022 // produce an executable, this file does not by itself cause the
00023 // resulting executable to be covered by the GNU General Public
00024 // License.  This exception does not however invalidate any other
00025 // reasons why the executable file might be covered by the GNU General
00026 // Public License.
00027 
00028 #ifndef OLENA_IO_GZ_STREAM_HH
00029 # define OLENA_IO_GZ_STREAM_HH
00030 
00031 # include <oln/config/system.hh>
00032 
00033 # include <cassert>
00034 # include <fstream>
00035 # include <string>
00036 # include <zlib.h>
00037 
00038 namespace oln {
00039 
00040   namespace io {
00041 
00043     namespace gz {
00044 
00045 
00047       class zfilebuf : public std::streambuf
00048       {
00049       public:
00050 
00051 
00052         zfilebuf() : file(0),  mode(0),  own_file_descriptor(0)
00053         {
00054           inbuf = new char[lenbuf];
00055           outbuf = new char[lenbuf];
00056           setg(0, 0, 0);
00057           setp(outbuf, outbuf + lenbuf);
00058         }
00059 
00060         virtual ~zfilebuf()
00061         {
00062           sync();
00063           delete[] inbuf;
00064           delete[] outbuf;
00065           if (own_file_descriptor)
00066             close();
00067         }
00068 
00069 
00073         zfilebuf*
00074         open(const char *name, int io_mode)
00075         {
00076           if (is_open())
00077             return 0;
00078 
00079           char char_mode[10];
00080           char *p;
00081           memset(char_mode,'\0',10);
00082           p = char_mode;
00083 
00084           if (io_mode & std::ios::in)
00085             {
00086               mode = std::ios::in;
00087               *p++ = 'r';
00088             }
00089           else
00090             if (io_mode & std::ios::app)
00091               {
00092                 mode = std::ios::app;
00093                 *p++ = 'a';
00094               }
00095             else
00096               {
00097                 mode = std::ios::out;
00098                 *p++ = 'w';
00099               }
00100           if (io_mode & std::ios::binary)
00101             {
00102               mode |= std::ios::binary;
00103               *p++ = 'b';
00104             }
00105 
00106           // Hard code the compression level
00107           if (io_mode & (std::ios::out|std::ios::app))
00108             *p++ = '9';
00109 
00110           if ((file = gzopen(name, char_mode)) == 0)
00111             return 0;
00112 
00113           name_ = name;
00114           own_file_descriptor = 1;
00115           return this;
00116         }
00117 
00121         zfilebuf*
00122         attach(int file_descriptor, int io_mode)
00123         {
00124           if (is_open())
00125             return 0;
00126 
00127           char char_mode[10];
00128           char *p;
00129           memset(char_mode,'\0',10);
00130           p = char_mode;
00131 
00132           if (io_mode & std::ios::in)
00133             {
00134               mode = std::ios::in;
00135               *p++ = 'r';
00136             }
00137           else
00138             if (io_mode & std::ios::app)
00139               {
00140                 mode = std::ios::app;
00141                 *p++ = 'a';
00142               }
00143             else
00144               {
00145                 mode = std::ios::out;
00146                 *p++ = 'w';
00147               }
00148 
00149           if (io_mode & std::ios::binary)
00150             {
00151               mode |= std::ios::binary;
00152               *p++ = 'b';
00153             }
00154 
00155           // Hard code the compression level
00156           if (io_mode & (std::ios::out|std::ios::app))
00157             *p++ = '9';
00158 
00159           if ((file = gzdopen(file_descriptor, char_mode)) == 0)
00160             return 0;
00161 
00162           own_file_descriptor = 0;
00163           return this;
00164         }
00165 
00167         zfilebuf*
00168         close()
00169         {
00170           if (is_open())
00171             {
00172               sync();
00173               gzclose(file);
00174               file = 0;
00175             }
00176           return this;
00177         }
00178 
00179 
00180         int
00181         setcompressionlevel(short comp_level)
00182         {
00183           return gzsetparams(file, comp_level, -2);
00184         }
00185 
00186         int
00187         setcompressionstrategy(short comp_strategy)
00188         {
00189           return gzsetparams(file, -2, comp_strategy);
00190         }
00191 
00193         inline int
00194         is_open() const
00195         { return (file != 0); }
00196 
00197         virtual std::streampos
00198         seekoff(std::streamoff off, std::ios::seekdir dir, int) // which)
00199         {
00200           return std::streampos(gzseek(file, off, dir));
00201         }
00202 
00204         virtual int
00205         sync()
00206         {
00207           if (!is_open())
00208             return EOF;
00209           return flushbuf();
00210         }
00211 
00212       protected:
00213 
00217         virtual int
00218         underflow()
00219         {
00220           // If the file hasn't been opened for reading, error.
00221           if (!is_open() || !(mode & std::ios::in))
00222             return EOF;
00223 
00224           if (in_avail())
00225             return (unsigned char) *gptr();
00226 
00227           if (flushbuf() == EOF)
00228             return EOF;
00229 
00230           // Attempt to fill the buffer.
00231           if (fillbuf() == EOF)
00232             return EOF;
00233 
00234           assert (eback());
00235 
00236           return (unsigned char) *gptr();
00237         }
00238 
00243         virtual int
00244         overflow(int c = EOF)
00245         {
00246           if (!is_open() || !(mode & std::ios::out))
00247             return EOF;
00248 
00249           assert (pbase());
00250 
00251           if (flushbuf() == EOF)
00252             return EOF;
00253 
00254           if (c != EOF)
00255             {
00256               *pptr() = c;
00257               pbump(1);
00258             }
00259           return 0;
00260         }
00261 
00262       private:
00263 
00264         gzFile file;
00265         short mode;
00266         short own_file_descriptor;
00267         std::string name_;
00268         char *inbuf;
00269         char *outbuf;
00270         static const int lenbuf = 16 * 1024;
00271 
00273         int
00274         flushbuf()
00275         {
00276           int n = pptr() - outbuf;
00277 
00278           if (n == 0)
00279             return 0;
00280 
00281           if (gzwrite(file, outbuf, n) < n)
00282             return EOF;
00283 
00284           setp(outbuf, outbuf + lenbuf);
00285           return 0;
00286         }
00288         int
00289         fillbuf()
00290         {
00291           int t = gzread(file, inbuf, lenbuf);
00292           if (t <= 0) return EOF;
00293           setg(inbuf, inbuf, inbuf + t);
00294           return t;
00295         }
00296 
00297       };
00298 
00300       class zfilestream_common : virtual public std::ios
00301       {
00302         friend class zifstream;
00303         friend class zofstream;
00304         friend zofstream &setcompressionlevel(zofstream &, int);
00305         friend zofstream &setcompressionstrategy(zofstream &, int);
00306 
00307       public:
00308         virtual ~zfilestream_common() {}
00309 
00313         void
00314         attach(int fd, int io_mode)
00315         {
00316           if (!buffer.attach(fd, io_mode))
00317             clear(std::ios::failbit | std::ios::badbit);
00318           else
00319             clear();
00320         }
00321 
00325         void
00326         open(const char *name, int io_mode)
00327         {
00328           if (!buffer.open(name, io_mode))
00329             clear(std::ios::failbit | std::ios::badbit);
00330           else
00331             clear();
00332         }
00333 
00335         void
00336         close()
00337         {
00338           if (!buffer.close())
00339             clear(std::ios::failbit | std::ios::badbit);
00340         }
00341 
00342       protected:
00344         zfilestream_common() :  std::ios(zfilestream_common::rdbuf())
00345         { }
00346 
00347 
00348       private:
00349         zfilebuf*
00350         rdbuf()
00351         {
00352           return &buffer;
00353         }
00354 
00355         zfilebuf buffer;
00356       };
00357 
00358 
00360       class zifstream : public zfilestream_common, public std::istream
00361       {
00362       public:
00363 
00364         zifstream() : std::istream(zfilestream_common::rdbuf())
00365         {
00366           clear(std::ios::badbit);
00367         }
00368 
00370         zifstream(const char *name, int io_mode = std::ios::in) :
00371           std::istream(zfilestream_common::rdbuf())
00372         {
00373           zfilestream_common::open(name, io_mode);
00374         }
00375 
00377         zifstream(int fd, int io_mode = std::ios::in) :
00378           std::istream(zfilestream_common::rdbuf())
00379         {
00380           zfilestream_common::attach(fd, io_mode);
00381         }
00382 
00383         virtual ~zifstream() {}
00384       };
00385 
00386       class zofstream : public zfilestream_common, public std::ostream {
00387 
00388       public:
00389 
00390         zofstream() : std::ostream(zfilestream_common::rdbuf())
00391         {
00392           clear(std::ios::badbit);
00393         }
00394 
00396         zofstream(const char *name, int io_mode = std::ios::out) :
00397           std::ostream(zfilestream_common::rdbuf())
00398         {
00399           zfilestream_common::open(name, io_mode);
00400         }
00401 
00403         zofstream(int fd, int io_mode = std::ios::out) :
00404           std::ostream(zfilestream_common::rdbuf())
00405         {
00406           zfilestream_common::attach(fd, io_mode);
00407         }
00408 
00409         virtual ~zofstream() {}
00410 
00411       };
00412 
00413       // Forward declaration.
00414       template <class T>
00415       class zomanip;
00416 
00418       template <class T>
00419       zofstream&
00420       operator<<(zofstream &s, const zomanip<T> &m) {
00421         return (*m.func)(s, m.val);
00422       }
00423 
00424 
00426       template<class T> class zomanip
00427       {
00428         friend zofstream &operator<< <T>(zofstream &, const zomanip<T> &);
00429       public:
00430         zomanip(zofstream &(*f)(zofstream &, T), T v) : func(f), val(v) { }
00431       private:
00432         zofstream &(*func)(zofstream &, T);
00433         T val;
00434       };
00435 
00436 
00438       inline zofstream&
00439       setcompressionlevel(zofstream &s, int l) {
00440         (s.rdbuf())->setcompressionlevel(l);
00441         return s;
00442       }
00443 
00445       inline zofstream&
00446       setcompressionstrategy(zofstream &s, int l)
00447       {
00448         (s.rdbuf())->setcompressionstrategy(l);
00449         return s;
00450       }
00451 
00453       inline zomanip<int>
00454       setcompressionlevel(int l)
00455       {
00456         return zomanip<int>(&setcompressionlevel,l);
00457       }
00458 
00460       inline zomanip<int>
00461       setcompressionstrategy(int l)
00462       {
00463         return zomanip<int>(&setcompressionstrategy,l);
00464       }
00465 
00466     } // end of namespace gz
00467 
00468   } // end of namespace io
00469 
00470 } // end of namespace oln
00471 
00472 
00473 #endif // OLENA_IO_GZ_STREAM_HH

Generated on Thu Apr 15 20:13:10 2004 for Olena by doxygen 1.3.6-20040222