111293Sandreas.hansson@arm.com/* 211293Sandreas.hansson@arm.com * A C++ I/O streams interface to the zlib gz* functions 311293Sandreas.hansson@arm.com * 411293Sandreas.hansson@arm.com * by Ludwig Schwardt <schwardt@sun.ac.za> 511293Sandreas.hansson@arm.com * original version by Kevin Ruland <kevin@rodin.wustl.edu> 611293Sandreas.hansson@arm.com * 711293Sandreas.hansson@arm.com * This version is standard-compliant and compatible with gcc 3.x. 811293Sandreas.hansson@arm.com */ 911293Sandreas.hansson@arm.com 1011293Sandreas.hansson@arm.com#include "zfstream.h" 1111293Sandreas.hansson@arm.com#include <cstring> // for strcpy, strcat, strlen (mode strings) 1211293Sandreas.hansson@arm.com#include <cstdio> // for BUFSIZ 1311293Sandreas.hansson@arm.com 1411293Sandreas.hansson@arm.com// Internal buffer sizes (default and "unbuffered" versions) 1511293Sandreas.hansson@arm.com#define BIGBUFSIZE BUFSIZ 1611293Sandreas.hansson@arm.com#define SMALLBUFSIZE 1 1711293Sandreas.hansson@arm.com 1811293Sandreas.hansson@arm.com/*****************************************************************************/ 1911293Sandreas.hansson@arm.com 2011293Sandreas.hansson@arm.com// Default constructor 2111293Sandreas.hansson@arm.comgzfilebuf::gzfilebuf() 2211293Sandreas.hansson@arm.com: file(NULL), io_mode(std::ios_base::openmode(0)), own_fd(false), 2311293Sandreas.hansson@arm.com buffer(NULL), buffer_size(BIGBUFSIZE), own_buffer(true) 2411293Sandreas.hansson@arm.com{ 2511293Sandreas.hansson@arm.com // No buffers to start with 2611293Sandreas.hansson@arm.com this->disable_buffer(); 2711293Sandreas.hansson@arm.com} 2811293Sandreas.hansson@arm.com 2911293Sandreas.hansson@arm.com// Destructor 3011293Sandreas.hansson@arm.comgzfilebuf::~gzfilebuf() 3111293Sandreas.hansson@arm.com{ 3211293Sandreas.hansson@arm.com // Sync output buffer and close only if responsible for file 3311293Sandreas.hansson@arm.com // (i.e. attached streams should be left open at this stage) 3411293Sandreas.hansson@arm.com this->sync(); 3511293Sandreas.hansson@arm.com if (own_fd) 3611293Sandreas.hansson@arm.com this->close(); 3711293Sandreas.hansson@arm.com // Make sure internal buffer is deallocated 3811293Sandreas.hansson@arm.com this->disable_buffer(); 3911293Sandreas.hansson@arm.com} 4011293Sandreas.hansson@arm.com 4111293Sandreas.hansson@arm.com// Set compression level and strategy 4211293Sandreas.hansson@arm.comint 4311293Sandreas.hansson@arm.comgzfilebuf::setcompression(int comp_level, 4411293Sandreas.hansson@arm.com int comp_strategy) 4511293Sandreas.hansson@arm.com{ 4611293Sandreas.hansson@arm.com return gzsetparams(file, comp_level, comp_strategy); 4711293Sandreas.hansson@arm.com} 4811293Sandreas.hansson@arm.com 4911293Sandreas.hansson@arm.com// Open gzipped file 5011293Sandreas.hansson@arm.comgzfilebuf* 5111293Sandreas.hansson@arm.comgzfilebuf::open(const char *name, 5211293Sandreas.hansson@arm.com std::ios_base::openmode mode) 5311293Sandreas.hansson@arm.com{ 5411293Sandreas.hansson@arm.com // Fail if file already open 5511293Sandreas.hansson@arm.com if (this->is_open()) 5611293Sandreas.hansson@arm.com return NULL; 5711293Sandreas.hansson@arm.com // Don't support simultaneous read/write access (yet) 5811293Sandreas.hansson@arm.com if ((mode & std::ios_base::in) && (mode & std::ios_base::out)) 5911293Sandreas.hansson@arm.com return NULL; 6011293Sandreas.hansson@arm.com 6111293Sandreas.hansson@arm.com // Build mode string for gzopen and check it [27.8.1.3.2] 6211293Sandreas.hansson@arm.com char char_mode[6] = "\0\0\0\0\0"; 6311293Sandreas.hansson@arm.com if (!this->open_mode(mode, char_mode)) 6411293Sandreas.hansson@arm.com return NULL; 6511293Sandreas.hansson@arm.com 6611293Sandreas.hansson@arm.com // Attempt to open file 6711293Sandreas.hansson@arm.com if ((file = gzopen(name, char_mode)) == NULL) 6811293Sandreas.hansson@arm.com return NULL; 6911293Sandreas.hansson@arm.com 7011293Sandreas.hansson@arm.com // On success, allocate internal buffer and set flags 7111293Sandreas.hansson@arm.com this->enable_buffer(); 7211293Sandreas.hansson@arm.com io_mode = mode; 7311293Sandreas.hansson@arm.com own_fd = true; 7411293Sandreas.hansson@arm.com return this; 7511293Sandreas.hansson@arm.com} 7611293Sandreas.hansson@arm.com 7711293Sandreas.hansson@arm.com// Attach to gzipped file 7811293Sandreas.hansson@arm.comgzfilebuf* 7911293Sandreas.hansson@arm.comgzfilebuf::attach(int fd, 8011293Sandreas.hansson@arm.com std::ios_base::openmode mode) 8111293Sandreas.hansson@arm.com{ 8211293Sandreas.hansson@arm.com // Fail if file already open 8311293Sandreas.hansson@arm.com if (this->is_open()) 8411293Sandreas.hansson@arm.com return NULL; 8511293Sandreas.hansson@arm.com // Don't support simultaneous read/write access (yet) 8611293Sandreas.hansson@arm.com if ((mode & std::ios_base::in) && (mode & std::ios_base::out)) 8711293Sandreas.hansson@arm.com return NULL; 8811293Sandreas.hansson@arm.com 8911293Sandreas.hansson@arm.com // Build mode string for gzdopen and check it [27.8.1.3.2] 9011293Sandreas.hansson@arm.com char char_mode[6] = "\0\0\0\0\0"; 9111293Sandreas.hansson@arm.com if (!this->open_mode(mode, char_mode)) 9211293Sandreas.hansson@arm.com return NULL; 9311293Sandreas.hansson@arm.com 9411293Sandreas.hansson@arm.com // Attempt to attach to file 9511293Sandreas.hansson@arm.com if ((file = gzdopen(fd, char_mode)) == NULL) 9611293Sandreas.hansson@arm.com return NULL; 9711293Sandreas.hansson@arm.com 9811293Sandreas.hansson@arm.com // On success, allocate internal buffer and set flags 9911293Sandreas.hansson@arm.com this->enable_buffer(); 10011293Sandreas.hansson@arm.com io_mode = mode; 10111293Sandreas.hansson@arm.com own_fd = false; 10211293Sandreas.hansson@arm.com return this; 10311293Sandreas.hansson@arm.com} 10411293Sandreas.hansson@arm.com 10511293Sandreas.hansson@arm.com// Close gzipped file 10611293Sandreas.hansson@arm.comgzfilebuf* 10711293Sandreas.hansson@arm.comgzfilebuf::close() 10811293Sandreas.hansson@arm.com{ 10911293Sandreas.hansson@arm.com // Fail immediately if no file is open 11011293Sandreas.hansson@arm.com if (!this->is_open()) 11111293Sandreas.hansson@arm.com return NULL; 11211293Sandreas.hansson@arm.com // Assume success 11311293Sandreas.hansson@arm.com gzfilebuf* retval = this; 11411293Sandreas.hansson@arm.com // Attempt to sync and close gzipped file 11511293Sandreas.hansson@arm.com if (this->sync() == -1) 11611293Sandreas.hansson@arm.com retval = NULL; 11711293Sandreas.hansson@arm.com if (gzclose(file) < 0) 11811293Sandreas.hansson@arm.com retval = NULL; 11911293Sandreas.hansson@arm.com // File is now gone anyway (postcondition [27.8.1.3.8]) 12011293Sandreas.hansson@arm.com file = NULL; 12111293Sandreas.hansson@arm.com own_fd = false; 12211293Sandreas.hansson@arm.com // Destroy internal buffer if it exists 12311293Sandreas.hansson@arm.com this->disable_buffer(); 12411293Sandreas.hansson@arm.com return retval; 12511293Sandreas.hansson@arm.com} 12611293Sandreas.hansson@arm.com 12711293Sandreas.hansson@arm.com/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 12811293Sandreas.hansson@arm.com 12911293Sandreas.hansson@arm.com// Convert int open mode to mode string 13011293Sandreas.hansson@arm.combool 13111293Sandreas.hansson@arm.comgzfilebuf::open_mode(std::ios_base::openmode mode, 13211293Sandreas.hansson@arm.com char* c_mode) const 13311293Sandreas.hansson@arm.com{ 13411293Sandreas.hansson@arm.com bool testb = mode & std::ios_base::binary; 13511293Sandreas.hansson@arm.com bool testi = mode & std::ios_base::in; 13611293Sandreas.hansson@arm.com bool testo = mode & std::ios_base::out; 13711293Sandreas.hansson@arm.com bool testt = mode & std::ios_base::trunc; 13811293Sandreas.hansson@arm.com bool testa = mode & std::ios_base::app; 13911293Sandreas.hansson@arm.com 14011293Sandreas.hansson@arm.com // Check for valid flag combinations - see [27.8.1.3.2] (Table 92) 14111293Sandreas.hansson@arm.com // Original zfstream hardcoded the compression level to maximum here... 14211293Sandreas.hansson@arm.com // Double the time for less than 1% size improvement seems 14311293Sandreas.hansson@arm.com // excessive though - keeping it at the default level 14411293Sandreas.hansson@arm.com // To change back, just append "9" to the next three mode strings 14511293Sandreas.hansson@arm.com if (!testi && testo && !testt && !testa) 14611293Sandreas.hansson@arm.com strcpy(c_mode, "w"); 14711293Sandreas.hansson@arm.com if (!testi && testo && !testt && testa) 14811293Sandreas.hansson@arm.com strcpy(c_mode, "a"); 14911293Sandreas.hansson@arm.com if (!testi && testo && testt && !testa) 15011293Sandreas.hansson@arm.com strcpy(c_mode, "w"); 15111293Sandreas.hansson@arm.com if (testi && !testo && !testt && !testa) 15211293Sandreas.hansson@arm.com strcpy(c_mode, "r"); 15311293Sandreas.hansson@arm.com // No read/write mode yet 15411293Sandreas.hansson@arm.com// if (testi && testo && !testt && !testa) 15511293Sandreas.hansson@arm.com// strcpy(c_mode, "r+"); 15611293Sandreas.hansson@arm.com// if (testi && testo && testt && !testa) 15711293Sandreas.hansson@arm.com// strcpy(c_mode, "w+"); 15811293Sandreas.hansson@arm.com 15911293Sandreas.hansson@arm.com // Mode string should be empty for invalid combination of flags 16011293Sandreas.hansson@arm.com if (strlen(c_mode) == 0) 16111293Sandreas.hansson@arm.com return false; 16211293Sandreas.hansson@arm.com if (testb) 16311293Sandreas.hansson@arm.com strcat(c_mode, "b"); 16411293Sandreas.hansson@arm.com return true; 16511293Sandreas.hansson@arm.com} 16611293Sandreas.hansson@arm.com 16711293Sandreas.hansson@arm.com// Determine number of characters in internal get buffer 16811293Sandreas.hansson@arm.comstd::streamsize 16911293Sandreas.hansson@arm.comgzfilebuf::showmanyc() 17011293Sandreas.hansson@arm.com{ 17111293Sandreas.hansson@arm.com // Calls to underflow will fail if file not opened for reading 17211293Sandreas.hansson@arm.com if (!this->is_open() || !(io_mode & std::ios_base::in)) 17311293Sandreas.hansson@arm.com return -1; 17411293Sandreas.hansson@arm.com // Make sure get area is in use 17511293Sandreas.hansson@arm.com if (this->gptr() && (this->gptr() < this->egptr())) 17611293Sandreas.hansson@arm.com return std::streamsize(this->egptr() - this->gptr()); 17711293Sandreas.hansson@arm.com else 17811293Sandreas.hansson@arm.com return 0; 17911293Sandreas.hansson@arm.com} 18011293Sandreas.hansson@arm.com 18111293Sandreas.hansson@arm.com// Fill get area from gzipped file 18211293Sandreas.hansson@arm.comgzfilebuf::int_type 18311293Sandreas.hansson@arm.comgzfilebuf::underflow() 18411293Sandreas.hansson@arm.com{ 18511293Sandreas.hansson@arm.com // If something is left in the get area by chance, return it 18611293Sandreas.hansson@arm.com // (this shouldn't normally happen, as underflow is only supposed 18711293Sandreas.hansson@arm.com // to be called when gptr >= egptr, but it serves as error check) 18811293Sandreas.hansson@arm.com if (this->gptr() && (this->gptr() < this->egptr())) 18911293Sandreas.hansson@arm.com return traits_type::to_int_type(*(this->gptr())); 19011293Sandreas.hansson@arm.com 19111293Sandreas.hansson@arm.com // If the file hasn't been opened for reading, produce error 19211293Sandreas.hansson@arm.com if (!this->is_open() || !(io_mode & std::ios_base::in)) 19311293Sandreas.hansson@arm.com return traits_type::eof(); 19411293Sandreas.hansson@arm.com 19511293Sandreas.hansson@arm.com // Attempt to fill internal buffer from gzipped file 19611293Sandreas.hansson@arm.com // (buffer must be guaranteed to exist...) 19711293Sandreas.hansson@arm.com int bytes_read = gzread(file, buffer, buffer_size); 19811293Sandreas.hansson@arm.com // Indicates error or EOF 19911293Sandreas.hansson@arm.com if (bytes_read <= 0) 20011293Sandreas.hansson@arm.com { 20111293Sandreas.hansson@arm.com // Reset get area 20211293Sandreas.hansson@arm.com this->setg(buffer, buffer, buffer); 20311293Sandreas.hansson@arm.com return traits_type::eof(); 20411293Sandreas.hansson@arm.com } 20511293Sandreas.hansson@arm.com // Make all bytes read from file available as get area 20611293Sandreas.hansson@arm.com this->setg(buffer, buffer, buffer + bytes_read); 20711293Sandreas.hansson@arm.com 20811293Sandreas.hansson@arm.com // Return next character in get area 20911293Sandreas.hansson@arm.com return traits_type::to_int_type(*(this->gptr())); 21011293Sandreas.hansson@arm.com} 21111293Sandreas.hansson@arm.com 21211293Sandreas.hansson@arm.com// Write put area to gzipped file 21311293Sandreas.hansson@arm.comgzfilebuf::int_type 21411293Sandreas.hansson@arm.comgzfilebuf::overflow(int_type c) 21511293Sandreas.hansson@arm.com{ 21611293Sandreas.hansson@arm.com // Determine whether put area is in use 21711293Sandreas.hansson@arm.com if (this->pbase()) 21811293Sandreas.hansson@arm.com { 21911293Sandreas.hansson@arm.com // Double-check pointer range 22011293Sandreas.hansson@arm.com if (this->pptr() > this->epptr() || this->pptr() < this->pbase()) 22111293Sandreas.hansson@arm.com return traits_type::eof(); 22211293Sandreas.hansson@arm.com // Add extra character to buffer if not EOF 22311293Sandreas.hansson@arm.com if (!traits_type::eq_int_type(c, traits_type::eof())) 22411293Sandreas.hansson@arm.com { 22511293Sandreas.hansson@arm.com *(this->pptr()) = traits_type::to_char_type(c); 22611293Sandreas.hansson@arm.com this->pbump(1); 22711293Sandreas.hansson@arm.com } 22811293Sandreas.hansson@arm.com // Number of characters to write to file 22911293Sandreas.hansson@arm.com int bytes_to_write = this->pptr() - this->pbase(); 23011293Sandreas.hansson@arm.com // Overflow doesn't fail if nothing is to be written 23111293Sandreas.hansson@arm.com if (bytes_to_write > 0) 23211293Sandreas.hansson@arm.com { 23311293Sandreas.hansson@arm.com // If the file hasn't been opened for writing, produce error 23411293Sandreas.hansson@arm.com if (!this->is_open() || !(io_mode & std::ios_base::out)) 23511293Sandreas.hansson@arm.com return traits_type::eof(); 23611293Sandreas.hansson@arm.com // If gzipped file won't accept all bytes written to it, fail 23711293Sandreas.hansson@arm.com if (gzwrite(file, this->pbase(), bytes_to_write) != bytes_to_write) 23811293Sandreas.hansson@arm.com return traits_type::eof(); 23911293Sandreas.hansson@arm.com // Reset next pointer to point to pbase on success 24011293Sandreas.hansson@arm.com this->pbump(-bytes_to_write); 24111293Sandreas.hansson@arm.com } 24211293Sandreas.hansson@arm.com } 24311293Sandreas.hansson@arm.com // Write extra character to file if not EOF 24411293Sandreas.hansson@arm.com else if (!traits_type::eq_int_type(c, traits_type::eof())) 24511293Sandreas.hansson@arm.com { 24611293Sandreas.hansson@arm.com // If the file hasn't been opened for writing, produce error 24711293Sandreas.hansson@arm.com if (!this->is_open() || !(io_mode & std::ios_base::out)) 24811293Sandreas.hansson@arm.com return traits_type::eof(); 24911293Sandreas.hansson@arm.com // Impromptu char buffer (allows "unbuffered" output) 25011293Sandreas.hansson@arm.com char_type last_char = traits_type::to_char_type(c); 25111293Sandreas.hansson@arm.com // If gzipped file won't accept this character, fail 25211293Sandreas.hansson@arm.com if (gzwrite(file, &last_char, 1) != 1) 25311293Sandreas.hansson@arm.com return traits_type::eof(); 25411293Sandreas.hansson@arm.com } 25511293Sandreas.hansson@arm.com 25611293Sandreas.hansson@arm.com // If you got here, you have succeeded (even if c was EOF) 25711293Sandreas.hansson@arm.com // The return value should therefore be non-EOF 25811293Sandreas.hansson@arm.com if (traits_type::eq_int_type(c, traits_type::eof())) 25911293Sandreas.hansson@arm.com return traits_type::not_eof(c); 26011293Sandreas.hansson@arm.com else 26111293Sandreas.hansson@arm.com return c; 26211293Sandreas.hansson@arm.com} 26311293Sandreas.hansson@arm.com 26411293Sandreas.hansson@arm.com// Assign new buffer 26511293Sandreas.hansson@arm.comstd::streambuf* 26611293Sandreas.hansson@arm.comgzfilebuf::setbuf(char_type* p, 26711293Sandreas.hansson@arm.com std::streamsize n) 26811293Sandreas.hansson@arm.com{ 26911293Sandreas.hansson@arm.com // First make sure stuff is sync'ed, for safety 27011293Sandreas.hansson@arm.com if (this->sync() == -1) 27111293Sandreas.hansson@arm.com return NULL; 27211293Sandreas.hansson@arm.com // If buffering is turned off on purpose via setbuf(0,0), still allocate one... 27311293Sandreas.hansson@arm.com // "Unbuffered" only really refers to put [27.8.1.4.10], while get needs at 27411293Sandreas.hansson@arm.com // least a buffer of size 1 (very inefficient though, therefore make it bigger?) 27511293Sandreas.hansson@arm.com // This follows from [27.5.2.4.3]/12 (gptr needs to point at something, it seems) 27611293Sandreas.hansson@arm.com if (!p || !n) 27711293Sandreas.hansson@arm.com { 27811293Sandreas.hansson@arm.com // Replace existing buffer (if any) with small internal buffer 27911293Sandreas.hansson@arm.com this->disable_buffer(); 28011293Sandreas.hansson@arm.com buffer = NULL; 28111293Sandreas.hansson@arm.com buffer_size = 0; 28211293Sandreas.hansson@arm.com own_buffer = true; 28311293Sandreas.hansson@arm.com this->enable_buffer(); 28411293Sandreas.hansson@arm.com } 28511293Sandreas.hansson@arm.com else 28611293Sandreas.hansson@arm.com { 28711293Sandreas.hansson@arm.com // Replace existing buffer (if any) with external buffer 28811293Sandreas.hansson@arm.com this->disable_buffer(); 28911293Sandreas.hansson@arm.com buffer = p; 29011293Sandreas.hansson@arm.com buffer_size = n; 29111293Sandreas.hansson@arm.com own_buffer = false; 29211293Sandreas.hansson@arm.com this->enable_buffer(); 29311293Sandreas.hansson@arm.com } 29411293Sandreas.hansson@arm.com return this; 29511293Sandreas.hansson@arm.com} 29611293Sandreas.hansson@arm.com 29711293Sandreas.hansson@arm.com// Write put area to gzipped file (i.e. ensures that put area is empty) 29811293Sandreas.hansson@arm.comint 29911293Sandreas.hansson@arm.comgzfilebuf::sync() 30011293Sandreas.hansson@arm.com{ 30111293Sandreas.hansson@arm.com return traits_type::eq_int_type(this->overflow(), traits_type::eof()) ? -1 : 0; 30211293Sandreas.hansson@arm.com} 30311293Sandreas.hansson@arm.com 30411293Sandreas.hansson@arm.com/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 30511293Sandreas.hansson@arm.com 30611293Sandreas.hansson@arm.com// Allocate internal buffer 30711293Sandreas.hansson@arm.comvoid 30811293Sandreas.hansson@arm.comgzfilebuf::enable_buffer() 30911293Sandreas.hansson@arm.com{ 31011293Sandreas.hansson@arm.com // If internal buffer required, allocate one 31111293Sandreas.hansson@arm.com if (own_buffer && !buffer) 31211293Sandreas.hansson@arm.com { 31311293Sandreas.hansson@arm.com // Check for buffered vs. "unbuffered" 31411293Sandreas.hansson@arm.com if (buffer_size > 0) 31511293Sandreas.hansson@arm.com { 31611293Sandreas.hansson@arm.com // Allocate internal buffer 31711293Sandreas.hansson@arm.com buffer = new char_type[buffer_size]; 31811293Sandreas.hansson@arm.com // Get area starts empty and will be expanded by underflow as need arises 31911293Sandreas.hansson@arm.com this->setg(buffer, buffer, buffer); 32011293Sandreas.hansson@arm.com // Setup entire internal buffer as put area. 32111293Sandreas.hansson@arm.com // The one-past-end pointer actually points to the last element of the buffer, 32211293Sandreas.hansson@arm.com // so that overflow(c) can safely add the extra character c to the sequence. 32311293Sandreas.hansson@arm.com // These pointers remain in place for the duration of the buffer 32411293Sandreas.hansson@arm.com this->setp(buffer, buffer + buffer_size - 1); 32511293Sandreas.hansson@arm.com } 32611293Sandreas.hansson@arm.com else 32711293Sandreas.hansson@arm.com { 32811293Sandreas.hansson@arm.com // Even in "unbuffered" case, (small?) get buffer is still required 32911293Sandreas.hansson@arm.com buffer_size = SMALLBUFSIZE; 33011293Sandreas.hansson@arm.com buffer = new char_type[buffer_size]; 33111293Sandreas.hansson@arm.com this->setg(buffer, buffer, buffer); 33211293Sandreas.hansson@arm.com // "Unbuffered" means no put buffer 33311293Sandreas.hansson@arm.com this->setp(0, 0); 33411293Sandreas.hansson@arm.com } 33511293Sandreas.hansson@arm.com } 33611293Sandreas.hansson@arm.com else 33711293Sandreas.hansson@arm.com { 33811293Sandreas.hansson@arm.com // If buffer already allocated, reset buffer pointers just to make sure no 33911293Sandreas.hansson@arm.com // stale chars are lying around 34011293Sandreas.hansson@arm.com this->setg(buffer, buffer, buffer); 34111293Sandreas.hansson@arm.com this->setp(buffer, buffer + buffer_size - 1); 34211293Sandreas.hansson@arm.com } 34311293Sandreas.hansson@arm.com} 34411293Sandreas.hansson@arm.com 34511293Sandreas.hansson@arm.com// Destroy internal buffer 34611293Sandreas.hansson@arm.comvoid 34711293Sandreas.hansson@arm.comgzfilebuf::disable_buffer() 34811293Sandreas.hansson@arm.com{ 34911293Sandreas.hansson@arm.com // If internal buffer exists, deallocate it 35011293Sandreas.hansson@arm.com if (own_buffer && buffer) 35111293Sandreas.hansson@arm.com { 35211293Sandreas.hansson@arm.com // Preserve unbuffered status by zeroing size 35311293Sandreas.hansson@arm.com if (!this->pbase()) 35411293Sandreas.hansson@arm.com buffer_size = 0; 35511293Sandreas.hansson@arm.com delete[] buffer; 35611293Sandreas.hansson@arm.com buffer = NULL; 35711293Sandreas.hansson@arm.com this->setg(0, 0, 0); 35811293Sandreas.hansson@arm.com this->setp(0, 0); 35911293Sandreas.hansson@arm.com } 36011293Sandreas.hansson@arm.com else 36111293Sandreas.hansson@arm.com { 36211293Sandreas.hansson@arm.com // Reset buffer pointers to initial state if external buffer exists 36311293Sandreas.hansson@arm.com this->setg(buffer, buffer, buffer); 36411293Sandreas.hansson@arm.com if (buffer) 36511293Sandreas.hansson@arm.com this->setp(buffer, buffer + buffer_size - 1); 36611293Sandreas.hansson@arm.com else 36711293Sandreas.hansson@arm.com this->setp(0, 0); 36811293Sandreas.hansson@arm.com } 36911293Sandreas.hansson@arm.com} 37011293Sandreas.hansson@arm.com 37111293Sandreas.hansson@arm.com/*****************************************************************************/ 37211293Sandreas.hansson@arm.com 37311293Sandreas.hansson@arm.com// Default constructor initializes stream buffer 37411293Sandreas.hansson@arm.comgzifstream::gzifstream() 37511293Sandreas.hansson@arm.com: std::istream(NULL), sb() 37611293Sandreas.hansson@arm.com{ this->init(&sb); } 37711293Sandreas.hansson@arm.com 37811293Sandreas.hansson@arm.com// Initialize stream buffer and open file 37911293Sandreas.hansson@arm.comgzifstream::gzifstream(const char* name, 38011293Sandreas.hansson@arm.com std::ios_base::openmode mode) 38111293Sandreas.hansson@arm.com: std::istream(NULL), sb() 38211293Sandreas.hansson@arm.com{ 38311293Sandreas.hansson@arm.com this->init(&sb); 38411293Sandreas.hansson@arm.com this->open(name, mode); 38511293Sandreas.hansson@arm.com} 38611293Sandreas.hansson@arm.com 38711293Sandreas.hansson@arm.com// Initialize stream buffer and attach to file 38811293Sandreas.hansson@arm.comgzifstream::gzifstream(int fd, 38911293Sandreas.hansson@arm.com std::ios_base::openmode mode) 39011293Sandreas.hansson@arm.com: std::istream(NULL), sb() 39111293Sandreas.hansson@arm.com{ 39211293Sandreas.hansson@arm.com this->init(&sb); 39311293Sandreas.hansson@arm.com this->attach(fd, mode); 39411293Sandreas.hansson@arm.com} 39511293Sandreas.hansson@arm.com 39611293Sandreas.hansson@arm.com// Open file and go into fail() state if unsuccessful 39711293Sandreas.hansson@arm.comvoid 39811293Sandreas.hansson@arm.comgzifstream::open(const char* name, 39911293Sandreas.hansson@arm.com std::ios_base::openmode mode) 40011293Sandreas.hansson@arm.com{ 40111293Sandreas.hansson@arm.com if (!sb.open(name, mode | std::ios_base::in)) 40211293Sandreas.hansson@arm.com this->setstate(std::ios_base::failbit); 40311293Sandreas.hansson@arm.com else 40411293Sandreas.hansson@arm.com this->clear(); 40511293Sandreas.hansson@arm.com} 40611293Sandreas.hansson@arm.com 40711293Sandreas.hansson@arm.com// Attach to file and go into fail() state if unsuccessful 40811293Sandreas.hansson@arm.comvoid 40911293Sandreas.hansson@arm.comgzifstream::attach(int fd, 41011293Sandreas.hansson@arm.com std::ios_base::openmode mode) 41111293Sandreas.hansson@arm.com{ 41211293Sandreas.hansson@arm.com if (!sb.attach(fd, mode | std::ios_base::in)) 41311293Sandreas.hansson@arm.com this->setstate(std::ios_base::failbit); 41411293Sandreas.hansson@arm.com else 41511293Sandreas.hansson@arm.com this->clear(); 41611293Sandreas.hansson@arm.com} 41711293Sandreas.hansson@arm.com 41811293Sandreas.hansson@arm.com// Close file 41911293Sandreas.hansson@arm.comvoid 42011293Sandreas.hansson@arm.comgzifstream::close() 42111293Sandreas.hansson@arm.com{ 42211293Sandreas.hansson@arm.com if (!sb.close()) 42311293Sandreas.hansson@arm.com this->setstate(std::ios_base::failbit); 42411293Sandreas.hansson@arm.com} 42511293Sandreas.hansson@arm.com 42611293Sandreas.hansson@arm.com/*****************************************************************************/ 42711293Sandreas.hansson@arm.com 42811293Sandreas.hansson@arm.com// Default constructor initializes stream buffer 42911293Sandreas.hansson@arm.comgzofstream::gzofstream() 43011293Sandreas.hansson@arm.com: std::ostream(NULL), sb() 43111293Sandreas.hansson@arm.com{ this->init(&sb); } 43211293Sandreas.hansson@arm.com 43311293Sandreas.hansson@arm.com// Initialize stream buffer and open file 43411293Sandreas.hansson@arm.comgzofstream::gzofstream(const char* name, 43511293Sandreas.hansson@arm.com std::ios_base::openmode mode) 43611293Sandreas.hansson@arm.com: std::ostream(NULL), sb() 43711293Sandreas.hansson@arm.com{ 43811293Sandreas.hansson@arm.com this->init(&sb); 43911293Sandreas.hansson@arm.com this->open(name, mode); 44011293Sandreas.hansson@arm.com} 44111293Sandreas.hansson@arm.com 44211293Sandreas.hansson@arm.com// Initialize stream buffer and attach to file 44311293Sandreas.hansson@arm.comgzofstream::gzofstream(int fd, 44411293Sandreas.hansson@arm.com std::ios_base::openmode mode) 44511293Sandreas.hansson@arm.com: std::ostream(NULL), sb() 44611293Sandreas.hansson@arm.com{ 44711293Sandreas.hansson@arm.com this->init(&sb); 44811293Sandreas.hansson@arm.com this->attach(fd, mode); 44911293Sandreas.hansson@arm.com} 45011293Sandreas.hansson@arm.com 45111293Sandreas.hansson@arm.com// Open file and go into fail() state if unsuccessful 45211293Sandreas.hansson@arm.comvoid 45311293Sandreas.hansson@arm.comgzofstream::open(const char* name, 45411293Sandreas.hansson@arm.com std::ios_base::openmode mode) 45511293Sandreas.hansson@arm.com{ 45611293Sandreas.hansson@arm.com if (!sb.open(name, mode | std::ios_base::out)) 45711293Sandreas.hansson@arm.com this->setstate(std::ios_base::failbit); 45811293Sandreas.hansson@arm.com else 45911293Sandreas.hansson@arm.com this->clear(); 46011293Sandreas.hansson@arm.com} 46111293Sandreas.hansson@arm.com 46211293Sandreas.hansson@arm.com// Attach to file and go into fail() state if unsuccessful 46311293Sandreas.hansson@arm.comvoid 46411293Sandreas.hansson@arm.comgzofstream::attach(int fd, 46511293Sandreas.hansson@arm.com std::ios_base::openmode mode) 46611293Sandreas.hansson@arm.com{ 46711293Sandreas.hansson@arm.com if (!sb.attach(fd, mode | std::ios_base::out)) 46811293Sandreas.hansson@arm.com this->setstate(std::ios_base::failbit); 46911293Sandreas.hansson@arm.com else 47011293Sandreas.hansson@arm.com this->clear(); 47111293Sandreas.hansson@arm.com} 47211293Sandreas.hansson@arm.com 47311293Sandreas.hansson@arm.com// Close file 47411293Sandreas.hansson@arm.comvoid 47511293Sandreas.hansson@arm.comgzofstream::close() 47611293Sandreas.hansson@arm.com{ 47711293Sandreas.hansson@arm.com if (!sb.close()) 47811293Sandreas.hansson@arm.com this->setstate(std::ios_base::failbit); 47911293Sandreas.hansson@arm.com} 480