00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "zfstream.h"
00011 #include <cstring>
00012 #include <cstdio>
00013
00014
00015 #define BIGBUFSIZE BUFSIZ
00016 #define SMALLBUFSIZE 1
00017
00018
00019
00020
00021 gzfilebuf::gzfilebuf()
00022 : file(NULL), io_mode(std::ios_base::openmode(0)), own_fd(false),
00023 buffer(NULL), buffer_size(BIGBUFSIZE), own_buffer(true)
00024 {
00025
00026 this->disable_buffer();
00027 }
00028
00029
00030 gzfilebuf::~gzfilebuf()
00031 {
00032
00033
00034 this->sync();
00035 if (own_fd)
00036 this->close();
00037
00038 this->disable_buffer();
00039 }
00040
00041
00042 int
00043 gzfilebuf::setcompression(int comp_level,
00044 int comp_strategy)
00045 {
00046 return gzsetparams(file, comp_level, comp_strategy);
00047 }
00048
00049
00050 gzfilebuf*
00051 gzfilebuf::open(const char *name,
00052 std::ios_base::openmode mode)
00053 {
00054
00055 if (this->is_open())
00056 return NULL;
00057
00058 if ((mode & std::ios_base::in) && (mode & std::ios_base::out))
00059 return NULL;
00060
00061
00062 char char_mode[6] = "\0\0\0\0\0";
00063 if (!this->open_mode(mode, char_mode))
00064 return NULL;
00065
00066
00067 if ((file = gzopen(name, char_mode)) == NULL)
00068 return NULL;
00069
00070
00071 this->enable_buffer();
00072 io_mode = mode;
00073 own_fd = true;
00074 return this;
00075 }
00076
00077
00078 gzfilebuf*
00079 gzfilebuf::attach(int fd,
00080 std::ios_base::openmode mode)
00081 {
00082
00083 if (this->is_open())
00084 return NULL;
00085
00086 if ((mode & std::ios_base::in) && (mode & std::ios_base::out))
00087 return NULL;
00088
00089
00090 char char_mode[6] = "\0\0\0\0\0";
00091 if (!this->open_mode(mode, char_mode))
00092 return NULL;
00093
00094
00095 if ((file = gzdopen(fd, char_mode)) == NULL)
00096 return NULL;
00097
00098
00099 this->enable_buffer();
00100 io_mode = mode;
00101 own_fd = false;
00102 return this;
00103 }
00104
00105
00106 gzfilebuf*
00107 gzfilebuf::close()
00108 {
00109
00110 if (!this->is_open())
00111 return NULL;
00112
00113 gzfilebuf* retval = this;
00114
00115 if (this->sync() == -1)
00116 retval = NULL;
00117 if (gzclose(file) < 0)
00118 retval = NULL;
00119
00120 file = NULL;
00121 own_fd = false;
00122
00123 this->disable_buffer();
00124 return retval;
00125 }
00126
00127
00128
00129
00130 bool
00131 gzfilebuf::open_mode(std::ios_base::openmode mode,
00132 char* c_mode) const
00133 {
00134 bool testb = mode & std::ios_base::binary;
00135 bool testi = mode & std::ios_base::in;
00136 bool testo = mode & std::ios_base::out;
00137 bool testt = mode & std::ios_base::trunc;
00138 bool testa = mode & std::ios_base::app;
00139
00140
00141
00142
00143
00144
00145 if (!testi && testo && !testt && !testa)
00146 strcpy(c_mode, "w");
00147 if (!testi && testo && !testt && testa)
00148 strcpy(c_mode, "a");
00149 if (!testi && testo && testt && !testa)
00150 strcpy(c_mode, "w");
00151 if (testi && !testo && !testt && !testa)
00152 strcpy(c_mode, "r");
00153
00154
00155
00156
00157
00158
00159
00160 if (strlen(c_mode) == 0)
00161 return false;
00162 if (testb)
00163 strcat(c_mode, "b");
00164 return true;
00165 }
00166
00167
00168 std::streamsize
00169 gzfilebuf::showmanyc()
00170 {
00171
00172 if (!this->is_open() || !(io_mode & std::ios_base::in))
00173 return -1;
00174
00175 if (this->gptr() && (this->gptr() < this->egptr()))
00176 return std::streamsize(this->egptr() - this->gptr());
00177 else
00178 return 0;
00179 }
00180
00181
00182 gzfilebuf::int_type
00183 gzfilebuf::underflow()
00184 {
00185
00186
00187
00188 if (this->gptr() && (this->gptr() < this->egptr()))
00189 return traits_type::to_int_type(*(this->gptr()));
00190
00191
00192 if (!this->is_open() || !(io_mode & std::ios_base::in))
00193 return traits_type::eof();
00194
00195
00196
00197 int bytes_read = gzread(file, buffer, buffer_size);
00198
00199 if (bytes_read <= 0)
00200 {
00201
00202 this->setg(buffer, buffer, buffer);
00203 return traits_type::eof();
00204 }
00205
00206 this->setg(buffer, buffer, buffer + bytes_read);
00207
00208
00209 return traits_type::to_int_type(*(this->gptr()));
00210 }
00211
00212
00213 gzfilebuf::int_type
00214 gzfilebuf::overflow(int_type c)
00215 {
00216
00217 if (this->pbase())
00218 {
00219
00220 if (this->pptr() > this->epptr() || this->pptr() < this->pbase())
00221 return traits_type::eof();
00222
00223 if (!traits_type::eq_int_type(c, traits_type::eof()))
00224 {
00225 *(this->pptr()) = traits_type::to_char_type(c);
00226 this->pbump(1);
00227 }
00228
00229 int bytes_to_write = this->pptr() - this->pbase();
00230
00231 if (bytes_to_write > 0)
00232 {
00233
00234 if (!this->is_open() || !(io_mode & std::ios_base::out))
00235 return traits_type::eof();
00236
00237 if (gzwrite(file, this->pbase(), bytes_to_write) != bytes_to_write)
00238 return traits_type::eof();
00239
00240 this->pbump(-bytes_to_write);
00241 }
00242 }
00243
00244 else if (!traits_type::eq_int_type(c, traits_type::eof()))
00245 {
00246
00247 if (!this->is_open() || !(io_mode & std::ios_base::out))
00248 return traits_type::eof();
00249
00250 char_type last_char = traits_type::to_char_type(c);
00251
00252 if (gzwrite(file, &last_char, 1) != 1)
00253 return traits_type::eof();
00254 }
00255
00256
00257
00258 if (traits_type::eq_int_type(c, traits_type::eof()))
00259 return traits_type::not_eof(c);
00260 else
00261 return c;
00262 }
00263
00264
00265 std::streambuf*
00266 gzfilebuf::setbuf(char_type* p,
00267 std::streamsize n)
00268 {
00269
00270 if (this->sync() == -1)
00271 return NULL;
00272
00273
00274
00275
00276 if (!p || !n)
00277 {
00278
00279 this->disable_buffer();
00280 buffer = NULL;
00281 buffer_size = 0;
00282 own_buffer = true;
00283 this->enable_buffer();
00284 }
00285 else
00286 {
00287
00288 this->disable_buffer();
00289 buffer = p;
00290 buffer_size = n;
00291 own_buffer = false;
00292 this->enable_buffer();
00293 }
00294 return this;
00295 }
00296
00297
00298 int
00299 gzfilebuf::sync()
00300 {
00301 return traits_type::eq_int_type(this->overflow(), traits_type::eof()) ? -1 : 0;
00302 }
00303
00304
00305
00306
00307 void
00308 gzfilebuf::enable_buffer()
00309 {
00310
00311 if (own_buffer && !buffer)
00312 {
00313
00314 if (buffer_size > 0)
00315 {
00316
00317 buffer = new char_type[buffer_size];
00318
00319 this->setg(buffer, buffer, buffer);
00320
00321
00322
00323
00324 this->setp(buffer, buffer + buffer_size - 1);
00325 }
00326 else
00327 {
00328
00329 buffer_size = SMALLBUFSIZE;
00330 buffer = new char_type[buffer_size];
00331 this->setg(buffer, buffer, buffer);
00332
00333 this->setp(0, 0);
00334 }
00335 }
00336 else
00337 {
00338
00339
00340 this->setg(buffer, buffer, buffer);
00341 this->setp(buffer, buffer + buffer_size - 1);
00342 }
00343 }
00344
00345
00346 void
00347 gzfilebuf::disable_buffer()
00348 {
00349
00350 if (own_buffer && buffer)
00351 {
00352
00353 if (!this->pbase())
00354 buffer_size = 0;
00355 delete[] buffer;
00356 buffer = NULL;
00357 this->setg(0, 0, 0);
00358 this->setp(0, 0);
00359 }
00360 else
00361 {
00362
00363 this->setg(buffer, buffer, buffer);
00364 if (buffer)
00365 this->setp(buffer, buffer + buffer_size - 1);
00366 else
00367 this->setp(0, 0);
00368 }
00369 }
00370
00371
00372
00373
00374 gzifstream::gzifstream()
00375 : std::istream(NULL), sb()
00376 { this->init(&sb); }
00377
00378
00379 gzifstream::gzifstream(const char* name,
00380 std::ios_base::openmode mode)
00381 : std::istream(NULL), sb()
00382 {
00383 this->init(&sb);
00384 this->open(name, mode);
00385 }
00386
00387
00388 gzifstream::gzifstream(int fd,
00389 std::ios_base::openmode mode)
00390 : std::istream(NULL), sb()
00391 {
00392 this->init(&sb);
00393 this->attach(fd, mode);
00394 }
00395
00396
00397 void
00398 gzifstream::open(const char* name,
00399 std::ios_base::openmode mode)
00400 {
00401 if (!sb.open(name, mode | std::ios_base::in))
00402 this->setstate(std::ios_base::failbit);
00403 else
00404 this->clear();
00405 }
00406
00407
00408 void
00409 gzifstream::attach(int fd,
00410 std::ios_base::openmode mode)
00411 {
00412 if (!sb.attach(fd, mode | std::ios_base::in))
00413 this->setstate(std::ios_base::failbit);
00414 else
00415 this->clear();
00416 }
00417
00418
00419 void
00420 gzifstream::close()
00421 {
00422 if (!sb.close())
00423 this->setstate(std::ios_base::failbit);
00424 }
00425
00426
00427
00428
00429 gzofstream::gzofstream()
00430 : std::ostream(NULL), sb()
00431 { this->init(&sb); }
00432
00433
00434 gzofstream::gzofstream(const char* name,
00435 std::ios_base::openmode mode)
00436 : std::ostream(NULL), sb()
00437 {
00438 this->init(&sb);
00439 this->open(name, mode);
00440 }
00441
00442
00443 gzofstream::gzofstream(int fd,
00444 std::ios_base::openmode mode)
00445 : std::ostream(NULL), sb()
00446 {
00447 this->init(&sb);
00448 this->attach(fd, mode);
00449 }
00450
00451
00452 void
00453 gzofstream::open(const char* name,
00454 std::ios_base::openmode mode)
00455 {
00456 if (!sb.open(name, mode | std::ios_base::out))
00457 this->setstate(std::ios_base::failbit);
00458 else
00459 this->clear();
00460 }
00461
00462
00463 void
00464 gzofstream::attach(int fd,
00465 std::ios_base::openmode mode)
00466 {
00467 if (!sb.attach(fd, mode | std::ios_base::out))
00468 this->setstate(std::ios_base::failbit);
00469 else
00470 this->clear();
00471 }
00472
00473
00474 void
00475 gzofstream::close()
00476 {
00477 if (!sb.close())
00478 this->setstate(std::ios_base::failbit);
00479 }