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