00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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
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
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)
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
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
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
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
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 }
00472
00473 }
00474
00475 }
00476
00477
00478 #endif // OLENA_IO_GZ_STREAM_HH