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