source: fact/tools/rootmacros/izstream.h@ 14963

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