A C++ wrapper class for the zlib
The zlib compression library
The zlib library is lossless data-compression library written in C (for more informatio, see the zlib Home Page). The zlib is related to gzip.
As a C++ user, I thought it would be nice to use the zlib thru the iostream interface. I didn't have enough to wrap perfectly the zlib facilities, so I used zlib's high level interface.
The izipstream and ozipstream classes below can be used as regular iostreams. They work fine with the HPUX HP C++ compiler 10.22 (based on cfront). The last version of zlib working with HPUX 10 can be found in The HP-UX Porting and Archive Centre.
Code
Header: file zipiostream.h
/*
wrapping the zlib with iostream using gzFile
setbuf NYI
Jean-Louis Ardoint 1996
*/
#include
#include
class zipstreambuf : public streambuf
{
public:
static const int openprot;
private:
char opened;
int mode;
gzFile file;
public:
zipstreambuf() { opened = 0; }
int is_open() { return opened; }
zipstreambuf* open(const char * name, int om);
zipstreambuf* close();
~zipstreambuf() { close(); }
virtual int overflow(int=EOF);
virtual int underflow();
virtual int sync() ;
/* NYI
virtual streambuf*
setbuf(char* p, int len) ;
*/
};
class zipstreambase : virtual public ios
{
zipstreambuf buf;
public:
zipstreambase() {init(&buf);}
zipstreambase(const char* name,
int mode);
~zipstreambase();
void open(const char* name, int mode);
void close();
// NYI void setbuf(char* p, int l);
zipstreambuf* rdbuf() { return &buf; }
};
class izipstream : public zipstreambase, public istream
{
public:
izipstream() {}
izipstream(const char* name,
int mode=ios::in)
: zipstreambase(name,mode) {}
zipstreambuf* rdbuf() {return zipstreambase::rdbuf(); }
void open(const char* name)
{zipstreambase::open(name,ios::in);}
};
class ozipstream : public zipstreambase, public ostream
{
public:
ozipstream() {}
ozipstream(const char* name,
int mode=ios::out)
: zipstreambase(name,mode) {}
zipstreambuf* rdbuf() {return zipstreambase::rdbuf(); }
void open(const char* name)
{zipstreambase::open(name,ios::out);}
};
Body: file zipiostream.cc
#include
zipstreambuf* zipstreambuf::open(const char* name, int om)
{
if (is_open())
return (zipstreambuf*)0;
mode = om;
// no append nor read/write mode
if ((mode & ios::ate) || (mode & ios::app)
|| ((mode & ios::in) && (mode & ios::out)))
return (zipstreambuf*)0;
char fmode[10];
char * fmodeptr = fmode;
if (mode & ios::in)
{
*fmodeptr++ = 'r';
}
else if (mode & ios::out)
*fmodeptr++ = 'w';
*fmodeptr++ = 'b';
*fmodeptr = '\0';
file = gzopen(name,fmode);
if (file == NULL)
return (zipstreambuf*)0;
opened = 1;
return this;
}
zipstreambuf * zipstreambuf::close()
{
if (opened)
{
sync();
opened = 0;
if (gzclose(file) == Z_OK)
return this;
}
return (zipstreambuf*)0;
}
int zipstreambuf::underflow()
{
if (gptr() && gptr() < egptr()) return zapeof(*gptr());
if (!(mode&ios::in) || !opened || allocate()==EOF) return EOF;
int count = gzread(file,base(),blen());
if (count < 1)
{
setg(0,0,0);
return EOF;
}
setg(base(),base(),base()+count);
return zapeof(*base());
}
int zipstreambuf::overflow(int c)
{
if (!(mode&ios::out) || !opened || allocate()==EOF) return EOF;
if (gptr() && egptr() > gptr())
return EOF;
setg(0,0,0);
// make sure there is a put area
if (!pptr()) setp(base(),base());
int w = pptr() -pbase();
if (c != EOF)
{
*pptr() = c;
++w;
}
if (gzwrite(file,pbase(),w))
{
setp(base(),ebuf()-1);
return zapeof(c);
}
setp(0,0);
return EOF;
}
int zipstreambuf::sync()
{
if (gptr() && egptr() > gptr())
return EOF;
if (pptr() && pptr() > pbase())
return overflow(EOF);
return 0;
}
// CLASS zipstreambase
zipstreambase::zipstreambase(const char* name, int mode)
{
init(&buf);
open(name,mode);
}
zipstreambase::~zipstreambase()
{
if(buf.is_open())
buf.close();
}
void zipstreambase::open(const char* name, int mode)
{
if (!buf.open(name,mode))
clear(rdstate() & ios::badbit);
}
void zipstreambase::close()
{
if (buf.is_open())
if (!buf.close())
clear(rdstate() & ios::badbit);
}
Back to my homepage
Last modified Feb 21, 1997
This page hosted by
Get your own Free Home Page