gz_stream.hh

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

Generated on Tue Feb 20 20:19:50 2007 for Olena by  doxygen 1.5.1