121308Sache
221308Sache#include "zfstream.h"
321308Sache
421308Sachegzfilebuf::gzfilebuf() :
521308Sache  file(NULL),
621308Sache  mode(0),
7119610Sache  own_file_descriptor(0)
821308Sache{ }
921308Sache
1021308Sachegzfilebuf::~gzfilebuf() {
1121308Sache
1221308Sache  sync();
1321308Sache  if ( own_file_descriptor )
1421308Sache    close();
1558310Sache
1621308Sache}
1721308Sache
1821308Sachegzfilebuf *gzfilebuf::open( const char *name,
1921308Sache                            int io_mode ) {
2021308Sache
2121308Sache  if ( is_open() )
2221308Sache    return NULL;
2321308Sache
2421308Sache  char char_mode[10];
2521308Sache  char *p = char_mode;
2658310Sache
2721308Sache  if ( io_mode & ios::in ) {
2821308Sache    mode = ios::in;
2921308Sache    *p++ = 'r';
3021308Sache  } else if ( io_mode & ios::app ) {
3121308Sache    mode = ios::app;
3221308Sache    *p++ = 'a';
3326497Sache  } else {
3426497Sache    mode = ios::out;
3521308Sache    *p++ = 'w';
3621308Sache  }
3721308Sache
3821308Sache  if ( io_mode & ios::binary ) {
3921308Sache    mode |= ios::binary;
4021308Sache    *p++ = 'b';
4126497Sache  }
4226497Sache
4326497Sache  // Hard code the compression level
4426497Sache  if ( io_mode & (ios::out|ios::app )) {
4526497Sache    *p++ = '9';
4621308Sache  }
4721308Sache
48119610Sache  // Put the end-of-string indicator
49119610Sache  *p = '\0';
5021308Sache
5121308Sache  if ( (file = gzopen(name, char_mode)) == NULL )
5221308Sache    return NULL;
5358310Sache
5458310Sache  own_file_descriptor = 1;
5558310Sache
5647558Sache  return this;
57119610Sache
5847558Sache}
5921308Sache
6075406Sachegzfilebuf *gzfilebuf::attach( int file_descriptor,
6121308Sache                              int io_mode ) {
6258310Sache
63119610Sache  if ( is_open() )
6421308Sache    return NULL;
6521308Sache
6621308Sache  char char_mode[10];
6721308Sache  char *p = char_mode;
6821308Sache
69119610Sache  if ( io_mode & ios::in ) {
70119610Sache    mode = ios::in;
71119610Sache    *p++ = 'r';
7275406Sache  } else if ( io_mode & ios::app ) {
73119610Sache    mode = ios::app;
74119610Sache    *p++ = 'a';
7521308Sache  } else {
7621308Sache    mode = ios::out;
7721308Sache    *p++ = 'w';
7821308Sache  }
7921308Sache
8021308Sache  if ( io_mode & ios::binary ) {
8121308Sache    mode |= ios::binary;
8221308Sache    *p++ = 'b';
8321308Sache  }
8421308Sache
8521308Sache  // Hard code the compression level
8621308Sache  if ( io_mode & (ios::out|ios::app )) {
8721308Sache    *p++ = '9';
8821308Sache  }
8921308Sache
9021308Sache  // Put the end-of-string indicator
9121308Sache  *p = '\0';
9221308Sache
9321308Sache  if ( (file = gzdopen(file_descriptor, char_mode)) == NULL )
9421308Sache    return NULL;
9521308Sache
9621308Sache  own_file_descriptor = 0;
9721308Sache
9821308Sache  return this;
9921308Sache
10021308Sache}
10121308Sache
10221308Sachegzfilebuf *gzfilebuf::close() {
10321308Sache
10421308Sache  if ( is_open() ) {
10521308Sache
10621308Sache    sync();
10721308Sache    gzclose( file );
108119610Sache    file = NULL;
10921308Sache
11021308Sache  }
11121308Sache
11221308Sache  return this;
11321308Sache
11421308Sache}
11521308Sache
11621308Sacheint gzfilebuf::setcompressionlevel( int comp_level ) {
11721308Sache
11821308Sache  return gzsetparams(file, comp_level, -2);
11921308Sache
12021308Sache}
12121308Sache
12221308Sacheint gzfilebuf::setcompressionstrategy( int comp_strategy ) {
12321308Sache
12421308Sache  return gzsetparams(file, -2, comp_strategy);
12521308Sache
12621308Sache}
12721308Sache
12821308Sache
12921308Sachestreampos gzfilebuf::seekoff( streamoff off, ios::seek_dir dir, int which ) {
13021308Sache
13121308Sache  return streampos(EOF);
13221308Sache
13321308Sache}
13421308Sache
13521308Sacheint gzfilebuf::underflow() {
13621308Sache
13721308Sache  // If the file hasn't been opened for reading, error.
138119610Sache  if ( !is_open() || !(mode & ios::in) )
13921308Sache    return EOF;
14021308Sache
14121308Sache  // if a buffer doesn't exists, allocate one.
14221308Sache  if ( !base() ) {
14321308Sache
14421308Sache    if ( (allocate()) == EOF )
14521308Sache      return EOF;
14621308Sache    setp(0,0);
14721308Sache
14821308Sache  } else {
14921308Sache
15021308Sache    if ( in_avail() )
15121308Sache      return (unsigned char) *gptr();
15221308Sache
15321308Sache    if ( out_waiting() ) {
15421308Sache      if ( flushbuf() == EOF )
15521308Sache        return EOF;
15621308Sache    }
15721308Sache
15821308Sache  }
15921308Sache
16021308Sache  // Attempt to fill the buffer.
16121308Sache
16221308Sache  int result = fillbuf();
16321308Sache  if ( result == EOF ) {
16421308Sache    // disable get area
16521308Sache    setg(0,0,0);
16621308Sache    return EOF;
16721308Sache  }
16821308Sache
16921308Sache  return (unsigned char) *gptr();
170119610Sache
17121308Sache}
172119610Sache
173119610Sacheint gzfilebuf::overflow( int c ) {
174119610Sache
175119610Sache  if ( !is_open() || !(mode & ios::out) )
17621308Sache    return EOF;
17721308Sache
17821308Sache  if ( !base() ) {
17921308Sache    if ( allocate() == EOF )
18021308Sache      return EOF;
18121308Sache    setg(0,0,0);
18221308Sache  } else {
18321308Sache    if (in_avail()) {
18421308Sache        return EOF;
18521308Sache    }
18647558Sache    if (out_waiting()) {
18747558Sache      if (flushbuf() == EOF)
18847558Sache        return EOF;
189119610Sache    }
19047558Sache  }
19175406Sache
19221308Sache  int bl = blen();
193119610Sache  setp( base(), base() + bl);
19421308Sache
19521308Sache  if ( c != EOF ) {
19621308Sache
19721308Sache    *pptr() = c;
19821308Sache    pbump(1);
19947558Sache
20075406Sache  }
20147558Sache
20221308Sache  return 0;
20375406Sache
20421308Sache}
20521308Sache
20621308Sacheint gzfilebuf::sync() {
20721308Sache
20821308Sache  if ( !is_open() )
20921308Sache    return EOF;
21021308Sache
21121308Sache  if ( out_waiting() )
21221308Sache    return flushbuf();
21321308Sache
21475406Sache  return 0;
21575406Sache
21621308Sache}
21721308Sache
21821308Sacheint gzfilebuf::flushbuf() {
219119610Sache
22021308Sache  int n;
22121308Sache  char *q;
22221308Sache
22321308Sache  q = pbase();
22421308Sache  n = pptr() - q;
22521308Sache
22621308Sache  if ( gzwrite( file, q, n) < n )
22721308Sache    return EOF;
22821308Sache
22947558Sache  setp(0,0);
23021308Sache
23121308Sache  return 0;
232119610Sache
23321308Sache}
23421308Sache
23521308Sacheint gzfilebuf::fillbuf() {
23621308Sache
23721308Sache  int required;
23821308Sache  char *p;
23921308Sache
24021308Sache  p = base();
24121308Sache
24221308Sache  required = blen();
24321308Sache
24421308Sache  int t = gzread( file, p, required );
24521308Sache
24621308Sache  if ( t <= 0) return EOF;
24721308Sache
24821308Sache  setg( base(), base(), base()+t);
24975406Sache
25021308Sache  return t;
25121308Sache
25275406Sache}
25321308Sache
25475406Sachegzfilestream_common::gzfilestream_common() :
25521308Sache  ios( gzfilestream_common::rdbuf() )
256119610Sache{ }
257119610Sache
258119610Sachegzfilestream_common::~gzfilestream_common()
259119610Sache{ }
260119610Sache
261119610Sachevoid gzfilestream_common::attach( int fd, int io_mode ) {
262119610Sache
26321308Sache  if ( !buffer.attach( fd, io_mode) )
26421308Sache    clear( ios::failbit | ios::badbit );
26521308Sache  else
26621308Sache    clear();
26721308Sache
26821308Sache}
26921308Sache
270119610Sachevoid gzfilestream_common::open( const char *name, int io_mode ) {
271119610Sache
272119610Sache  if ( !buffer.open( name, io_mode ) )
273119610Sache    clear( ios::failbit | ios::badbit );
274119610Sache  else
275119610Sache    clear();
276119610Sache
277119610Sache}
27821308Sache
27921308Sachevoid gzfilestream_common::close() {
28047558Sache
28147558Sache  if ( !buffer.close() )
28247558Sache    clear( ios::failbit | ios::badbit );
28347558Sache
28447558Sache}
28521308Sache
28621308Sachegzfilebuf *gzfilestream_common::rdbuf()
28721308Sache{
28821308Sache  return &buffer;
28921308Sache}
29021308Sache
291119610Sachegzifstream::gzifstream() :
292119610Sache  ios( gzfilestream_common::rdbuf() )
293119610Sache{
294119610Sache  clear( ios::badbit );
295119610Sache}
29621308Sache
29721308Sachegzifstream::gzifstream( const char *name, int io_mode ) :
29821308Sache  ios( gzfilestream_common::rdbuf() )
29921308Sache{
300119610Sache  gzfilestream_common::open( name, io_mode );
301119610Sache}
302119610Sache
303119610Sachegzifstream::gzifstream( int fd, int io_mode ) :
304119610Sache  ios( gzfilestream_common::rdbuf() )
30521308Sache{
306119610Sache  gzfilestream_common::attach( fd, io_mode );
307119610Sache}
308119610Sache
309119610Sachegzifstream::~gzifstream() { }
310119610Sache
311119610Sachegzofstream::gzofstream() :
312119610Sache  ios( gzfilestream_common::rdbuf() )
313119610Sache{
314119610Sache  clear( ios::badbit );
315119610Sache}
316119610Sache
317119610Sachegzofstream::gzofstream( const char *name, int io_mode ) :
31875406Sache  ios( gzfilestream_common::rdbuf() )
31975406Sache{
32021308Sache  gzfilestream_common::open( name, io_mode );
32121308Sache}
32221308Sache
32321308Sachegzofstream::gzofstream( int fd, int io_mode ) :
32421308Sache  ios( gzfilestream_common::rdbuf() )
32521308Sache{
32621308Sache  gzfilestream_common::attach( fd, io_mode );
32721308Sache}
328119610Sache
329119610Sachegzofstream::~gzofstream() { }
330119610Sache