Changeset 12255


Ignore:
Timestamp:
10/25/11 13:49:11 (13 years ago)
Author:
neise
Message:
i know its wrong ... but i can't work without these files...
Location:
fact/tools/rootmacros
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • fact/tools/rootmacros/fits.h

    r12200 r12255  
    1 #error Please replace fits.h with https://fact.isdc.unige.ch/svn/trunk/Mars/mcore/fits.h
     1#ifndef MARS_fits
     2#define MARS_fits
     3
     4#include <stdint.h>
     5
     6#include <map>
     7#include <string>
     8#include <sstream>
     9#include <algorithm>
     10
     11#ifdef __EXCEPTIONS
     12#include <stdexcept>
     13#endif
     14
     15#ifdef __CINT__
     16#define off_t size_t
     17#endif
     18
     19#ifndef __MARS__
     20#include <vector>
     21#include <iomanip>
     22#include <iostream>
     23#define gLog cerr
     24#define err ""
     25#define all ""
     26#else
     27#include "MLog.h"
     28#include "MLogManip.h"
     29#endif
     30
     31#ifdef HAVE_ZLIB
     32#include "izstream.h"
     33#else
     34#include <fstream>
     35#define izstream ifstream
     36#warning Support for zipped FITS files disabled.
     37#endif
     38
     39namespace std
     40{
     41
     42class fits : public izstream
     43{
     44public:
     45    struct Entry
     46    {
     47        char   type;
     48        string value;
     49        string comment;
     50
     51        template<typename T>
     52            T Get() const
     53        {
     54            T t;
     55
     56            istringstream str(value);
     57            str >> t;
     58
     59            return t;
     60        }
     61    };
     62
     63    struct Table
     64    {
     65        off_t offset;
     66
     67        string name;
     68        size_t bytes_per_row;
     69        size_t num_rows;
     70        size_t num_cols;
     71
     72        struct Column
     73        {
     74            size_t offset;
     75            size_t num;
     76            size_t size;
     77            char   type;
     78            string unit;
     79        };
     80
     81        typedef map<string, Entry>  Keys;
     82        typedef map<string, Column> Columns;
     83
     84        Columns cols;
     85        Keys    keys;
     86
     87        string Trim(const string &str, char c=' ') const
     88        {
     89            // Trim Both leading and trailing spaces
     90            const size_t pstart = str.find_first_not_of(c); // Find the first character position after excluding leading blank spaces
     91            const size_t pend   = str.find_last_not_of(c);  // Find the first character position from reverse af
     92
     93            // if all spaces or empty return an empty string
     94            if (string::npos==pstart || string::npos==pend)
     95                return string();
     96
     97            return str.substr(pstart, pend-pstart+1);
     98        }
     99
     100        bool Check(const string &key, char type, const string &value="") const
     101        {
     102            const Keys::const_iterator it = keys.find(key);
     103            if (it==keys.end())
     104            {
     105                ostringstream str;
     106                str << "Key '" << key << "' not found.";
     107#ifdef __EXCEPTIONS
     108                throw runtime_error(str.str());
     109#else
     110                gLog << err << "ERROR - " << str.str() << endl;
     111                return false;
     112#endif
     113            }
     114
     115            if (it->second.type!=type)
     116            {
     117                ostringstream str;
     118                str << "Wrong type for key '" << key << "': expected " << type << ", found " << it->second.type << ".";
     119#ifdef __EXCEPTIONS
     120                throw runtime_error(str.str());
     121#else
     122                gLog << err << "ERROR - " << str.str() << endl;
     123                return false;
     124#endif
     125            }
     126
     127            if (!value.empty() && it->second.value!=value)
     128            {
     129                ostringstream str;
     130                str << "Wrong value for key '" << key << "': expected " << value << ", found " << it->second.value << ".";
     131#ifdef __EXCEPTIONS
     132                throw runtime_error(str.str());
     133#else
     134                gLog << err << "ERROR - " << str.str() << endl;
     135                return false;
     136#endif
     137            }
     138
     139            return true;
     140        }
     141
     142        Keys ParseBlock(const vector<string> &vec) const
     143        {
     144            map<string,Entry> rc;
     145
     146            for (unsigned int i=0; i<vec.size(); i++)
     147            {
     148                const string key = Trim(vec[i].substr(0,8));
     149                // Keywords without a value, like COMMENT / HISTORY
     150                if (vec[i].substr(8,2)!="= ")
     151                    continue;
     152
     153                char type = 0;
     154
     155                string com;
     156                string val = Trim(vec[i].substr(10));
     157                if (val[0]=='\'')
     158                {
     159                    // First skip all '' in the string
     160                    size_t p = 1;
     161                    while (1)
     162                    {
     163                        const size_t pp = val.find_first_of('\'', p);
     164                        if (pp==string::npos)
     165                            break;
     166
     167                        p = val[pp+1]=='\'' ? pp+2 : pp+1;
     168                    }
     169
     170                    // Now find the comment
     171                    const size_t ppp = val.find_first_of('/', p);
     172
     173                    // Set value, comment and type
     174                    com  = ppp==string::npos ? "" : Trim(val.substr(ppp+1));
     175                    val  = Trim(val.substr(1, p-2));
     176                    type = 'T';
     177                }
     178                else
     179                {
     180                    const size_t p = val.find_first_of('/');
     181
     182                    com = Trim(val.substr(p+2));
     183                    val = Trim(val.substr(0, p));
     184
     185                    if (val.empty() || val.find_first_of('T')!=string::npos || val.find_first_of('F')!=string::npos)
     186                        type = 'B';
     187                    else
     188                        type = val.find_last_of('.')==string::npos ? 'I' : 'F';
     189                }
     190
     191                const Entry e = { type, val, com };
     192                rc[key] = e;
     193            }
     194
     195            return rc;
     196        }
     197
     198        Table() : offset(0) { }
     199        Table(const vector<string> &vec, off_t off) :
     200            offset(off), keys(ParseBlock(vec))
     201        {
     202            if (!Check("XTENSION", 'T', "BINTABLE") ||
     203                !Check("NAXIS",    'I', "2")        ||
     204                !Check("BITPIX",   'I', "8")        ||
     205                !Check("PCOUNT",   'I', "0")        ||
     206                !Check("GCOUNT",   'I', "1")        ||
     207                !Check("EXTNAME",  'T')             ||
     208                !Check("NAXIS1",   'I')             ||
     209                !Check("NAXIS2",   'I')             ||
     210                !Check("TFIELDS",  'I'))
     211                return;
     212
     213            bytes_per_row = Get<size_t>("NAXIS1");
     214            num_rows      = Get<size_t>("NAXIS2");
     215            num_cols      = Get<size_t>("TFIELDS");
     216
     217            size_t bytes = 0;
     218            for (size_t i=1; i<=num_cols; i++)
     219            {
     220                ostringstream num;
     221                num << i;
     222
     223                if (!Check("TTYPE"+num.str(), 'T') ||
     224                    !Check("TFORM"+num.str(), 'T'))
     225                    return;
     226
     227                const string id   = Get<string>("TTYPE"+num.str());
     228                const string fmt  = Get<string>("TFORM"+num.str());
     229                const string unit = Get<string>("TUNIT"+num.str(), "");
     230
     231                istringstream sin(fmt);
     232                int n = 0;
     233                sin >> n;
     234                if (!sin)
     235                    n = 1;
     236
     237                const char type = fmt[fmt.length()-1];
     238
     239                size_t size = 0;
     240                switch (type)
     241                {
     242                    // We could use negative values to mark floats
     243                    // otheriwse we could just cast them to int64_t?
     244                case 'L': size = 1; break; // logical
     245                // case 'X': size = n; break; // bits (n=number of bytes needed to contain all bits)
     246                case 'B': size = 1; break; // byte
     247                case 'I': size = 2; break; // short
     248                case 'J': size = 4; break; // int
     249                case 'K': size = 8; break; // long long
     250                case 'E': size = 4; break; // float
     251                case 'D': size = 8; break; // double
     252                // case 'C': size =  8; break; // complex float
     253                // case 'M': size = 16; break; // complex double
     254                // case 'P': size =  8; break; // array descriptor (32bit)
     255                // case 'Q': size = 16; break; // array descriptor (64bit)
     256                default:
     257                    {
     258                        ostringstream str;
     259                        str << "FITS format TFORM='" << fmt << "' not yet supported.";
     260#ifdef __EXCEPTIONS
     261                        throw runtime_error(str.str());
     262#else
     263                        gLog << err << "ERROR - " << str.str() << endl;
     264                        return;
     265#endif
     266                    }
     267                }
     268
     269                const Table::Column col = { bytes, n, size, type, unit };
     270
     271                cols[id] = col;
     272                bytes  += n*size;
     273            }
     274
     275            if (bytes!=bytes_per_row)
     276            {
     277#ifdef __EXCEPTIONS
     278                throw runtime_error("Column size mismatch");
     279#else
     280                gLog << err << "ERROR - Column size mismatch" << endl;
     281                return;
     282#endif
     283            }
     284
     285            name = Get<string>("EXTNAME");
     286        }
     287
     288        void PrintKeys(bool display_all=false) const
     289        {
     290            for (Keys::const_iterator it=keys.begin(); it!=keys.end(); it++)
     291            {
     292                if (!display_all &&
     293                    (it->first.substr(0, 6)!="TTYPE" ||
     294                     it->first.substr(0, 6)!="TFORM" ||
     295                     it->first.substr(0, 6)!="TUNIT" ||
     296                     it->first!="TFIELDS"  ||
     297                     it->first!="XTENSION" ||
     298                     it->first!="NAXIS"    ||
     299                     it->first!="BITPIX"   ||
     300                     it->first!="PCOUNT"   ||
     301                     it->first!="GCOUNT")
     302                   )
     303                    continue;
     304
     305                gLog << all << setw(2) << it->second.type << '|' << it->first << '=' << it->second.value << '/' << it->second.comment << '|' << endl;
     306            }}
     307
     308        void PrintColumns() const
     309        {
     310            typedef map<pair<size_t, string>, Column> Sorted;
     311
     312            Sorted sorted;
     313
     314            for (Columns::const_iterator it=cols.begin(); it!=cols.end(); it++)
     315                sorted[make_pair(it->second.offset, it->first)] = it->second;
     316
     317            for (Sorted::const_iterator it=sorted.begin(); it!=sorted.end(); it++)
     318            {
     319                gLog << all << setw(6) << it->second.offset << "| ";
     320                gLog << it->second.num << 'x';
     321                switch (it->second.type)
     322                {
     323                case 'L': gLog << "bool(8)";    break;
     324                case 'B': gLog << "byte(8)";    break;
     325                case 'I': gLog << "short(16)";  break;
     326                case 'J': gLog << "int(32)";    break;
     327                case 'K': gLog << "int(64)";    break;
     328                case 'E': gLog << "float(32)";  break;
     329                case 'D': gLog << "double(64)"; break;
     330                }
     331                gLog << ": " << it->first.second << " [" << it->second.unit << "]" << endl;
     332            }
     333        }
     334
     335        operator bool() const { return !name.empty(); }
     336
     337        bool HasKey(const string &key) const
     338        {
     339            return keys.find(key)!=keys.end();
     340        }
     341
     342            // Values of keys are always signed
     343        template<typename T>
     344            T Get(const string &key) const
     345        {
     346            const map<string,Entry>::const_iterator it = keys.find(key);
     347            if (it==keys.end())
     348            {
     349                ostringstream str;
     350                str << "Key '" << key << "' not found." << endl;
     351#ifdef __EXCEPTIONS
     352                throw runtime_error(str.str());
     353#else
     354                gLog << err << "ERROR - " << str.str() << endl;
     355                return 0;
     356#endif
     357            }
     358            return it->second.Get<T>();
     359        }
     360
     361            // Values of keys are always signed
     362        template<typename T>
     363            T Get(const string &key, const string &deflt) const
     364        {
     365            const map<string,Entry>::const_iterator it = keys.find(key);
     366            return it==keys.end() ? deflt :it->second.Get<T>();
     367        }
     368
     369        size_t GetN(const string &key) const
     370        {
     371            const Columns::const_iterator it = cols.find(key);
     372            return it==cols.end() ? 0 : it->second.num;
     373        }
     374    };
     375
     376private:
     377    Table fTable;
     378
     379    typedef pair<void*, Table::Column> Address;
     380    typedef vector<Address> Addresses;
     381    //map<void*, Table::Column> fAddresses;
     382    Addresses fAddresses;
     383
     384    vector<char> fBufferRow;
     385    vector<char> fBufferDat;
     386
     387    size_t fRow;
     388
     389    vector<string> ReadBlock(vector<string> &vec)
     390    {
     391        bool endtag = false;
     392        for (int i=0; i<36; i++)
     393        {
     394            char c[81];
     395            c[80] = 0;
     396            read(c, 80);
     397            if (!good())
     398                break;
     399
     400            if (c[0]==0)
     401                return vector<string>();
     402
     403            string str(c);
     404
     405//            if (!str.empty())
     406//                cout << setw(2) << i << "|" << str << "|" << (endtag?'-':'+') << endl;
     407
     408            if (str=="END                                                                             ")
     409            {
     410                endtag = true;
     411
     412                // Make sure that no empty vector is returned
     413                if (vec.size()%36==0)
     414                    vec.push_back(string("END     = '' / "));
     415            }
     416
     417            if (endtag)
     418                continue;
     419
     420            vec.push_back(str);
     421        }
     422
     423        return vec;
     424    }
     425
     426    string Compile(const string &key, int16_t i=-1)
     427    {
     428        if (i<0)
     429            return key;
     430
     431        ostringstream str;
     432        str << key << i;
     433        return str.str();
     434    }
     435
     436public:
     437    fits(const string &fname) : izstream(fname.c_str())
     438    {
     439        char simple[10];
     440        read(simple, 10);
     441        if (!good())
     442            return;
     443
     444        if (memcmp(simple, "SIMPLE  = ", 10))
     445        {
     446            clear(rdstate()|ios::badbit);
     447#ifdef __EXCEPTIONS
     448            throw runtime_error("File is not a FITS file.");
     449#else
     450            gLog << err << "ERROR - File is not a FITS file." << endl;
     451            return;
     452#endif
     453        }
     454
     455        seekg(0);
     456
     457        while (good())
     458        {
     459            vector<string> block;
     460            while (1)
     461            {
     462                // FIXME: Set limit on memory consumption
     463                ReadBlock(block);
     464                if (!good())
     465                {
     466                    clear(rdstate()|ios::badbit);
     467#ifdef __EXCEPTIONS
     468                    throw runtime_error("FITS file corrupted.");
     469#else
     470                    gLog << err << "ERROR - FITS file corrupted." << endl;
     471                    return;
     472#endif
     473                }
     474
     475                if (block.size()%36)
     476                    break;
     477            }
     478
     479            if (block.size()==0)
     480                break;
     481
     482            if (block[0].substr(0, 9)=="SIMPLE  =")
     483                continue;
     484
     485            if (block[0].substr(0, 9)=="XTENSION=")
     486            {
     487                // FIXME: Check for table name
     488
     489                fTable = Table(block, tellg());
     490                fRow   = (size_t)-1;
     491
     492                //fTable.PrintKeys();
     493
     494                if (!fTable)
     495                {
     496                    clear(rdstate()|ios::badbit);
     497                    return;
     498                }
     499
     500                fBufferRow.resize(fTable.bytes_per_row);
     501                fBufferDat.resize(fTable.bytes_per_row);
     502
     503                /*
     504                 // Next table should start at:
     505                 const size_t size = fTable.bytes_per_row*fTable.num_rows;
     506                 const size_t blks = size/(36*80);
     507                 const size_t rest = size%(36*80);
     508
     509                seekg((blks+(rest>0?1:0))*(36*80), ios::cur);
     510                if (!good())
     511                     gLog << err << "File seems to be incomplete (less data than expected from header)." << endl;
     512
     513                fRow   = fTable.num_rows;
     514                 */
     515
     516                break;
     517            }
     518        }
     519    }
     520
     521    void ReadRow(size_t row)
     522    {
     523        // if (row!=fRow+1) // Fast seeking is ensured by izstream
     524        seekg(fTable.offset+row*fTable.bytes_per_row);
     525
     526        fRow = row;
     527
     528        read(fBufferRow.data(), fBufferRow.size());
     529        //fin.clear(fin.rdstate()&~ios::eofbit);
     530    }
     531
     532    template<size_t N>
     533        void revcpy(char *dest, const char *src, int num)
     534    {
     535        const char *pend = src + num*N;
     536        for (const char *ptr = src; ptr<pend; ptr+=N, dest+=N)
     537            reverse_copy(ptr, ptr+N, dest);
     538    }
     539
     540    bool GetRow(size_t row)
     541    {
     542        ReadRow(row);
     543        if (!good())
     544            return good();
     545
     546        for (Addresses::const_iterator it=fAddresses.begin(); it!=fAddresses.end(); it++)
     547        {
     548            const Table::Column &c = it->second;
     549
     550            const char *src = fBufferRow.data() + c.offset;
     551            char *dest = reinterpret_cast<char*>(it->first);
     552
     553            // Let the compiler do some optimization by
     554            // knowing the we only have 1, 2, 4 and 8
     555            switch (c.size)
     556            {
     557            case 1: memcpy   (dest, src, c.num*c.size); break;
     558            case 2: revcpy<2>(dest, src, c.num);        break;
     559            case 4: revcpy<4>(dest, src, c.num);        break;
     560            case 8: revcpy<8>(dest, src, c.num);        break;
     561            }
     562        }
     563
     564        return good();
     565    }
     566
     567    bool GetNextRow()
     568    {
     569        return GetRow(fRow+1);
     570    }
     571
     572    bool SkipNextRow()
     573    {
     574        seekg(fTable.offset+(++fRow)*fTable.bytes_per_row);
     575        return good();
     576    }
     577
     578    static bool Compare(const Address &p1, const Address &p2)
     579    {
     580        return p1.first>p2.first;
     581    }
     582
     583    template<typename T>
     584    bool SetPtrAddress(const string &name, T *ptr, size_t cnt)
     585    {
     586        if (fTable.cols.count(name)==0)
     587        {
     588            ostringstream str;
     589            str <<"SetPtrAddress('" << name << "') - Column not found." << endl;
     590#ifdef __EXCEPTIONS
     591            throw runtime_error(str.str());
     592#else
     593            gLog << err << "ERROR - " << str.str() << endl;
     594            return false;
     595#endif
     596        }
     597
     598        if (sizeof(T)!=fTable.cols[name].size)
     599        {
     600            ostringstream str;
     601            str << "SetPtrAddress('" << name << "') - Element size mismatch: expected "
     602                << fTable.cols[name].size << " from header, got " << sizeof(T) << endl;
     603#ifdef __EXCEPTIONS
     604            throw runtime_error(str.str());
     605#else
     606            gLog << err << "ERROR - " << str.str() << endl;
     607            return false;
     608#endif
     609        }
     610
     611        if (cnt!=fTable.cols[name].num)
     612        {
     613            ostringstream str;
     614            str << "SetPtrAddress('" << name << "') - Element count mismatch: expected "
     615                << fTable.cols[name].num << " from header, got " << cnt << endl;
     616#ifdef __EXCEPTIONS
     617            throw runtime_error(str.str());
     618#else
     619            gLog << err << "ERROR - " << str.str() << endl;
     620            return false;
     621#endif
     622        }
     623
     624        // if (fAddresses.count(ptr)>0)
     625        //     gLog << warn << "SetPtrAddress('" << name << "') - Pointer " << ptr << " already assigned." << endl;
     626
     627        //fAddresses[ptr] = fTable.cols[name];
     628        fAddresses.push_back(make_pair(ptr, fTable.cols[name]));
     629        sort(fAddresses.begin(), fAddresses.end(), Compare);
     630        return true;
     631    }
     632
     633    template<class T>
     634    bool SetRefAddress(const string &name, T &ptr)
     635    {
     636        return SetPtrAddress(name, &ptr, sizeof(ptr)/sizeof(T));
     637    }
     638
     639    template<typename T>
     640    bool SetVecAddress(const string &name, vector<T> &vec)
     641    {
     642        return SetPtrAddress(name, vec.data(), vec.size());
     643    }
     644
     645    template<typename T>
     646        T Get(const string &key) const
     647    {
     648        return fTable.Get<T>(key);
     649    }
     650
     651    template<typename T>
     652        T Get(const string &key, const string &deflt) const
     653    {
     654        return fTable.Get<T>(key, deflt);
     655    }
     656
     657    bool SetPtrAddress(const string &name, void *ptr)
     658    {
     659        if (fTable.cols.count(name)==0)
     660        {
     661            ostringstream str;
     662            str <<"SetPtrAddress('" << name << "') - Column not found." << endl;
     663#ifdef __EXCEPTIONS
     664            throw runtime_error(str.str());
     665#else
     666            gLog << err << "ERROR - " << str.str() << endl;
     667            return false;
     668#endif
     669        }
     670
     671        // if (fAddresses.count(ptr)>0)
     672        //     gLog << warn << "SetPtrAddress('" << name << "') - Pointer " << ptr << " already assigned." << endl;
     673
     674        //fAddresses[ptr] = fTable.cols[name];
     675        fAddresses.push_back(make_pair(ptr, fTable.cols[name]));
     676        sort(fAddresses.begin(), fAddresses.end(), Compare);
     677        return true;
     678    }
     679
     680    bool     HasKey(const string &key) const { return fTable.HasKey(key); }
     681    int64_t  GetInt(const string &key) const { return fTable.Get<int64_t>(key); }
     682    uint64_t GetUInt(const string &key) const { return fTable.Get<uint64_t>(key); }
     683    double   GetFloat(const string &key) const { return fTable.Get<double>(key); }
     684    string   GetStr(const string &key) const { return fTable.Get<string>(key); }
     685
     686    size_t GetN(const string &key) const
     687    {
     688        return fTable.GetN(key);
     689    }
     690
     691    size_t GetNumRows() const { return fTable.num_rows; }
     692    size_t GetRow() const { return fRow; }
     693
     694    operator bool() const { return fTable && fTable.offset!=0; }
     695
     696    void PrintKeys() const { fTable.PrintKeys(); }
     697    void PrintColumns() const { fTable.PrintColumns(); }
     698};
     699
     700};
     701#endif
  • fact/tools/rootmacros/izstream.h

    r12199 r12255  
    1 #error Please replace izstream.h with https://fact.isdc.unige.ch/svn/trunk/Mars/mcore/izstream.h
     1#ifndef MARS_izstream
     2#define MARS_izstream
     3
     4#include <istream>
     5#include <streambuf>
     6
     7#ifdef __MARS__
     8#ifndef ROOT_TObject
     9#include <TObject.h> // Needed for ClassDef
     10#endif
     11#endif
     12
     13#ifdef __CINT__
     14typedef void *gzFile;
     15#else
     16#include <zlib.h>
     17#endif
     18
     19class izstream : public std::streambuf, public std::istream
     20{
     21private:
     22    static const int fgBufferSize = 3276804; // maximum size of a fact event + 4
     23
     24    gzFile fFile;                 // file handle for compressed file
     25    char   fBuffer[fgBufferSize]; // data buffer
     26
     27    int underflow()
     28    {
     29        if (gptr() && gptr()<egptr())
     30            return * reinterpret_cast<unsigned char *>(gptr());
     31
     32        if (!is_open())
     33            return EOF;
     34
     35        // gptr()-eback(): if more than four bytes are already flushed
     36        const int iputback = gptr()-eback()>4 ? 4 : gptr()-eback();
     37
     38        // Copy the last four bytes flushed into the putback area
     39        memcpy(fBuffer+(4-iputback), gptr()-iputback, iputback);
     40
     41        // Fill the buffer starting at the current file position and reset buffer
     42        // pointers by calling setg
     43        const int num = gzread(fFile, fBuffer+4, fgBufferSize-4);
     44        if (num <= 0) // ERROR or EOF
     45            return EOF;
     46
     47        // reset buffer pointers
     48        setg(fBuffer+(4-iputback), fBuffer+4, fBuffer+4+num);
     49
     50        // return next character
     51        return *reinterpret_cast<unsigned char *>(gptr());
     52    }
     53
     54
     55public:
     56    izstream() : std::istream(this), fFile(0)
     57    {
     58        setg(fBuffer+4, fBuffer+4, fBuffer+4);
     59    }
     60    izstream(const char *name) : std::istream(this), fFile(0)
     61    {
     62        setg(fBuffer+4, fBuffer+4, fBuffer+4);
     63        open(name);
     64    }
     65    ~izstream() { izstream::close(); }
     66
     67    int is_open() { return fFile!=0; }
     68
     69    // --------------------------------------------------------------------------
     70    //
     71    // Open a file by name. Test if it is open like for an ifstream
     72    // It doesn't matter whether the file is gzip compressed or not.
     73    //
     74    void open(const char* name)
     75    {
     76        if (is_open())
     77        {
     78            clear(rdstate()|std::ios::failbit);
     79            return;
     80        }
     81
     82        fFile = gzopen(name, "rb");
     83        if (fFile == 0)
     84        {
     85            clear(rdstate()|std::ios::failbit);
     86            return;
     87        }
     88    }
     89    // --------------------------------------------------------------------------
     90    //
     91    // Close an open file.
     92    //
     93    void close()
     94    {
     95        if (!is_open())
     96            return;
     97
     98        if (gzclose(fFile) != Z_OK)
     99            clear(rdstate()|std::ios::failbit);
     100
     101        fFile = 0;
     102    }
     103
     104    std::streambuf::pos_type seekoff(std::streambuf::off_type offset, std::ios_base::seekdir dir,
     105                                     std::ios_base::openmode = std::ios_base::in)
     106    {
     107        // Using a switch instead results in:
     108        //  In member function `virtual std::streampos izstream::seekoff(long int, std::_Ios_Seekdir, std::_Ios_Openmode)':
     109        //  warning: enumeration value `_M_ios_seekdir_end' not handled in switch
     110        //  warning: case value `0' not in enumerated type `_Ios_Seekdir'
     111        //  warning: case value `1' not in enumerated type `_Ios_Seekdir'
     112        //  warning: case value `2' not in enumerated type `_Ios_Seekdir'
     113
     114        if (dir==std::ios::end)
     115        {
     116            clear(rdstate()|std::ios::failbit);
     117            return EOF;
     118        }
     119
     120        // We only do relative seeking to avoid unnecessary decompression
     121        // of the whole file
     122        if (dir==std::ios::beg)
     123            offset -= tellg();
     124
     125        // Calculate future position in streambuffer
     126        const char *ptr = gptr()+offset;
     127
     128        // This is the number of bytes still available in the buffer
     129        const size_t sbuf = egptr()-gptr();
     130
     131        // Check if the new position will still be in the buffer
     132        // In this case the target data was already decompressed.
     133        if (ptr>=eback() && ptr<egptr())
     134        {
     135            // Absolute position in z-stream
     136            const z_off_t zpos = gztell(fFile)-sbuf; //gzseek(fFile, 0, SEEK_CUR);
     137
     138            gbump(offset);
     139
     140            return zpos+offset;
     141        }
     142
     143        const streampos pos = gzseek(fFile, offset-sbuf, SEEK_CUR);
     144
     145        // Buffer is empty - force refilling
     146        setg(fBuffer+4, fBuffer+4, fBuffer+4);
     147
     148        return pos<0 ? streampos(EOF) : pos;
     149
     150        /*
     151         // SEEK_END not supported by zlib
     152         if (dir==ios::end)
     153         {
     154             // Position in z-stream
     155             const z_off_t zpos = gzseek(fFile, offset, SEEK_END);
     156             if (zpos<0)
     157                 return EOF;
     158
     159             return fill_buffer()==EOF ? EOF : zpos;
     160         }
     161         */
     162        return EOF;
     163    }
     164
     165    std::streambuf::pos_type seekpos(std::streambuf::pos_type pos,
     166                                     std::ios_base::openmode = std::ios_base::in)
     167    {
     168        return seekoff(pos, std::ios::beg);
     169    }
     170
     171#ifdef __MARS__
     172    ClassDef(izstream, 0) // A C++ wrapper to istream zlib files
     173#endif
     174};
     175
     176#endif
Note: See TracChangeset for help on using the changeset viewer.