00001
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00033
00034 #ifndef GROOVX_RUTZ_GZSTREAMBUF_CC_UTC20050626084020_DEFINED
00035 #define GROOVX_RUTZ_GZSTREAMBUF_CC_UTC20050626084020_DEFINED
00036
00037 #include "rutz/gzstreambuf.h"
00038
00039 #include "rutz/error.h"
00040 #include "rutz/fstring.h"
00041 #include "rutz/sfmt.h"
00042 #include "rutz/shared_ptr.h"
00043
00044 #include <fstream>
00045
00046 #include "rutz/trace.h"
00047
00048 using rutz::fstring;
00049 using rutz::shared_ptr;
00050
00051 rutz::gzstreambuf::gzstreambuf(const char* name, int om,
00052 bool throw_exception)
00053 :
00054 m_opened(false),
00055 m_mode(0),
00056 m_gzfile(0)
00057 {
00058
00059 if ( (om & std::ios::ate) || (om & std::ios::app)
00060 || ((om & std::ios::in) && (om & std::ios::out)) )
00061 {
00062 ;
00063 }
00064 else
00065 {
00066 char fmode[10];
00067 char* fmodeptr = fmode;
00068
00069 if (om & std::ios::in)
00070 {
00071 *fmodeptr++ = 'r';
00072 setg(m_buf+s_pback_size,
00073 m_buf+s_pback_size,
00074 m_buf+s_pback_size);
00075 }
00076 else if (om & std::ios::out)
00077 {
00078 *fmodeptr++ = 'w';
00079 setp(m_buf, m_buf+(s_buf_size-1));
00080 }
00081
00082 *fmodeptr++ = 'b';
00083 *fmodeptr = '\0';
00084
00085 m_gzfile = gzopen(name,fmode);
00086
00087 if (m_gzfile != NULL)
00088 {
00089 m_opened = true;
00090 m_mode = om;
00091 }
00092 }
00093
00094 if (throw_exception && !m_opened)
00095 {
00096 if (om & std::ios::in)
00097 {
00098 throw rutz::error(rutz::sfmt("couldn't open file '%s' "
00099 "for reading", name), SRC_POS);
00100 }
00101 else if (om & std::ios::out)
00102 {
00103 throw rutz::error(rutz::sfmt("couldn't open file '%s' "
00104 "for writing", name), SRC_POS);
00105 }
00106 }
00107 }
00108
00109 void rutz::gzstreambuf::close()
00110 {
00111 if (m_opened)
00112 {
00113 sync();
00114 m_opened = false;
00115 gzclose(m_gzfile);
00116 }
00117 }
00118
00119 int rutz::gzstreambuf::underflow()
00120 {
00121 GVX_TRACE("rutz::gzstreambuf::underflow");
00122
00123 if (gptr() < egptr())
00124 return *gptr();
00125
00126 int numPutback = 0;
00127 if (s_pback_size > 0)
00128 {
00129
00130
00131
00132 numPutback = gptr() - eback();
00133 if (numPutback > 4)
00134 numPutback = 4;
00135
00136
00137
00138 std::memcpy (m_buf+(4-numPutback), gptr()-numPutback,
00139 numPutback);
00140 }
00141
00142
00143 const int num =
00144 gzread(m_gzfile, m_buf+s_pback_size, s_buf_size-s_pback_size);
00145
00146 if (num <= 0)
00147 return EOF;
00148
00149
00150 setg (m_buf+s_pback_size-numPutback,
00151 m_buf+s_pback_size,
00152 m_buf+s_pback_size+num);
00153
00154
00155
00156
00157
00158
00159 return static_cast<unsigned char>(*gptr());
00160 }
00161
00162 int rutz::gzstreambuf::overflow(int c)
00163 {
00164 GVX_TRACE("rutz::gzstreambuf::overflow");
00165 if (!(m_mode & std::ios::out) || !m_opened) return EOF;
00166
00167 if (c != EOF)
00168 {
00169
00170 *pptr() = c;
00171 pbump(1);
00172 }
00173
00174 if (flushoutput() == EOF)
00175 {
00176 return -1;
00177 }
00178
00179 return c;
00180 }
00181
00182 int rutz::gzstreambuf::sync()
00183 {
00184 if (flushoutput() == EOF)
00185 {
00186 return -1;
00187 }
00188 return 0;
00189 }
00190
00191 int rutz::gzstreambuf::flushoutput()
00192 {
00193 if (!(m_mode & std::ios::out) || !m_opened) return EOF;
00194
00195 int num = pptr()-pbase();
00196 if ( gzwrite(m_gzfile, pbase(), num) != num )
00197 {
00198 return EOF;
00199 }
00200
00201 pbump(-num);
00202 return num;
00203 }
00204
00205 namespace
00206 {
00207 class gzstream : public std::iostream
00208 {
00209 private:
00210 rutz::gzstreambuf m_buf;
00211 public:
00212 gzstream(const char* filename_cstr,
00213 std::ios::openmode mode,
00214 bool throw_exception)
00215 :
00216 std::iostream(0),
00217 m_buf(filename_cstr, mode, throw_exception)
00218 {
00219 rdbuf(&m_buf);
00220 }
00221 };
00222 }
00223
00224 shared_ptr<std::ostream> rutz::ogzopen(const fstring& filename,
00225 std::ios::openmode flags)
00226 {
00227 static fstring gz_ext(".gz");
00228
00229 if (filename.ends_with(gz_ext))
00230 {
00231 return shared_ptr<std::ostream>
00232 (new gzstream(filename.c_str(), std::ios::out|flags, true));
00233 }
00234 else
00235 {
00236 shared_ptr<std::ostream> result =
00237 make_shared(new std::ofstream(filename.c_str(), flags));
00238 if (result->fail())
00239 throw rutz::error(rutz::sfmt("couldn't open file '%s' "
00240 "for writing", filename.c_str()),
00241 SRC_POS);
00242
00243 return result;
00244 }
00245 }
00246
00247 shared_ptr<std::ostream> rutz::ogzopen(const char* filename,
00248 std::ios::openmode flags)
00249 {
00250 return ogzopen(fstring(filename), flags);
00251 }
00252
00253 shared_ptr<std::istream> rutz::igzopen(const char* filename,
00254 std::ios::openmode flags)
00255 {
00256 return shared_ptr<std::iostream>
00257 (new gzstream(filename, std::ios::in|flags, true));
00258 }
00259
00260 shared_ptr<std::istream> rutz::igzopen(const fstring& filename,
00261 std::ios::openmode flags)
00262 {
00263 return igzopen(filename.c_str(), flags);
00264 }
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294 static const char __attribute__((used)) vcid_groovx_rutz_gzstreambuf_cc_utc20050626084020[] = "$Id: gzstreambuf.cc 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00295 #endif // !GROOVX_RUTZ_GZSTREAMBUF_CC_UTC20050626084020_DEFINED