/* ======================================================================== *\ ! ! * ! * This file is part of MARS, the MAGIC Analysis and Reconstruction ! * Software. It is distributed to you in the hope that it can be a useful ! * and timesaving tool in analysing Data of imaging Cerenkov telescopes. ! * It is distributed WITHOUT ANY WARRANTY. ! * ! * Permission to use, copy, modify and distribute this software and its ! * documentation for any purpose is hereby granted without fee, ! * provided that the above copyright notice appear in all copies and ! * that both that copyright notice and this permission notice appear ! * in supporting documentation. It is provided "as is" without express ! * or implied warranty. ! * ! ! ! Author(s): Thomas Bretz, 12/2005 ! ! Copyright: MAGIC Software Development, 2000-2005 ! ! \* ======================================================================== */ ////////////////////////////////////////////////////////////////////////////// // // MZlib // // This is a C++ wrapper for zlib. // // WARNING: - There might not be support for all features. // - seek calls might be rather slow // ////////////////////////////////////////////////////////////////////////////// #include "MZlib.h" #include // memcpy (UBuntu 8.10) ClassImp(MZlib); using namespace std; // -------------------------------------------------------------------------- // // 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 MZlib::open(const char* name) { if (is_open()) { clear(rdstate()|ios::badbit); return; } fFile = gzopen(name, "rb"); if (fFile == 0) { clear(rdstate()|ios::badbit); return; } } // -------------------------------------------------------------------------- // // Close an open file. // void MZlib::close() { if (!is_open()) return; if (gzclose(fFile) != Z_OK) clear(rdstate()|ios::badbit); fFile = 0; } // -------------------------------------------------------------------------- // // Fill the buffer starting at the current file position and reset buffer // pointers by calling setg // int MZlib::fill_buffer(int iputback) { 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 num; } // -------------------------------------------------------------------------- // // Handle a buffer underflow (buffer went empty) // int MZlib::underflow() { if (gptr() && gptr()(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); if (fill_buffer(iputback)==EOF) return EOF; // return next character return *reinterpret_cast(gptr()); } // -------------------------------------------------------------------------- // # if (__GNUC__>2) streambuf::pos_type MZlib::seekoff(streambuf::off_type offset, ios_base::seekdir dir, ios_base::openmode) # else streampos MZlib::seekoff(streamoff offset, int dir, int) # endif { // Using a switch instead results in: // In member function `virtual std::streampos MZlib::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==ios::cur) { // Position in z-stream const z_off_t zpos = gztell(fFile); //gzseek(fFile, 0, SEEK_CUR); // Calculate future position in streambuffer const char *ptr = gptr()+offset; // Check if the new position will still be in the buffer // In this case the target data was already decompressed. if (ptr=egptr()) return seekpos(zpos+ptr-egptr()); gbump(offset); return zpos+offset; // zpos-blen: Position in z-stream coresponding to buffer position // return seekpos(gztell(fFile)+gptr()-egptr()+offset); } if (dir==ios::beg) return seekpos(offset); /* // 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; } // -------------------------------------------------------------------------- // # if (__GNUC__>2) streambuf::pos_type MZlib::seekpos(streambuf::pos_type pos, ios_base::openmode) # else streampos MZlib::seekpos(streampos pos, int) # endif { // Seek the z-stream to the given position if (gzseek(fFile, pos, SEEK_SET)<0) return EOF; // Fill buffer if (fill_buffer()==EOF) return EOF; return pos; }