source: trunk/Mars/mbase/MZlib.cc@ 11461

Last change on this file since 11461 was 11435, checked in by tbretz, 13 years ago
Further optimized seeking so that we always seek relative.
File size: 5.3 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of MARS, the MAGIC Analysis and Reconstruction
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
7! * It is distributed WITHOUT ANY WARRANTY.
8! *
9! * Permission to use, copy, modify and distribute this software and its
10! * documentation for any purpose is hereby granted without fee,
11! * provided that the above copyright notice appear in all copies and
12! * that both that copyright notice and this permission notice appear
13! * in supporting documentation. It is provided "as is" without express
14! * or implied warranty.
15! *
16!
17!
18! Author(s): Thomas Bretz, 12/2005 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2005
21!
22!
23\* ======================================================================== */
24
25
26//////////////////////////////////////////////////////////////////////////////
27//
28// MZlib
29//
30// This is a C++ wrapper for zlib.
31//
32// WARNING: - There might not be support for all features.
33// - seek calls might be rather slow
34//
35//////////////////////////////////////////////////////////////////////////////
36#include "MZlib.h"
37
38#include <string.h> // memcpy (UBuntu 8.10)
39
40ClassImp(MZlib);
41
42using namespace std;
43
44// --------------------------------------------------------------------------
45//
46// Open a file by name. Test if it is open like for an ifstream
47// It doesn't matter whether the file is gzip compressed or not.
48//
49void MZlib::open(const char* name)
50{
51 if (is_open())
52 {
53 clear(rdstate()|ios::badbit);
54 return;
55 }
56
57 fFile = gzopen(name, "rb");
58 if (fFile == 0)
59 {
60 clear(rdstate()|ios::badbit);
61 return;
62 }
63}
64
65// --------------------------------------------------------------------------
66//
67// Close an open file.
68//
69void MZlib::close()
70{
71 if (!is_open())
72 return;
73
74 if (gzclose(fFile) != Z_OK)
75 clear(rdstate()|ios::badbit);
76
77 fFile = 0;
78}
79
80// --------------------------------------------------------------------------
81//
82// Handle a buffer underflow (buffer went empty)
83//
84int MZlib::underflow()
85{
86 if (gptr() && gptr()<egptr())
87 return * reinterpret_cast<unsigned char *>(gptr());
88
89 if (!is_open())
90 return EOF;
91
92 // gptr()-eback(): if more than four bytes are already flushed
93 const int iputback = gptr()-eback()>4 ? 4 : gptr()-eback();
94
95 // Copy the last four bytes flushed into the putback area
96 memcpy(fBuffer+(4-iputback), gptr()-iputback, iputback);
97
98 // Fill the buffer starting at the current file position and reset buffer
99 // pointers by calling setg
100 const int num = gzread(fFile, fBuffer+4, fgBufferSize-4);
101 if (num <= 0) // ERROR or EOF
102 return EOF;
103
104 // reset buffer pointers
105 setg(fBuffer+(4-iputback), fBuffer+4, fBuffer+4+num);
106
107 // return next character
108 return *reinterpret_cast<unsigned char *>(gptr());
109}
110
111// --------------------------------------------------------------------------
112//
113#include <iostream>
114# if (__GNUC__>2)
115streambuf::pos_type MZlib::seekoff(streambuf::off_type offset, ios_base::seekdir dir,
116 ios_base::openmode)
117# else
118streampos MZlib::seekoff(streamoff offset, int dir, int)
119# endif
120{
121 // Using a switch instead results in:
122 // In member function `virtual std::streampos MZlib::seekoff(long int, std::_Ios_Seekdir, std::_Ios_Openmode)':
123 // warning: enumeration value `_M_ios_seekdir_end' not handled in switch
124 // warning: case value `0' not in enumerated type `_Ios_Seekdir'
125 // warning: case value `1' not in enumerated type `_Ios_Seekdir'
126 // warning: case value `2' not in enumerated type `_Ios_Seekdir'
127
128 if (dir==ios::end)
129 {
130 clear(rdstate()|ios::failbit);
131 return EOF;
132 }
133
134 // We only do relative seeking to avoid unnecessary decompression
135 // of the whole file
136 if (dir==ios::beg)
137 offset -= tellg();
138
139 // Calculate future position in streambuffer
140 const char *ptr = gptr()+offset;
141
142 // This is the number of bytes still available in the buffer
143 const size_t sbuf = egptr()-gptr();
144
145 // Check if the new position will still be in the buffer
146 // In this case the target data was already decompressed.
147 if (ptr>=eback() && ptr<egptr())
148 {
149 // Absolute position in z-stream
150 const z_off_t zpos = gztell(fFile)-sbuf; //gzseek(fFile, 0, SEEK_CUR);
151
152 gbump(offset);
153
154 return zpos+offset;
155 }
156
157 const streampos pos = gzseek(fFile, offset-sbuf, SEEK_CUR);
158
159 // Buffer is empty - force refilling
160 setg(fBuffer+4, fBuffer+4, fBuffer+4);
161
162 return pos<0 ? streampos(EOF) : pos;
163
164 /*
165 // SEEK_END not supported by zlib
166 if (dir==ios::end)
167 {
168 // Position in z-stream
169 const z_off_t zpos = gzseek(fFile, offset, SEEK_END);
170 if (zpos<0)
171 return EOF;
172
173 return fill_buffer()==EOF ? EOF : zpos;
174 }
175 */
176 return EOF;
177
178}
179
180// --------------------------------------------------------------------------
181//
182# if (__GNUC__>2)
183streambuf::pos_type MZlib::seekpos(streambuf::pos_type pos, ios_base::openmode)
184# else
185streampos MZlib::seekpos(streampos pos, int)
186# endif
187{
188 return seekoff(pos, ios::beg);
189}
Note: See TracBrowser for help on using the repository browser.