| 1 | /* | 
 
 
 
 
 | 2 | * A C++ I/O streams interface to the zlib gz* functions | 
 
 
 
 
 | 3 | * | 
 
 
 
 
 | 4 | * by Ludwig Schwardt <schwardt@sun.ac.za> | 
 
 
 
 
 | 5 | * original version by Kevin Ruland <kevin@rodin.wustl.edu> | 
 
 
 
 
 | 6 | * | 
 
 
 
 
 | 7 | * This version is standard-compliant and compatible with gcc 3.x. | 
 
 
 
 
 | 8 | */ | 
 
 
 
 
 | 9 |  | 
 
 
 
 
 | 10 | #include "zfstream.h" | 
 
 
 
 
 | 11 | #include <cstring>          // for strcpy, strcat, strlen (mode strings) | 
 
 
 
 
 | 12 | #include <cstdio>           // for BUFSIZ | 
 
 
 
 
 | 13 |  | 
 
 
 
 
 | 14 | // Internal buffer sizes (default and "unbuffered" versions) | 
 
 
 
 
 | 15 | #define BIGBUFSIZE BUFSIZ | 
 
 
 
 
 | 16 | #define SMALLBUFSIZE 1 | 
 
 
 
 
 | 17 |  | 
 
 
 
 
 | 18 | /*****************************************************************************/ | 
 
 
 
 
 | 19 |  | 
 
 
 
 
 | 20 | // Default constructor | 
 
 
 
 
 | 21 | gzfilebuf::gzfilebuf() | 
 
 
 
 
 | 22 | : file(NULL), io_mode(std::ios_base::openmode(0)), own_fd(false), | 
 
 
 
 
 | 23 | buffer(NULL), buffer_size(BIGBUFSIZE), own_buffer(true) | 
 
 
 
 
 | 24 | { | 
 
 
 
 
 | 25 | // No buffers to start with | 
 
 
 
 
 | 26 | this->disable_buffer(); | 
 
 
 
 
 | 27 | } | 
 
 
 
 
 | 28 |  | 
 
 
 
 
 | 29 | // Destructor | 
 
 
 
 
 | 30 | gzfilebuf::~gzfilebuf() | 
 
 
 
 
 | 31 | { | 
 
 
 
 
 | 32 | // Sync output buffer and close only if responsible for file | 
 
 
 
 
 | 33 | // (i.e. attached streams should be left open at this stage) | 
 
 
 
 
 | 34 | this->sync(); | 
 
 
 
 
 | 35 | if (own_fd) | 
 
 
 
 
 | 36 | this->close(); | 
 
 
 
 
 | 37 | // Make sure internal buffer is deallocated | 
 
 
 
 
 | 38 | this->disable_buffer(); | 
 
 
 
 
 | 39 | } | 
 
 
 
 
 | 40 |  | 
 
 
 
 
 | 41 | // Set compression level and strategy | 
 
 
 
 
 | 42 | int | 
 
 
 
 
 | 43 | gzfilebuf::setcompression(int comp_level, | 
 
 
 
 
 | 44 | int comp_strategy) | 
 
 
 
 
 | 45 | { | 
 
 
 
 
 | 46 | return gzsetparams(file, comp_level, comp_strategy); | 
 
 
 
 
 | 47 | } | 
 
 
 
 
 | 48 |  | 
 
 
 
 
 | 49 | // Open gzipped file | 
 
 
 
 
 | 50 | gzfilebuf* | 
 
 
 
 
 | 51 | gzfilebuf::open(const char *name, | 
 
 
 
 
 | 52 | std::ios_base::openmode mode) | 
 
 
 
 
 | 53 | { | 
 
 
 
 
 | 54 | // Fail if file already open | 
 
 
 
 
 | 55 | if (this->is_open()) | 
 
 
 
 
 | 56 | return NULL; | 
 
 
 
 
 | 57 | // Don't support simultaneous read/write access (yet) | 
 
 
 
 
 | 58 | if ((mode & std::ios_base::in) && (mode & std::ios_base::out)) | 
 
 
 
 
 | 59 | return NULL; | 
 
 
 
 
 | 60 |  | 
 
 
 
 
 | 61 | // Build mode string for gzopen and check it [27.8.1.3.2] | 
 
 
 
 
 | 62 | char char_mode[6] = "\0\0\0\0\0"; | 
 
 
 
 
 | 63 | if (!this->open_mode(mode, char_mode)) | 
 
 
 
 
 | 64 | return NULL; | 
 
 
 
 
 | 65 |  | 
 
 
 
 
 | 66 | // Attempt to open file | 
 
 
 
 
 | 67 | if ((file = gzopen(name, char_mode)) == NULL) | 
 
 
 
 
 | 68 | return NULL; | 
 
 
 
 
 | 69 |  | 
 
 
 
 
 | 70 | // On success, allocate internal buffer and set flags | 
 
 
 
 
 | 71 | this->enable_buffer(); | 
 
 
 
 
 | 72 | io_mode = mode; | 
 
 
 
 
 | 73 | own_fd = true; | 
 
 
 
 
 | 74 | return this; | 
 
 
 
 
 | 75 | } | 
 
 
 
 
 | 76 |  | 
 
 
 
 
 | 77 | // Attach to gzipped file | 
 
 
 
 
 | 78 | gzfilebuf* | 
 
 
 
 
 | 79 | gzfilebuf::attach(int fd, | 
 
 
 
 
 | 80 | std::ios_base::openmode mode) | 
 
 
 
 
 | 81 | { | 
 
 
 
 
 | 82 | // Fail if file already open | 
 
 
 
 
 | 83 | if (this->is_open()) | 
 
 
 
 
 | 84 | return NULL; | 
 
 
 
 
 | 85 | // Don't support simultaneous read/write access (yet) | 
 
 
 
 
 | 86 | if ((mode & std::ios_base::in) && (mode & std::ios_base::out)) | 
 
 
 
 
 | 87 | return NULL; | 
 
 
 
 
 | 88 |  | 
 
 
 
 
 | 89 | // Build mode string for gzdopen and check it [27.8.1.3.2] | 
 
 
 
 
 | 90 | char char_mode[6] = "\0\0\0\0\0"; | 
 
 
 
 
 | 91 | if (!this->open_mode(mode, char_mode)) | 
 
 
 
 
 | 92 | return NULL; | 
 
 
 
 
 | 93 |  | 
 
 
 
 
 | 94 | // Attempt to attach to file | 
 
 
 
 
 | 95 | if ((file = gzdopen(fd, char_mode)) == NULL) | 
 
 
 
 
 | 96 | return NULL; | 
 
 
 
 
 | 97 |  | 
 
 
 
 
 | 98 | // On success, allocate internal buffer and set flags | 
 
 
 
 
 | 99 | this->enable_buffer(); | 
 
 
 
 
 | 100 | io_mode = mode; | 
 
 
 
 
 | 101 | own_fd = false; | 
 
 
 
 
 | 102 | return this; | 
 
 
 
 
 | 103 | } | 
 
 
 
 
 | 104 |  | 
 
 
 
 
 | 105 | // Close gzipped file | 
 
 
 
 
 | 106 | gzfilebuf* | 
 
 
 
 
 | 107 | gzfilebuf::close() | 
 
 
 
 
 | 108 | { | 
 
 
 
 
 | 109 | // Fail immediately if no file is open | 
 
 
 
 
 | 110 | if (!this->is_open()) | 
 
 
 
 
 | 111 | return NULL; | 
 
 
 
 
 | 112 | // Assume success | 
 
 
 
 
 | 113 | gzfilebuf* retval = this; | 
 
 
 
 
 | 114 | // Attempt to sync and close gzipped file | 
 
 
 
 
 | 115 | if (this->sync() == -1) | 
 
 
 
 
 | 116 | retval = NULL; | 
 
 
 
 
 | 117 | if (gzclose(file) < 0) | 
 
 
 
 
 | 118 | retval = NULL; | 
 
 
 
 
 | 119 | // File is now gone anyway (postcondition [27.8.1.3.8]) | 
 
 
 
 
 | 120 | file = NULL; | 
 
 
 
 
 | 121 | own_fd = false; | 
 
 
 
 
 | 122 | // Destroy internal buffer if it exists | 
 
 
 
 
 | 123 | this->disable_buffer(); | 
 
 
 
 
 | 124 | return retval; | 
 
 
 
 
 | 125 | } | 
 
 
 
 
 | 126 |  | 
 
 
 
 
 | 127 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | 
 
 
 
 
 | 128 |  | 
 
 
 
 
 | 129 | // Convert int open mode to mode string | 
 
 
 
 
 | 130 | bool | 
 
 
 
 
 | 131 | gzfilebuf::open_mode(std::ios_base::openmode mode, | 
 
 
 
 
 | 132 | char* c_mode) const | 
 
 
 
 
 | 133 | { | 
 
 
 
 
 | 134 | bool testb = mode & std::ios_base::binary; | 
 
 
 
 
 | 135 | bool testi = mode & std::ios_base::in; | 
 
 
 
 
 | 136 | bool testo = mode & std::ios_base::out; | 
 
 
 
 
 | 137 | bool testt = mode & std::ios_base::trunc; | 
 
 
 
 
 | 138 | bool testa = mode & std::ios_base::app; | 
 
 
 
 
 | 139 |  | 
 
 
 
 
 | 140 | // Check for valid flag combinations - see [27.8.1.3.2] (Table 92) | 
 
 
 
 
 | 141 | // Original zfstream hardcoded the compression level to maximum here... | 
 
 
 
 
 | 142 | // Double the time for less than 1% size improvement seems | 
 
 
 
 
 | 143 | // excessive though - keeping it at the default level | 
 
 
 
 
 | 144 | // To change back, just append "9" to the next three mode strings | 
 
 
 
 
 | 145 | if (!testi && testo && !testt && !testa) | 
 
 
 
 
 | 146 | strcpy(c_mode, "w"); | 
 
 
 
 
 | 147 | if (!testi && testo && !testt && testa) | 
 
 
 
 
 | 148 | strcpy(c_mode, "a"); | 
 
 
 
 
 | 149 | if (!testi && testo && testt && !testa) | 
 
 
 
 
 | 150 | strcpy(c_mode, "w"); | 
 
 
 
 
 | 151 | if (testi && !testo && !testt && !testa) | 
 
 
 
 
 | 152 | strcpy(c_mode, "r"); | 
 
 
 
 
 | 153 | // No read/write mode yet | 
 
 
 
 
 | 154 | //  if (testi && testo && !testt && !testa) | 
 
 
 
 
 | 155 | //    strcpy(c_mode, "r+"); | 
 
 
 
 
 | 156 | //  if (testi && testo && testt && !testa) | 
 
 
 
 
 | 157 | //    strcpy(c_mode, "w+"); | 
 
 
 
 
 | 158 |  | 
 
 
 
 
 | 159 | // Mode string should be empty for invalid combination of flags | 
 
 
 
 
 | 160 | if (strlen(c_mode) == 0) | 
 
 
 
 
 | 161 | return false; | 
 
 
 
 
 | 162 | if (testb) | 
 
 
 
 
 | 163 | strcat(c_mode, "b"); | 
 
 
 
 
 | 164 | return true; | 
 
 
 
 
 | 165 | } | 
 
 
 
 
 | 166 |  | 
 
 
 
 
 | 167 | // Determine number of characters in internal get buffer | 
 
 
 
 
 | 168 | std::streamsize | 
 
 
 
 
 | 169 | gzfilebuf::showmanyc() | 
 
 
 
 
 | 170 | { | 
 
 
 
 
 | 171 | // Calls to underflow will fail if file not opened for reading | 
 
 
 
 
 | 172 | if (!this->is_open() || !(io_mode & std::ios_base::in)) | 
 
 
 
 
 | 173 | return -1; | 
 
 
 
 
 | 174 | // Make sure get area is in use | 
 
 
 
 
 | 175 | if (this->gptr() && (this->gptr() < this->egptr())) | 
 
 
 
 
 | 176 | return std::streamsize(this->egptr() - this->gptr()); | 
 
 
 
 
 | 177 | else | 
 
 
 
 
 | 178 | return 0; | 
 
 
 
 
 | 179 | } | 
 
 
 
 
 | 180 |  | 
 
 
 
 
 | 181 | // Fill get area from gzipped file | 
 
 
 
 
 | 182 | gzfilebuf::int_type | 
 
 
 
 
 | 183 | gzfilebuf::underflow() | 
 
 
 
 
 | 184 | { | 
 
 
 
 
 | 185 | // If something is left in the get area by chance, return it | 
 
 
 
 
 | 186 | // (this shouldn't normally happen, as underflow is only supposed | 
 
 
 
 
 | 187 | // to be called when gptr >= egptr, but it serves as error check) | 
 
 
 
 
 | 188 | if (this->gptr() && (this->gptr() < this->egptr())) | 
 
 
 
 
 | 189 | return traits_type::to_int_type(*(this->gptr())); | 
 
 
 
 
 | 190 |  | 
 
 
 
 
 | 191 | // If the file hasn't been opened for reading, produce error | 
 
 
 
 
 | 192 | if (!this->is_open() || !(io_mode & std::ios_base::in)) | 
 
 
 
 
 | 193 | return traits_type::eof(); | 
 
 
 
 
 | 194 |  | 
 
 
 
 
 | 195 | // Attempt to fill internal buffer from gzipped file | 
 
 
 
 
 | 196 | // (buffer must be guaranteed to exist...) | 
 
 
 
 
 | 197 | int bytes_read = gzread(file, buffer, buffer_size); | 
 
 
 
 
 | 198 | // Indicates error or EOF | 
 
 
 
 
 | 199 | if (bytes_read <= 0) | 
 
 
 
 
 | 200 | { | 
 
 
 
 
 | 201 | // Reset get area | 
 
 
 
 
 | 202 | this->setg(buffer, buffer, buffer); | 
 
 
 
 
 | 203 | return traits_type::eof(); | 
 
 
 
 
 | 204 | } | 
 
 
 
 
 | 205 | // Make all bytes read from file available as get area | 
 
 
 
 
 | 206 | this->setg(buffer, buffer, buffer + bytes_read); | 
 
 
 
 
 | 207 |  | 
 
 
 
 
 | 208 | // Return next character in get area | 
 
 
 
 
 | 209 | return traits_type::to_int_type(*(this->gptr())); | 
 
 
 
 
 | 210 | } | 
 
 
 
 
 | 211 |  | 
 
 
 
 
 | 212 | // Write put area to gzipped file | 
 
 
 
 
 | 213 | gzfilebuf::int_type | 
 
 
 
 
 | 214 | gzfilebuf::overflow(int_type c) | 
 
 
 
 
 | 215 | { | 
 
 
 
 
 | 216 | // Determine whether put area is in use | 
 
 
 
 
 | 217 | if (this->pbase()) | 
 
 
 
 
 | 218 | { | 
 
 
 
 
 | 219 | // Double-check pointer range | 
 
 
 
 
 | 220 | if (this->pptr() > this->epptr() || this->pptr() < this->pbase()) | 
 
 
 
 
 | 221 | return traits_type::eof(); | 
 
 
 
 
 | 222 | // Add extra character to buffer if not EOF | 
 
 
 
 
 | 223 | if (!traits_type::eq_int_type(c, traits_type::eof())) | 
 
 
 
 
 | 224 | { | 
 
 
 
 
 | 225 | *(this->pptr()) = traits_type::to_char_type(c); | 
 
 
 
 
 | 226 | this->pbump(1); | 
 
 
 
 
 | 227 | } | 
 
 
 
 
 | 228 | // Number of characters to write to file | 
 
 
 
 
 | 229 | int bytes_to_write = this->pptr() - this->pbase(); | 
 
 
 
 
 | 230 | // Overflow doesn't fail if nothing is to be written | 
 
 
 
 
 | 231 | if (bytes_to_write > 0) | 
 
 
 
 
 | 232 | { | 
 
 
 
 
 | 233 | // If the file hasn't been opened for writing, produce error | 
 
 
 
 
 | 234 | if (!this->is_open() || !(io_mode & std::ios_base::out)) | 
 
 
 
 
 | 235 | return traits_type::eof(); | 
 
 
 
 
 | 236 | // If gzipped file won't accept all bytes written to it, fail | 
 
 
 
 
 | 237 | if (gzwrite(file, this->pbase(), bytes_to_write) != bytes_to_write) | 
 
 
 
 
 | 238 | return traits_type::eof(); | 
 
 
 
 
 | 239 | // Reset next pointer to point to pbase on success | 
 
 
 
 
 | 240 | this->pbump(-bytes_to_write); | 
 
 
 
 
 | 241 | } | 
 
 
 
 
 | 242 | } | 
 
 
 
 
 | 243 | // Write extra character to file if not EOF | 
 
 
 
 
 | 244 | else if (!traits_type::eq_int_type(c, traits_type::eof())) | 
 
 
 
 
 | 245 | { | 
 
 
 
 
 | 246 | // If the file hasn't been opened for writing, produce error | 
 
 
 
 
 | 247 | if (!this->is_open() || !(io_mode & std::ios_base::out)) | 
 
 
 
 
 | 248 | return traits_type::eof(); | 
 
 
 
 
 | 249 | // Impromptu char buffer (allows "unbuffered" output) | 
 
 
 
 
 | 250 | char_type last_char = traits_type::to_char_type(c); | 
 
 
 
 
 | 251 | // If gzipped file won't accept this character, fail | 
 
 
 
 
 | 252 | if (gzwrite(file, &last_char, 1) != 1) | 
 
 
 
 
 | 253 | return traits_type::eof(); | 
 
 
 
 
 | 254 | } | 
 
 
 
 
 | 255 |  | 
 
 
 
 
 | 256 | // If you got here, you have succeeded (even if c was EOF) | 
 
 
 
 
 | 257 | // The return value should therefore be non-EOF | 
 
 
 
 
 | 258 | if (traits_type::eq_int_type(c, traits_type::eof())) | 
 
 
 
 
 | 259 | return traits_type::not_eof(c); | 
 
 
 
 
 | 260 | else | 
 
 
 
 
 | 261 | return c; | 
 
 
 
 
 | 262 | } | 
 
 
 
 
 | 263 |  | 
 
 
 
 
 | 264 | // Assign new buffer | 
 
 
 
 
 | 265 | std::streambuf* | 
 
 
 
 
 | 266 | gzfilebuf::setbuf(char_type* p, | 
 
 
 
 
 | 267 | std::streamsize n) | 
 
 
 
 
 | 268 | { | 
 
 
 
 
 | 269 | // First make sure stuff is sync'ed, for safety | 
 
 
 
 
 | 270 | if (this->sync() == -1) | 
 
 
 
 
 | 271 | return NULL; | 
 
 
 
 
 | 272 | // If buffering is turned off on purpose via setbuf(0,0), still allocate one... | 
 
 
 
 
 | 273 | // "Unbuffered" only really refers to put [27.8.1.4.10], while get needs at | 
 
 
 
 
 | 274 | // least a buffer of size 1 (very inefficient though, therefore make it bigger?) | 
 
 
 
 
 | 275 | // This follows from [27.5.2.4.3]/12 (gptr needs to point at something, it seems) | 
 
 
 
 
 | 276 | if (!p || !n) | 
 
 
 
 
 | 277 | { | 
 
 
 
 
 | 278 | // Replace existing buffer (if any) with small internal buffer | 
 
 
 
 
 | 279 | this->disable_buffer(); | 
 
 
 
 
 | 280 | buffer = NULL; | 
 
 
 
 
 | 281 | buffer_size = 0; | 
 
 
 
 
 | 282 | own_buffer = true; | 
 
 
 
 
 | 283 | this->enable_buffer(); | 
 
 
 
 
 | 284 | } | 
 
 
 
 
 | 285 | else | 
 
 
 
 
 | 286 | { | 
 
 
 
 
 | 287 | // Replace existing buffer (if any) with external buffer | 
 
 
 
 
 | 288 | this->disable_buffer(); | 
 
 
 
 
 | 289 | buffer = p; | 
 
 
 
 
 | 290 | buffer_size = n; | 
 
 
 
 
 | 291 | own_buffer = false; | 
 
 
 
 
 | 292 | this->enable_buffer(); | 
 
 
 
 
 | 293 | } | 
 
 
 
 
 | 294 | return this; | 
 
 
 
 
 | 295 | } | 
 
 
 
 
 | 296 |  | 
 
 
 
 
 | 297 | // Write put area to gzipped file (i.e. ensures that put area is empty) | 
 
 
 
 
 | 298 | int | 
 
 
 
 
 | 299 | gzfilebuf::sync() | 
 
 
 
 
 | 300 | { | 
 
 
 
 
 | 301 | return traits_type::eq_int_type(this->overflow(), traits_type::eof()) ? -1 : 0; | 
 
 
 
 
 | 302 | } | 
 
 
 
 
 | 303 |  | 
 
 
 
 
 | 304 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | 
 
 
 
 
 | 305 |  | 
 
 
 
 
 | 306 | // Allocate internal buffer | 
 
 
 
 
 | 307 | void | 
 
 
 
 
 | 308 | gzfilebuf::enable_buffer() | 
 
 
 
 
 | 309 | { | 
 
 
 
 
 | 310 | // If internal buffer required, allocate one | 
 
 
 
 
 | 311 | if (own_buffer && !buffer) | 
 
 
 
 
 | 312 | { | 
 
 
 
 
 | 313 | // Check for buffered vs. "unbuffered" | 
 
 
 
 
 | 314 | if (buffer_size > 0) | 
 
 
 
 
 | 315 | { | 
 
 
 
 
 | 316 | // Allocate internal buffer | 
 
 
 
 
 | 317 | buffer = new char_type[buffer_size]; | 
 
 
 
 
 | 318 | // Get area starts empty and will be expanded by underflow as need arises | 
 
 
 
 
 | 319 | this->setg(buffer, buffer, buffer); | 
 
 
 
 
 | 320 | // Setup entire internal buffer as put area. | 
 
 
 
 
 | 321 | // The one-past-end pointer actually points to the last element of the buffer, | 
 
 
 
 
 | 322 | // so that overflow(c) can safely add the extra character c to the sequence. | 
 
 
 
 
 | 323 | // These pointers remain in place for the duration of the buffer | 
 
 
 
 
 | 324 | this->setp(buffer, buffer + buffer_size - 1); | 
 
 
 
 
 | 325 | } | 
 
 
 
 
 | 326 | else | 
 
 
 
 
 | 327 | { | 
 
 
 
 
 | 328 | // Even in "unbuffered" case, (small?) get buffer is still required | 
 
 
 
 
 | 329 | buffer_size = SMALLBUFSIZE; | 
 
 
 
 
 | 330 | buffer = new char_type[buffer_size]; | 
 
 
 
 
 | 331 | this->setg(buffer, buffer, buffer); | 
 
 
 
 
 | 332 | // "Unbuffered" means no put buffer | 
 
 
 
 
 | 333 | this->setp(0, 0); | 
 
 
 
 
 | 334 | } | 
 
 
 
 
 | 335 | } | 
 
 
 
 
 | 336 | else | 
 
 
 
 
 | 337 | { | 
 
 
 
 
 | 338 | // If buffer already allocated, reset buffer pointers just to make sure no | 
 
 
 
 
 | 339 | // stale chars are lying around | 
 
 
 
 
 | 340 | this->setg(buffer, buffer, buffer); | 
 
 
 
 
 | 341 | this->setp(buffer, buffer + buffer_size - 1); | 
 
 
 
 
 | 342 | } | 
 
 
 
 
 | 343 | } | 
 
 
 
 
 | 344 |  | 
 
 
 
 
 | 345 | // Destroy internal buffer | 
 
 
 
 
 | 346 | void | 
 
 
 
 
 | 347 | gzfilebuf::disable_buffer() | 
 
 
 
 
 | 348 | { | 
 
 
 
 
 | 349 | // If internal buffer exists, deallocate it | 
 
 
 
 
 | 350 | if (own_buffer && buffer) | 
 
 
 
 
 | 351 | { | 
 
 
 
 
 | 352 | // Preserve unbuffered status by zeroing size | 
 
 
 
 
 | 353 | if (!this->pbase()) | 
 
 
 
 
 | 354 | buffer_size = 0; | 
 
 
 
 
 | 355 | delete[] buffer; | 
 
 
 
 
 | 356 | buffer = NULL; | 
 
 
 
 
 | 357 | this->setg(0, 0, 0); | 
 
 
 
 
 | 358 | this->setp(0, 0); | 
 
 
 
 
 | 359 | } | 
 
 
 
 
 | 360 | else | 
 
 
 
 
 | 361 | { | 
 
 
 
 
 | 362 | // Reset buffer pointers to initial state if external buffer exists | 
 
 
 
 
 | 363 | this->setg(buffer, buffer, buffer); | 
 
 
 
 
 | 364 | if (buffer) | 
 
 
 
 
 | 365 | this->setp(buffer, buffer + buffer_size - 1); | 
 
 
 
 
 | 366 | else | 
 
 
 
 
 | 367 | this->setp(0, 0); | 
 
 
 
 
 | 368 | } | 
 
 
 
 
 | 369 | } | 
 
 
 
 
 | 370 |  | 
 
 
 
 
 | 371 | /*****************************************************************************/ | 
 
 
 
 
 | 372 |  | 
 
 
 
 
 | 373 | // Default constructor initializes stream buffer | 
 
 
 
 
 | 374 | gzifstream::gzifstream() | 
 
 
 
 
 | 375 | : std::istream(NULL), sb() | 
 
 
 
 
 | 376 | { this->init(&sb); } | 
 
 
 
 
 | 377 |  | 
 
 
 
 
 | 378 | // Initialize stream buffer and open file | 
 
 
 
 
 | 379 | gzifstream::gzifstream(const char* name, | 
 
 
 
 
 | 380 | std::ios_base::openmode mode) | 
 
 
 
 
 | 381 | : std::istream(NULL), sb() | 
 
 
 
 
 | 382 | { | 
 
 
 
 
 | 383 | this->init(&sb); | 
 
 
 
 
 | 384 | this->open(name, mode); | 
 
 
 
 
 | 385 | } | 
 
 
 
 
 | 386 |  | 
 
 
 
 
 | 387 | // Initialize stream buffer and attach to file | 
 
 
 
 
 | 388 | gzifstream::gzifstream(int fd, | 
 
 
 
 
 | 389 | std::ios_base::openmode mode) | 
 
 
 
 
 | 390 | : std::istream(NULL), sb() | 
 
 
 
 
 | 391 | { | 
 
 
 
 
 | 392 | this->init(&sb); | 
 
 
 
 
 | 393 | this->attach(fd, mode); | 
 
 
 
 
 | 394 | } | 
 
 
 
 
 | 395 |  | 
 
 
 
 
 | 396 | // Open file and go into fail() state if unsuccessful | 
 
 
 
 
 | 397 | void | 
 
 
 
 
 | 398 | gzifstream::open(const char* name, | 
 
 
 
 
 | 399 | std::ios_base::openmode mode) | 
 
 
 
 
 | 400 | { | 
 
 
 
 
 | 401 | if (!sb.open(name, mode | std::ios_base::in)) | 
 
 
 
 
 | 402 | this->setstate(std::ios_base::failbit); | 
 
 
 
 
 | 403 | else | 
 
 
 
 
 | 404 | this->clear(); | 
 
 
 
 
 | 405 | } | 
 
 
 
 
 | 406 |  | 
 
 
 
 
 | 407 | // Attach to file and go into fail() state if unsuccessful | 
 
 
 
 
 | 408 | void | 
 
 
 
 
 | 409 | gzifstream::attach(int fd, | 
 
 
 
 
 | 410 | std::ios_base::openmode mode) | 
 
 
 
 
 | 411 | { | 
 
 
 
 
 | 412 | if (!sb.attach(fd, mode | std::ios_base::in)) | 
 
 
 
 
 | 413 | this->setstate(std::ios_base::failbit); | 
 
 
 
 
 | 414 | else | 
 
 
 
 
 | 415 | this->clear(); | 
 
 
 
 
 | 416 | } | 
 
 
 
 
 | 417 |  | 
 
 
 
 
 | 418 | // Close file | 
 
 
 
 
 | 419 | void | 
 
 
 
 
 | 420 | gzifstream::close() | 
 
 
 
 
 | 421 | { | 
 
 
 
 
 | 422 | if (!sb.close()) | 
 
 
 
 
 | 423 | this->setstate(std::ios_base::failbit); | 
 
 
 
 
 | 424 | } | 
 
 
 
 
 | 425 |  | 
 
 
 
 
 | 426 | /*****************************************************************************/ | 
 
 
 
 
 | 427 |  | 
 
 
 
 
 | 428 | // Default constructor initializes stream buffer | 
 
 
 
 
 | 429 | gzofstream::gzofstream() | 
 
 
 
 
 | 430 | : std::ostream(NULL), sb() | 
 
 
 
 
 | 431 | { this->init(&sb); } | 
 
 
 
 
 | 432 |  | 
 
 
 
 
 | 433 | // Initialize stream buffer and open file | 
 
 
 
 
 | 434 | gzofstream::gzofstream(const char* name, | 
 
 
 
 
 | 435 | std::ios_base::openmode mode) | 
 
 
 
 
 | 436 | : std::ostream(NULL), sb() | 
 
 
 
 
 | 437 | { | 
 
 
 
 
 | 438 | this->init(&sb); | 
 
 
 
 
 | 439 | this->open(name, mode); | 
 
 
 
 
 | 440 | } | 
 
 
 
 
 | 441 |  | 
 
 
 
 
 | 442 | // Initialize stream buffer and attach to file | 
 
 
 
 
 | 443 | gzofstream::gzofstream(int fd, | 
 
 
 
 
 | 444 | std::ios_base::openmode mode) | 
 
 
 
 
 | 445 | : std::ostream(NULL), sb() | 
 
 
 
 
 | 446 | { | 
 
 
 
 
 | 447 | this->init(&sb); | 
 
 
 
 
 | 448 | this->attach(fd, mode); | 
 
 
 
 
 | 449 | } | 
 
 
 
 
 | 450 |  | 
 
 
 
 
 | 451 | // Open file and go into fail() state if unsuccessful | 
 
 
 
 
 | 452 | void | 
 
 
 
 
 | 453 | gzofstream::open(const char* name, | 
 
 
 
 
 | 454 | std::ios_base::openmode mode) | 
 
 
 
 
 | 455 | { | 
 
 
 
 
 | 456 | if (!sb.open(name, mode | std::ios_base::out)) | 
 
 
 
 
 | 457 | this->setstate(std::ios_base::failbit); | 
 
 
 
 
 | 458 | else | 
 
 
 
 
 | 459 | this->clear(); | 
 
 
 
 
 | 460 | } | 
 
 
 
 
 | 461 |  | 
 
 
 
 
 | 462 | // Attach to file and go into fail() state if unsuccessful | 
 
 
 
 
 | 463 | void | 
 
 
 
 
 | 464 | gzofstream::attach(int fd, | 
 
 
 
 
 | 465 | std::ios_base::openmode mode) | 
 
 
 
 
 | 466 | { | 
 
 
 
 
 | 467 | if (!sb.attach(fd, mode | std::ios_base::out)) | 
 
 
 
 
 | 468 | this->setstate(std::ios_base::failbit); | 
 
 
 
 
 | 469 | else | 
 
 
 
 
 | 470 | this->clear(); | 
 
 
 
 
 | 471 | } | 
 
 
 
 
 | 472 |  | 
 
 
 
 
 | 473 | // Close file | 
 
 
 
 
 | 474 | void | 
 
 
 
 
 | 475 | gzofstream::close() | 
 
 
 
 
 | 476 | { | 
 
 
 
 
 | 477 | if (!sb.close()) | 
 
 
 
 
 | 478 | this->setstate(std::ios_base::failbit); | 
 
 
 
 
 | 479 | } |