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 #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
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
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)
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
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
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
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 }
00467
00468 }
00469
00470 }
00471
00472
00473 #endif // OLENA_IO_GZ_STREAM_HH