Index: /trunk/Mars/mbase/izstream.h
===================================================================
--- /trunk/Mars/mbase/izstream.h	(revision 11550)
+++ /trunk/Mars/mbase/izstream.h	(revision 11551)
@@ -1,7 +1,12 @@
-#ifndef MARS_MZlib
-#define MARS_MZlib
+#ifndef MARS_izstream
+#define MARS_izstream
 
+#include <istream>
+#include <streambuf>
+
+#ifdef __MARS__
 #ifndef ROOT_TObject
 #include <TObject.h> // Needed for ClassDef
+#endif
 #endif
 
@@ -12,7 +17,5 @@
 #endif
 
-#include <istream>  // base classes for MLog
-
-class MZlib : public std::streambuf, public std::istream
+class izstream : public std::streambuf, public std::istream
 {
 private:
@@ -22,34 +25,151 @@
     char   fBuffer[fgBufferSize]; // data buffer
 
-    int underflow();
+    int underflow()
+    {
+        if (gptr() && gptr()<egptr())
+            return * reinterpret_cast<unsigned char *>(gptr());
+
+        if (!is_open())
+            return EOF;
+
+        // gptr()-eback(): if more than four bytes are already flushed
+        const int iputback = gptr()-eback()>4 ? 4 : gptr()-eback();
+
+        // Copy the last four bytes flushed into the putback area
+        memcpy(fBuffer+(4-iputback), gptr()-iputback, iputback);
+
+        // Fill the buffer starting at the current file position and reset buffer
+        // pointers by calling setg
+        const int num = gzread(fFile, fBuffer+4, fgBufferSize-4);
+        if (num <= 0) // ERROR or EOF
+            return EOF;
+
+        // reset buffer pointers
+        setg(fBuffer+(4-iputback), fBuffer+4, fBuffer+4+num);
+
+        // return next character
+        return *reinterpret_cast<unsigned char *>(gptr());
+    }
+
 
 public:
-    MZlib() : istream(this), fFile(0)
+    izstream() : std::istream(this), fFile(0)
     {
         setg(fBuffer+4, fBuffer+4, fBuffer+4);
     }
-    MZlib(const char *name) : istream(this), fFile(0)
+    izstream(const char *name) : std::istream(this), fFile(0)
     {
         setg(fBuffer+4, fBuffer+4, fBuffer+4);
         open(name);
     }
-    ~MZlib() { MZlib::close(); }
+    ~izstream() { izstream::close(); }
 
     int is_open() { return fFile!=0; }
 
-    void open(const char* name);
-    void close();
+    // --------------------------------------------------------------------------
+    //
+    // Open a file by name. Test if it is open like for an ifstream
+    // It doesn't matter whether the file is gzip compressed or not.
+    //
+    void open(const char* name)
+    {
+        if (is_open())
+        {
+            clear(rdstate()|std::ios::failbit);
+            return;
+        }
 
-# if (__GNUC__>2)
-    std::streambuf::pos_type seekoff(std::streambuf::off_type, std::ios_base::seekdir,
-                                     std::ios_base::openmode = std::ios_base::in);
-    std::streambuf::pos_type seekpos(std::streambuf::pos_type,
-                                     std::ios_base::openmode = std::ios_base::in);
-# else
-    std::streampos seekoff(std::streamoff, int, int = std::ios::in);
-//    std::streampos seekpos(std::streampos, int = std::ios::in);
-# endif
+        fFile = gzopen(name, "rb");
+        if (fFile == 0)
+        {
+            clear(rdstate()|std::ios::failbit);
+            return;
+        }
+    }
+    // --------------------------------------------------------------------------
+    //
+    // Close an open file.
+    //
+    void close()
+    {
+        if (!is_open())
+            return;
 
-    ClassDef(MZlib, 0) // A C++ wrapper to istream zlib files
+        if (gzclose(fFile) != Z_OK)
+            clear(rdstate()|std::ios::failbit);
+
+        fFile = 0;
+    }
+
+    std::streambuf::pos_type seekoff(std::streambuf::off_type offset, std::ios_base::seekdir dir,
+                                     std::ios_base::openmode = std::ios_base::in)
+    {
+        // Using a switch instead results in:
+        //  In member function `virtual std::streampos izstream::seekoff(long int, std::_Ios_Seekdir, std::_Ios_Openmode)':
+        //  warning: enumeration value `_M_ios_seekdir_end' not handled in switch
+        //  warning: case value `0' not in enumerated type `_Ios_Seekdir'
+        //  warning: case value `1' not in enumerated type `_Ios_Seekdir'
+        //  warning: case value `2' not in enumerated type `_Ios_Seekdir'
+
+        if (dir==std::ios::end)
+        {
+            clear(rdstate()|std::ios::failbit);
+            return EOF;
+        }
+
+        // We only do relative seeking to avoid unnecessary decompression
+        // of the whole file
+        if (dir==std::ios::beg)
+            offset -= tellg();
+
+        // Calculate future position in streambuffer
+        const char *ptr = gptr()+offset;
+
+        // This is the number of bytes still available in the buffer
+        const size_t sbuf = egptr()-gptr();
+
+        // Check if the new position will still be in the buffer
+        // In this case the target data was already decompressed.
+        if (ptr>=eback() && ptr<egptr())
+        {
+            // Absolute position in z-stream
+            const z_off_t zpos = gztell(fFile)-sbuf; //gzseek(fFile, 0, SEEK_CUR);
+
+            gbump(offset);
+
+            return zpos+offset;
+        }
+
+        const streampos pos = gzseek(fFile, offset-sbuf, SEEK_CUR);
+
+        // Buffer is empty - force refilling
+        setg(fBuffer+4, fBuffer+4, fBuffer+4);
+
+        return pos<0 ? streampos(EOF) : pos;
+
+        /*
+         // SEEK_END not supported by zlib
+         if (dir==ios::end)
+         {
+             // Position in z-stream
+             const z_off_t zpos = gzseek(fFile, offset, SEEK_END);
+             if (zpos<0)
+                 return EOF;
+
+             return fill_buffer()==EOF ? EOF : zpos;
+         }
+         */
+        return EOF;
+    }
+
+    std::streambuf::pos_type seekpos(std::streambuf::pos_type pos,
+                                     std::ios_base::openmode = std::ios_base::in)
+    {
+        return seekoff(pos, std::ios::beg);
+    }
+
+#ifdef __MARS__
+    ClassDef(izstream, 0) // A C++ wrapper to istream zlib files
+#endif
 };
 
