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