00001 #ifndef moses_gzfile_buf_h
00002 #define moses_gzfile_buf_h
00003
00004 #include <stdexcept>
00005 #include <streambuf>
00006 #include <zlib.h>
00007 #include <cstring>
00008
00012 class gzfilebuf : public std::streambuf
00013 {
00014 public:
00015 gzfilebuf(const char *filename) {
00016 _gzf = gzopen(filename, "rb");
00017 if (!_gzf)
00018 throw std::runtime_error("Could not open " + std::string(filename) + ".");
00019 setg (_buff+sizeof(int),
00020 _buff+sizeof(int),
00021 _buff+sizeof(int));
00022 }
00023 ~gzfilebuf() {
00024 gzclose(_gzf);
00025 }
00026 protected:
00027 virtual int_type overflow (int_type ) {
00028 throw;
00029 }
00030
00031
00032 virtual
00033 std::streamsize xsputn (const char* ,
00034 std::streamsize ) {
00035 throw;
00036 }
00037
00038 virtual std::streampos seekpos ( std::streampos , std::ios_base::openmode ) {
00039 throw;
00040 }
00041
00042
00043 virtual int_type underflow () {
00044
00045 if (gptr() < egptr()) {
00046 return traits_type::to_int_type(*gptr());
00047 }
00048
00049
00050
00051
00052
00053 unsigned int numPutback = gptr() - eback();
00054 if (numPutback > sizeof(int)) {
00055 numPutback = sizeof(int);
00056 }
00057
00058
00059
00060
00061 std::memmove (_buff+(sizeof(int)-numPutback), gptr()-numPutback,
00062 numPutback);
00063
00064
00065 int num = gzread(_gzf, _buff+sizeof(int), _buffsize-sizeof(int));
00066 if (num <= 0) {
00067
00068 return EOF;
00069 }
00070
00071
00072 setg (_buff+(sizeof(int)-numPutback),
00073 _buff+sizeof(int),
00074 _buff+sizeof(int)+num);
00075
00076
00077 return traits_type::to_int_type(*gptr());
00078 }
00079
00080 std::streamsize xsgetn (char* s,
00081 std::streamsize num) {
00082 return gzread(_gzf,s,num);
00083 }
00084
00085 private:
00086 gzFile _gzf;
00087 static const unsigned int _buffsize = 1024;
00088 char _buff[_buffsize];
00089 };
00090
00091 #endif