Fossil SCM

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

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button