00001
00013 #include <iostream>
00014 #include <zlib.h>
00015
00016 #ifndef __ZIPIOSTREAM_H__
00017 #define __ZIPIOSTREAM_H__
00018
00019
00024 #define zapeof(c) ((c)&0377)
00025
00026
00027 class zipstreambuf : public streambuf
00028 {
00029 public:
00030 static const int openprot;
00031 private:
00032 char opened;
00033 int mode;
00034 gzFile file;
00035 public:
00036 zipstreambuf() { opened = 0; }
00037 int is_open() const { return opened; }
00038
00039
00040 zipstreambuf* open(const char * name, int om) {
00041 if (is_open())
00042 return (zipstreambuf*)0;
00043
00044 mode = om;
00045
00046 if ((mode & ios::ate) || (mode & ios::app)
00047 || ((mode & ios::in) && (mode & ios::out)))
00048 return (zipstreambuf*)0;
00049
00050 char fmode[10];
00051 char * fmodeptr = fmode;
00052 if (mode & ios::in)
00053 {
00054 *fmodeptr++ = 'r';
00055 }
00056 else if (mode & ios::out)
00057 *fmodeptr++ = 'w';
00058 *fmodeptr++ = 'b';
00059 *fmodeptr = '\0';
00060
00061 file = gzopen(name,fmode);
00062 if (file == NULL)
00063 return (zipstreambuf*)0;
00064
00065 opened = 1;
00066 return this;
00067 }
00068
00069
00070 zipstreambuf* close() {
00071 if (opened)
00072 {
00073 sync();
00074 opened = 0;
00075 if (gzclose(file) == Z_OK)
00076 return this;
00077 }
00078 return (zipstreambuf*)0;
00079 }
00080
00081
00082 ~zipstreambuf() { close(); }
00083
00084 virtual int overflow(int c=EOF) {
00085
00086 if (!(mode&ios::out) || !opened || allocate()==EOF) return EOF;
00087 if (gptr() && egptr() > gptr())
00088 return EOF;
00089
00090 setg(0,0,0);
00091
00092
00093 if (!pptr()) setp(base(),base());
00094
00095 int w = pptr() -pbase();
00096
00097 if (c != EOF)
00098 {
00099 *pptr() = c;
00100 ++w;
00101 }
00102
00103 if (gzwrite(file,pbase(),w))
00104 {
00105 setp(base(),ebuf()-1);
00106 return zapeof(c);
00107 }
00108
00109 setp(0,0);
00110 return EOF;
00111 }
00112
00113
00114 virtual int underflow() {
00115 if (gptr() && gptr() < egptr()) return zapeof(*gptr());
00116
00117 if (!(mode&ios::in) || !opened || allocate()==EOF) return EOF;
00118
00119 int count = gzread(file,base(),blen());
00120 if (count < 1)
00121 {
00122 setg(0,0,0);
00123 return EOF;
00124 }
00125 setg(base(),base(),base()+count);
00126 return zapeof(*base());
00127 }
00128
00129
00130
00131 virtual int sync() {
00132 if (gptr() && egptr() > gptr())
00133 return EOF;
00134 if (pptr() && pptr() > pbase())
00135 return overflow(EOF);
00136
00137 return 0;
00138 }
00139
00140
00141
00142
00143
00144 };
00145
00146
00147
00148 class zipstreambase : virtual public ios
00149 {
00150 zipstreambuf buf;
00151 public:
00152 zipstreambase() {init(&buf);}
00153 zipstreambase(const char* name, int mode) {
00154 init(&buf);
00155 open(name,mode);
00156 }
00157 ~zipstreambase() {
00158 if(buf.is_open())
00159 buf.close();
00160 }
00161
00162 void open(const char* name, int mode){
00163 if (!buf.open(name,mode))
00164 clear(rdstate() & ios::badbit);
00165 }
00166
00167 void close(){
00168 if (buf.is_open())
00169 if (!buf.close())
00170 clear(rdstate() & ios::badbit);
00171 }
00172
00175 inline operator bool() const { return buf.is_open(); }
00176 inline bool operator!() const { return !buf.is_open(); }
00177
00178
00179 zipstreambuf* rdbuf() { return &buf; }
00180 };
00181
00182
00183
00184 class izipstream : public zipstreambase, public istream
00185 {
00186 public:
00187 izipstream() {}
00188 izipstream(const char* name,
00189 int mode=ios::in)
00190 : zipstreambase(name,mode) {}
00191
00192 zipstreambuf* rdbuf() {return zipstreambase::rdbuf(); }
00193 void open(const char* name)
00194 {zipstreambase::open(name,ios::in);}
00195 };
00196
00197
00198
00199 class ozipstream : public zipstreambase, public ostream
00200 {
00201 public:
00202 ozipstream() {}
00203 ozipstream(const char* name,
00204 int mode=ios::out)
00205 : zipstreambase(name,mode) {}
00206
00207 zipstreambuf* rdbuf() {return zipstreambase::rdbuf(); }
00208 void open(const char* name)
00209 {zipstreambase::open(name,ios::out);}
00210 };
00211
00212
00213 #endif