cannam@89: cannam@89: #include "zfstream.h" cannam@89: cannam@89: gzfilebuf::gzfilebuf() : cannam@89: file(NULL), cannam@89: mode(0), cannam@89: own_file_descriptor(0) cannam@89: { } cannam@89: cannam@89: gzfilebuf::~gzfilebuf() { cannam@89: cannam@89: sync(); cannam@89: if ( own_file_descriptor ) cannam@89: close(); cannam@89: cannam@89: } cannam@89: cannam@89: gzfilebuf *gzfilebuf::open( const char *name, cannam@89: int io_mode ) { cannam@89: cannam@89: if ( is_open() ) cannam@89: return NULL; cannam@89: cannam@89: char char_mode[10]; cannam@89: char *p = char_mode; cannam@89: cannam@89: if ( io_mode & ios::in ) { cannam@89: mode = ios::in; cannam@89: *p++ = 'r'; cannam@89: } else if ( io_mode & ios::app ) { cannam@89: mode = ios::app; cannam@89: *p++ = 'a'; cannam@89: } else { cannam@89: mode = ios::out; cannam@89: *p++ = 'w'; cannam@89: } cannam@89: cannam@89: if ( io_mode & ios::binary ) { cannam@89: mode |= ios::binary; cannam@89: *p++ = 'b'; cannam@89: } cannam@89: cannam@89: // Hard code the compression level cannam@89: if ( io_mode & (ios::out|ios::app )) { cannam@89: *p++ = '9'; cannam@89: } cannam@89: cannam@89: // Put the end-of-string indicator cannam@89: *p = '\0'; cannam@89: cannam@89: if ( (file = gzopen(name, char_mode)) == NULL ) cannam@89: return NULL; cannam@89: cannam@89: own_file_descriptor = 1; cannam@89: cannam@89: return this; cannam@89: cannam@89: } cannam@89: cannam@89: gzfilebuf *gzfilebuf::attach( int file_descriptor, cannam@89: int io_mode ) { cannam@89: cannam@89: if ( is_open() ) cannam@89: return NULL; cannam@89: cannam@89: char char_mode[10]; cannam@89: char *p = char_mode; cannam@89: cannam@89: if ( io_mode & ios::in ) { cannam@89: mode = ios::in; cannam@89: *p++ = 'r'; cannam@89: } else if ( io_mode & ios::app ) { cannam@89: mode = ios::app; cannam@89: *p++ = 'a'; cannam@89: } else { cannam@89: mode = ios::out; cannam@89: *p++ = 'w'; cannam@89: } cannam@89: cannam@89: if ( io_mode & ios::binary ) { cannam@89: mode |= ios::binary; cannam@89: *p++ = 'b'; cannam@89: } cannam@89: cannam@89: // Hard code the compression level cannam@89: if ( io_mode & (ios::out|ios::app )) { cannam@89: *p++ = '9'; cannam@89: } cannam@89: cannam@89: // Put the end-of-string indicator cannam@89: *p = '\0'; cannam@89: cannam@89: if ( (file = gzdopen(file_descriptor, char_mode)) == NULL ) cannam@89: return NULL; cannam@89: cannam@89: own_file_descriptor = 0; cannam@89: cannam@89: return this; cannam@89: cannam@89: } cannam@89: cannam@89: gzfilebuf *gzfilebuf::close() { cannam@89: cannam@89: if ( is_open() ) { cannam@89: cannam@89: sync(); cannam@89: gzclose( file ); cannam@89: file = NULL; cannam@89: cannam@89: } cannam@89: cannam@89: return this; cannam@89: cannam@89: } cannam@89: cannam@89: int gzfilebuf::setcompressionlevel( int comp_level ) { cannam@89: cannam@89: return gzsetparams(file, comp_level, -2); cannam@89: cannam@89: } cannam@89: cannam@89: int gzfilebuf::setcompressionstrategy( int comp_strategy ) { cannam@89: cannam@89: return gzsetparams(file, -2, comp_strategy); cannam@89: cannam@89: } cannam@89: cannam@89: cannam@89: streampos gzfilebuf::seekoff( streamoff off, ios::seek_dir dir, int which ) { cannam@89: cannam@89: return streampos(EOF); cannam@89: cannam@89: } cannam@89: cannam@89: int gzfilebuf::underflow() { cannam@89: cannam@89: // If the file hasn't been opened for reading, error. cannam@89: if ( !is_open() || !(mode & ios::in) ) cannam@89: return EOF; cannam@89: cannam@89: // if a buffer doesn't exists, allocate one. cannam@89: if ( !base() ) { cannam@89: cannam@89: if ( (allocate()) == EOF ) cannam@89: return EOF; cannam@89: setp(0,0); cannam@89: cannam@89: } else { cannam@89: cannam@89: if ( in_avail() ) cannam@89: return (unsigned char) *gptr(); cannam@89: cannam@89: if ( out_waiting() ) { cannam@89: if ( flushbuf() == EOF ) cannam@89: return EOF; cannam@89: } cannam@89: cannam@89: } cannam@89: cannam@89: // Attempt to fill the buffer. cannam@89: cannam@89: int result = fillbuf(); cannam@89: if ( result == EOF ) { cannam@89: // disable get area cannam@89: setg(0,0,0); cannam@89: return EOF; cannam@89: } cannam@89: cannam@89: return (unsigned char) *gptr(); cannam@89: cannam@89: } cannam@89: cannam@89: int gzfilebuf::overflow( int c ) { cannam@89: cannam@89: if ( !is_open() || !(mode & ios::out) ) cannam@89: return EOF; cannam@89: cannam@89: if ( !base() ) { cannam@89: if ( allocate() == EOF ) cannam@89: return EOF; cannam@89: setg(0,0,0); cannam@89: } else { cannam@89: if (in_avail()) { cannam@89: return EOF; cannam@89: } cannam@89: if (out_waiting()) { cannam@89: if (flushbuf() == EOF) cannam@89: return EOF; cannam@89: } cannam@89: } cannam@89: cannam@89: int bl = blen(); cannam@89: setp( base(), base() + bl); cannam@89: cannam@89: if ( c != EOF ) { cannam@89: cannam@89: *pptr() = c; cannam@89: pbump(1); cannam@89: cannam@89: } cannam@89: cannam@89: return 0; cannam@89: cannam@89: } cannam@89: cannam@89: int gzfilebuf::sync() { cannam@89: cannam@89: if ( !is_open() ) cannam@89: return EOF; cannam@89: cannam@89: if ( out_waiting() ) cannam@89: return flushbuf(); cannam@89: cannam@89: return 0; cannam@89: cannam@89: } cannam@89: cannam@89: int gzfilebuf::flushbuf() { cannam@89: cannam@89: int n; cannam@89: char *q; cannam@89: cannam@89: q = pbase(); cannam@89: n = pptr() - q; cannam@89: cannam@89: if ( gzwrite( file, q, n) < n ) cannam@89: return EOF; cannam@89: cannam@89: setp(0,0); cannam@89: cannam@89: return 0; cannam@89: cannam@89: } cannam@89: cannam@89: int gzfilebuf::fillbuf() { cannam@89: cannam@89: int required; cannam@89: char *p; cannam@89: cannam@89: p = base(); cannam@89: cannam@89: required = blen(); cannam@89: cannam@89: int t = gzread( file, p, required ); cannam@89: cannam@89: if ( t <= 0) return EOF; cannam@89: cannam@89: setg( base(), base(), base()+t); cannam@89: cannam@89: return t; cannam@89: cannam@89: } cannam@89: cannam@89: gzfilestream_common::gzfilestream_common() : cannam@89: ios( gzfilestream_common::rdbuf() ) cannam@89: { } cannam@89: cannam@89: gzfilestream_common::~gzfilestream_common() cannam@89: { } cannam@89: cannam@89: void gzfilestream_common::attach( int fd, int io_mode ) { cannam@89: cannam@89: if ( !buffer.attach( fd, io_mode) ) cannam@89: clear( ios::failbit | ios::badbit ); cannam@89: else cannam@89: clear(); cannam@89: cannam@89: } cannam@89: cannam@89: void gzfilestream_common::open( const char *name, int io_mode ) { cannam@89: cannam@89: if ( !buffer.open( name, io_mode ) ) cannam@89: clear( ios::failbit | ios::badbit ); cannam@89: else cannam@89: clear(); cannam@89: cannam@89: } cannam@89: cannam@89: void gzfilestream_common::close() { cannam@89: cannam@89: if ( !buffer.close() ) cannam@89: clear( ios::failbit | ios::badbit ); cannam@89: cannam@89: } cannam@89: cannam@89: gzfilebuf *gzfilestream_common::rdbuf() cannam@89: { cannam@89: return &buffer; cannam@89: } cannam@89: cannam@89: gzifstream::gzifstream() : cannam@89: ios( gzfilestream_common::rdbuf() ) cannam@89: { cannam@89: clear( ios::badbit ); cannam@89: } cannam@89: cannam@89: gzifstream::gzifstream( const char *name, int io_mode ) : cannam@89: ios( gzfilestream_common::rdbuf() ) cannam@89: { cannam@89: gzfilestream_common::open( name, io_mode ); cannam@89: } cannam@89: cannam@89: gzifstream::gzifstream( int fd, int io_mode ) : cannam@89: ios( gzfilestream_common::rdbuf() ) cannam@89: { cannam@89: gzfilestream_common::attach( fd, io_mode ); cannam@89: } cannam@89: cannam@89: gzifstream::~gzifstream() { } cannam@89: cannam@89: gzofstream::gzofstream() : cannam@89: ios( gzfilestream_common::rdbuf() ) cannam@89: { cannam@89: clear( ios::badbit ); cannam@89: } cannam@89: cannam@89: gzofstream::gzofstream( const char *name, int io_mode ) : cannam@89: ios( gzfilestream_common::rdbuf() ) cannam@89: { cannam@89: gzfilestream_common::open( name, io_mode ); cannam@89: } cannam@89: cannam@89: gzofstream::gzofstream( int fd, int io_mode ) : cannam@89: ios( gzfilestream_common::rdbuf() ) cannam@89: { cannam@89: gzfilestream_common::attach( fd, io_mode ); cannam@89: } cannam@89: cannam@89: gzofstream::~gzofstream() { }