source: trunk/Mars/mcore/izstream.h@ 20115

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