diff options
-rw-r--r-- | include/Handle.h | 4 | ||||
-rw-r--r-- | lib/Handle.cc | 71 |
2 files changed, 68 insertions, 7 deletions
diff --git a/include/Handle.h b/include/Handle.h index 1a3973d..23ecfe6 100644 --- a/include/Handle.h +++ b/include/Handle.h @@ -37,6 +37,7 @@ class Handle : public Base { virtual bool CanWatch() const; virtual int Dup() const; virtual void SetZ(int = 9) throw (GeneralException); + virtual void Flush(); protected: Handle(int h); int GetHandle() const; @@ -47,7 +48,8 @@ class Handle : public Base { int h; bool closed, nonblock; gzFile zfile; - int z; + zstream zstrm; + int z, c; }; Handle & operator<<(Handle &, const String &); diff --git a/lib/Handle.cc b/lib/Handle.cc index e3ed198..7bd9e37 100644 --- a/lib/Handle.cc +++ b/lib/Handle.cc @@ -20,6 +20,10 @@ #include "Handle.h" #include "gettext.h" +enum { + DEFLATE, INFLATE; +} + Handle::Handle(const Handle & nh) : itell(0), h(nh.h >= 0 ? dup(nh.h) : nh.h), closed(nh.closed), nonblock(nh.closed), zfile(0), z(0) { #ifdef DEBUG @@ -184,8 +188,27 @@ void Handle::close() throw (GeneralException) { return; } + Flush(); + if (h >= 0) { - if (z) { + if (z >= 10) { + int err; + if (c == DEFLATE) { + err = deflateEnd(&zstrm); + if (err != Z_OK) { + throw (String(_("Error during deflateEnd: ")) + zstrm.msg); + } + } else { + err = inflateEnd(&zstrm); + if (err != Z_OK) { + throw (String(_("Error during inflateEnd: ")) + zstrm.msg); + } + } + err = ::close(h); + if (err) { + throw GeneralException(String(_("Error during (zstream) close: ")) + strerror(errno)); + } + } else if (z) { #ifdef DEBUG std::cerr << "Performing gzclose on handle " << h << std::endl; #endif @@ -248,7 +271,29 @@ void Handle::SetZ(int az) throw (GeneralException) { if (h < 0) { throw GeneralException(_("Can't SetZ a virtual Handle.")); } - if (az) { + if (az >= 10) { +#ifdef DEBUG + std::cerr << "Setting up zstream using inflate/deflate...\n"; +#endif + int err; + zstrm.zalloc = Z_NULL; + zstrm.zfree = Z_NULL; + if (CanWrite()) { + c = DEFLATE; + err = deflateInit(&zstrm, az - 10); + if (err != Z_OK) { + throw GeneralException(String(_("Error in deflateInit: ")) + zstrm.msg); + } + } else { + c = INFLATE; + zstrm.next_in = 0; + zstrm.avail_in = 0; + err = inflateInit(&zstrm); + if (err != Z_OK) { + throw GeneralException(String(_("Error in inflateInit: ")) + zstrm.msg); + } + } + } else if (az) { char format[4]; int index = 0; if (CanRead()) { @@ -270,8 +315,8 @@ void Handle::SetZ(int az) throw (GeneralException) { } ssize_t Handle::uwrite(const void * buf, size_t count) throw (GeneralException) { - if (z) { - itell += count; + if (z >= 10) { + } else if (z) { #ifdef FULLDEBUG std::cerr << "Performing gzwrite of " << count << " byte for handle " << h << std::endl; #endif @@ -288,6 +333,7 @@ ssize_t Handle::uwrite(const void * buf, size_t count) throw (GeneralException) throw GeneralException(String(_("Error in zlib during gzwrite: ")) + m); } } + itell += err; return err; } else { itell += count = ::write(h, buf, count); @@ -296,8 +342,8 @@ ssize_t Handle::uwrite(const void * buf, size_t count) throw (GeneralException) } ssize_t Handle::uread(void * buf, size_t count) { - if (z) { - itell += count; + if (z >= 10) { + } if (z) { #ifdef DEBUG std::cerr << "Performing gzread of " << count << " byte for handle " << h << std::endl; #endif @@ -310,6 +356,7 @@ ssize_t Handle::uread(void * buf, size_t count) { return 0; } } + itell += err; return err; } else { itell += count = ::read(h, buf, count); @@ -398,3 +445,15 @@ void copy(Handle * s, Handle * d, ssize_t size) { d->write(&c, 1); } } + +void Handle::Flush() { + if (h < 0) + return; + if (z >= 10) { + + } else if (z) { + gzflush(z); + } else { + fsync(h); + } +} |