1*44bedb31SLionel Sambuc /*
2*44bedb31SLionel Sambuc * A C++ I/O streams interface to the zlib gz* functions
3*44bedb31SLionel Sambuc *
4*44bedb31SLionel Sambuc * by Ludwig Schwardt <schwardt@sun.ac.za>
5*44bedb31SLionel Sambuc * original version by Kevin Ruland <kevin@rodin.wustl.edu>
6*44bedb31SLionel Sambuc *
7*44bedb31SLionel Sambuc * This version is standard-compliant and compatible with gcc 3.x.
8*44bedb31SLionel Sambuc */
9*44bedb31SLionel Sambuc
10*44bedb31SLionel Sambuc #include "zfstream.h"
11*44bedb31SLionel Sambuc #include <cstring> // for strcpy, strcat, strlen (mode strings)
12*44bedb31SLionel Sambuc #include <cstdio> // for BUFSIZ
13*44bedb31SLionel Sambuc
14*44bedb31SLionel Sambuc // Internal buffer sizes (default and "unbuffered" versions)
15*44bedb31SLionel Sambuc #define BIGBUFSIZE BUFSIZ
16*44bedb31SLionel Sambuc #define SMALLBUFSIZE 1
17*44bedb31SLionel Sambuc
18*44bedb31SLionel Sambuc /*****************************************************************************/
19*44bedb31SLionel Sambuc
20*44bedb31SLionel Sambuc // Default constructor
gzfilebuf()21*44bedb31SLionel Sambuc gzfilebuf::gzfilebuf()
22*44bedb31SLionel Sambuc : file(NULL), io_mode(std::ios_base::openmode(0)), own_fd(false),
23*44bedb31SLionel Sambuc buffer(NULL), buffer_size(BIGBUFSIZE), own_buffer(true)
24*44bedb31SLionel Sambuc {
25*44bedb31SLionel Sambuc // No buffers to start with
26*44bedb31SLionel Sambuc this->disable_buffer();
27*44bedb31SLionel Sambuc }
28*44bedb31SLionel Sambuc
29*44bedb31SLionel Sambuc // Destructor
~gzfilebuf()30*44bedb31SLionel Sambuc gzfilebuf::~gzfilebuf()
31*44bedb31SLionel Sambuc {
32*44bedb31SLionel Sambuc // Sync output buffer and close only if responsible for file
33*44bedb31SLionel Sambuc // (i.e. attached streams should be left open at this stage)
34*44bedb31SLionel Sambuc this->sync();
35*44bedb31SLionel Sambuc if (own_fd)
36*44bedb31SLionel Sambuc this->close();
37*44bedb31SLionel Sambuc // Make sure internal buffer is deallocated
38*44bedb31SLionel Sambuc this->disable_buffer();
39*44bedb31SLionel Sambuc }
40*44bedb31SLionel Sambuc
41*44bedb31SLionel Sambuc // Set compression level and strategy
42*44bedb31SLionel Sambuc int
setcompression(int comp_level,int comp_strategy)43*44bedb31SLionel Sambuc gzfilebuf::setcompression(int comp_level,
44*44bedb31SLionel Sambuc int comp_strategy)
45*44bedb31SLionel Sambuc {
46*44bedb31SLionel Sambuc return gzsetparams(file, comp_level, comp_strategy);
47*44bedb31SLionel Sambuc }
48*44bedb31SLionel Sambuc
49*44bedb31SLionel Sambuc // Open gzipped file
50*44bedb31SLionel Sambuc gzfilebuf*
open(const char * name,std::ios_base::openmode mode)51*44bedb31SLionel Sambuc gzfilebuf::open(const char *name,
52*44bedb31SLionel Sambuc std::ios_base::openmode mode)
53*44bedb31SLionel Sambuc {
54*44bedb31SLionel Sambuc // Fail if file already open
55*44bedb31SLionel Sambuc if (this->is_open())
56*44bedb31SLionel Sambuc return NULL;
57*44bedb31SLionel Sambuc // Don't support simultaneous read/write access (yet)
58*44bedb31SLionel Sambuc if ((mode & std::ios_base::in) && (mode & std::ios_base::out))
59*44bedb31SLionel Sambuc return NULL;
60*44bedb31SLionel Sambuc
61*44bedb31SLionel Sambuc // Build mode string for gzopen and check it [27.8.1.3.2]
62*44bedb31SLionel Sambuc char char_mode[6] = "\0\0\0\0\0";
63*44bedb31SLionel Sambuc if (!this->open_mode(mode, char_mode))
64*44bedb31SLionel Sambuc return NULL;
65*44bedb31SLionel Sambuc
66*44bedb31SLionel Sambuc // Attempt to open file
67*44bedb31SLionel Sambuc if ((file = gzopen(name, char_mode)) == NULL)
68*44bedb31SLionel Sambuc return NULL;
69*44bedb31SLionel Sambuc
70*44bedb31SLionel Sambuc // On success, allocate internal buffer and set flags
71*44bedb31SLionel Sambuc this->enable_buffer();
72*44bedb31SLionel Sambuc io_mode = mode;
73*44bedb31SLionel Sambuc own_fd = true;
74*44bedb31SLionel Sambuc return this;
75*44bedb31SLionel Sambuc }
76*44bedb31SLionel Sambuc
77*44bedb31SLionel Sambuc // Attach to gzipped file
78*44bedb31SLionel Sambuc gzfilebuf*
attach(int fd,std::ios_base::openmode mode)79*44bedb31SLionel Sambuc gzfilebuf::attach(int fd,
80*44bedb31SLionel Sambuc std::ios_base::openmode mode)
81*44bedb31SLionel Sambuc {
82*44bedb31SLionel Sambuc // Fail if file already open
83*44bedb31SLionel Sambuc if (this->is_open())
84*44bedb31SLionel Sambuc return NULL;
85*44bedb31SLionel Sambuc // Don't support simultaneous read/write access (yet)
86*44bedb31SLionel Sambuc if ((mode & std::ios_base::in) && (mode & std::ios_base::out))
87*44bedb31SLionel Sambuc return NULL;
88*44bedb31SLionel Sambuc
89*44bedb31SLionel Sambuc // Build mode string for gzdopen and check it [27.8.1.3.2]
90*44bedb31SLionel Sambuc char char_mode[6] = "\0\0\0\0\0";
91*44bedb31SLionel Sambuc if (!this->open_mode(mode, char_mode))
92*44bedb31SLionel Sambuc return NULL;
93*44bedb31SLionel Sambuc
94*44bedb31SLionel Sambuc // Attempt to attach to file
95*44bedb31SLionel Sambuc if ((file = gzdopen(fd, char_mode)) == NULL)
96*44bedb31SLionel Sambuc return NULL;
97*44bedb31SLionel Sambuc
98*44bedb31SLionel Sambuc // On success, allocate internal buffer and set flags
99*44bedb31SLionel Sambuc this->enable_buffer();
100*44bedb31SLionel Sambuc io_mode = mode;
101*44bedb31SLionel Sambuc own_fd = false;
102*44bedb31SLionel Sambuc return this;
103*44bedb31SLionel Sambuc }
104*44bedb31SLionel Sambuc
105*44bedb31SLionel Sambuc // Close gzipped file
106*44bedb31SLionel Sambuc gzfilebuf*
close()107*44bedb31SLionel Sambuc gzfilebuf::close()
108*44bedb31SLionel Sambuc {
109*44bedb31SLionel Sambuc // Fail immediately if no file is open
110*44bedb31SLionel Sambuc if (!this->is_open())
111*44bedb31SLionel Sambuc return NULL;
112*44bedb31SLionel Sambuc // Assume success
113*44bedb31SLionel Sambuc gzfilebuf* retval = this;
114*44bedb31SLionel Sambuc // Attempt to sync and close gzipped file
115*44bedb31SLionel Sambuc if (this->sync() == -1)
116*44bedb31SLionel Sambuc retval = NULL;
117*44bedb31SLionel Sambuc if (gzclose(file) < 0)
118*44bedb31SLionel Sambuc retval = NULL;
119*44bedb31SLionel Sambuc // File is now gone anyway (postcondition [27.8.1.3.8])
120*44bedb31SLionel Sambuc file = NULL;
121*44bedb31SLionel Sambuc own_fd = false;
122*44bedb31SLionel Sambuc // Destroy internal buffer if it exists
123*44bedb31SLionel Sambuc this->disable_buffer();
124*44bedb31SLionel Sambuc return retval;
125*44bedb31SLionel Sambuc }
126*44bedb31SLionel Sambuc
127*44bedb31SLionel Sambuc /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
128*44bedb31SLionel Sambuc
129*44bedb31SLionel Sambuc // Convert int open mode to mode string
130*44bedb31SLionel Sambuc bool
open_mode(std::ios_base::openmode mode,char * c_mode) const131*44bedb31SLionel Sambuc gzfilebuf::open_mode(std::ios_base::openmode mode,
132*44bedb31SLionel Sambuc char* c_mode) const
133*44bedb31SLionel Sambuc {
134*44bedb31SLionel Sambuc bool testb = mode & std::ios_base::binary;
135*44bedb31SLionel Sambuc bool testi = mode & std::ios_base::in;
136*44bedb31SLionel Sambuc bool testo = mode & std::ios_base::out;
137*44bedb31SLionel Sambuc bool testt = mode & std::ios_base::trunc;
138*44bedb31SLionel Sambuc bool testa = mode & std::ios_base::app;
139*44bedb31SLionel Sambuc
140*44bedb31SLionel Sambuc // Check for valid flag combinations - see [27.8.1.3.2] (Table 92)
141*44bedb31SLionel Sambuc // Original zfstream hardcoded the compression level to maximum here...
142*44bedb31SLionel Sambuc // Double the time for less than 1% size improvement seems
143*44bedb31SLionel Sambuc // excessive though - keeping it at the default level
144*44bedb31SLionel Sambuc // To change back, just append "9" to the next three mode strings
145*44bedb31SLionel Sambuc if (!testi && testo && !testt && !testa)
146*44bedb31SLionel Sambuc strcpy(c_mode, "w");
147*44bedb31SLionel Sambuc if (!testi && testo && !testt && testa)
148*44bedb31SLionel Sambuc strcpy(c_mode, "a");
149*44bedb31SLionel Sambuc if (!testi && testo && testt && !testa)
150*44bedb31SLionel Sambuc strcpy(c_mode, "w");
151*44bedb31SLionel Sambuc if (testi && !testo && !testt && !testa)
152*44bedb31SLionel Sambuc strcpy(c_mode, "r");
153*44bedb31SLionel Sambuc // No read/write mode yet
154*44bedb31SLionel Sambuc // if (testi && testo && !testt && !testa)
155*44bedb31SLionel Sambuc // strcpy(c_mode, "r+");
156*44bedb31SLionel Sambuc // if (testi && testo && testt && !testa)
157*44bedb31SLionel Sambuc // strcpy(c_mode, "w+");
158*44bedb31SLionel Sambuc
159*44bedb31SLionel Sambuc // Mode string should be empty for invalid combination of flags
160*44bedb31SLionel Sambuc if (strlen(c_mode) == 0)
161*44bedb31SLionel Sambuc return false;
162*44bedb31SLionel Sambuc if (testb)
163*44bedb31SLionel Sambuc strcat(c_mode, "b");
164*44bedb31SLionel Sambuc return true;
165*44bedb31SLionel Sambuc }
166*44bedb31SLionel Sambuc
167*44bedb31SLionel Sambuc // Determine number of characters in internal get buffer
168*44bedb31SLionel Sambuc std::streamsize
showmanyc()169*44bedb31SLionel Sambuc gzfilebuf::showmanyc()
170*44bedb31SLionel Sambuc {
171*44bedb31SLionel Sambuc // Calls to underflow will fail if file not opened for reading
172*44bedb31SLionel Sambuc if (!this->is_open() || !(io_mode & std::ios_base::in))
173*44bedb31SLionel Sambuc return -1;
174*44bedb31SLionel Sambuc // Make sure get area is in use
175*44bedb31SLionel Sambuc if (this->gptr() && (this->gptr() < this->egptr()))
176*44bedb31SLionel Sambuc return std::streamsize(this->egptr() - this->gptr());
177*44bedb31SLionel Sambuc else
178*44bedb31SLionel Sambuc return 0;
179*44bedb31SLionel Sambuc }
180*44bedb31SLionel Sambuc
181*44bedb31SLionel Sambuc // Fill get area from gzipped file
182*44bedb31SLionel Sambuc gzfilebuf::int_type
underflow()183*44bedb31SLionel Sambuc gzfilebuf::underflow()
184*44bedb31SLionel Sambuc {
185*44bedb31SLionel Sambuc // If something is left in the get area by chance, return it
186*44bedb31SLionel Sambuc // (this shouldn't normally happen, as underflow is only supposed
187*44bedb31SLionel Sambuc // to be called when gptr >= egptr, but it serves as error check)
188*44bedb31SLionel Sambuc if (this->gptr() && (this->gptr() < this->egptr()))
189*44bedb31SLionel Sambuc return traits_type::to_int_type(*(this->gptr()));
190*44bedb31SLionel Sambuc
191*44bedb31SLionel Sambuc // If the file hasn't been opened for reading, produce error
192*44bedb31SLionel Sambuc if (!this->is_open() || !(io_mode & std::ios_base::in))
193*44bedb31SLionel Sambuc return traits_type::eof();
194*44bedb31SLionel Sambuc
195*44bedb31SLionel Sambuc // Attempt to fill internal buffer from gzipped file
196*44bedb31SLionel Sambuc // (buffer must be guaranteed to exist...)
197*44bedb31SLionel Sambuc int bytes_read = gzread(file, buffer, buffer_size);
198*44bedb31SLionel Sambuc // Indicates error or EOF
199*44bedb31SLionel Sambuc if (bytes_read <= 0)
200*44bedb31SLionel Sambuc {
201*44bedb31SLionel Sambuc // Reset get area
202*44bedb31SLionel Sambuc this->setg(buffer, buffer, buffer);
203*44bedb31SLionel Sambuc return traits_type::eof();
204*44bedb31SLionel Sambuc }
205*44bedb31SLionel Sambuc // Make all bytes read from file available as get area
206*44bedb31SLionel Sambuc this->setg(buffer, buffer, buffer + bytes_read);
207*44bedb31SLionel Sambuc
208*44bedb31SLionel Sambuc // Return next character in get area
209*44bedb31SLionel Sambuc return traits_type::to_int_type(*(this->gptr()));
210*44bedb31SLionel Sambuc }
211*44bedb31SLionel Sambuc
212*44bedb31SLionel Sambuc // Write put area to gzipped file
213*44bedb31SLionel Sambuc gzfilebuf::int_type
overflow(int_type c)214*44bedb31SLionel Sambuc gzfilebuf::overflow(int_type c)
215*44bedb31SLionel Sambuc {
216*44bedb31SLionel Sambuc // Determine whether put area is in use
217*44bedb31SLionel Sambuc if (this->pbase())
218*44bedb31SLionel Sambuc {
219*44bedb31SLionel Sambuc // Double-check pointer range
220*44bedb31SLionel Sambuc if (this->pptr() > this->epptr() || this->pptr() < this->pbase())
221*44bedb31SLionel Sambuc return traits_type::eof();
222*44bedb31SLionel Sambuc // Add extra character to buffer if not EOF
223*44bedb31SLionel Sambuc if (!traits_type::eq_int_type(c, traits_type::eof()))
224*44bedb31SLionel Sambuc {
225*44bedb31SLionel Sambuc *(this->pptr()) = traits_type::to_char_type(c);
226*44bedb31SLionel Sambuc this->pbump(1);
227*44bedb31SLionel Sambuc }
228*44bedb31SLionel Sambuc // Number of characters to write to file
229*44bedb31SLionel Sambuc int bytes_to_write = this->pptr() - this->pbase();
230*44bedb31SLionel Sambuc // Overflow doesn't fail if nothing is to be written
231*44bedb31SLionel Sambuc if (bytes_to_write > 0)
232*44bedb31SLionel Sambuc {
233*44bedb31SLionel Sambuc // If the file hasn't been opened for writing, produce error
234*44bedb31SLionel Sambuc if (!this->is_open() || !(io_mode & std::ios_base::out))
235*44bedb31SLionel Sambuc return traits_type::eof();
236*44bedb31SLionel Sambuc // If gzipped file won't accept all bytes written to it, fail
237*44bedb31SLionel Sambuc if (gzwrite(file, this->pbase(), bytes_to_write) != bytes_to_write)
238*44bedb31SLionel Sambuc return traits_type::eof();
239*44bedb31SLionel Sambuc // Reset next pointer to point to pbase on success
240*44bedb31SLionel Sambuc this->pbump(-bytes_to_write);
241*44bedb31SLionel Sambuc }
242*44bedb31SLionel Sambuc }
243*44bedb31SLionel Sambuc // Write extra character to file if not EOF
244*44bedb31SLionel Sambuc else if (!traits_type::eq_int_type(c, traits_type::eof()))
245*44bedb31SLionel Sambuc {
246*44bedb31SLionel Sambuc // If the file hasn't been opened for writing, produce error
247*44bedb31SLionel Sambuc if (!this->is_open() || !(io_mode & std::ios_base::out))
248*44bedb31SLionel Sambuc return traits_type::eof();
249*44bedb31SLionel Sambuc // Impromptu char buffer (allows "unbuffered" output)
250*44bedb31SLionel Sambuc char_type last_char = traits_type::to_char_type(c);
251*44bedb31SLionel Sambuc // If gzipped file won't accept this character, fail
252*44bedb31SLionel Sambuc if (gzwrite(file, &last_char, 1) != 1)
253*44bedb31SLionel Sambuc return traits_type::eof();
254*44bedb31SLionel Sambuc }
255*44bedb31SLionel Sambuc
256*44bedb31SLionel Sambuc // If you got here, you have succeeded (even if c was EOF)
257*44bedb31SLionel Sambuc // The return value should therefore be non-EOF
258*44bedb31SLionel Sambuc if (traits_type::eq_int_type(c, traits_type::eof()))
259*44bedb31SLionel Sambuc return traits_type::not_eof(c);
260*44bedb31SLionel Sambuc else
261*44bedb31SLionel Sambuc return c;
262*44bedb31SLionel Sambuc }
263*44bedb31SLionel Sambuc
264*44bedb31SLionel Sambuc // Assign new buffer
265*44bedb31SLionel Sambuc std::streambuf*
setbuf(char_type * p,std::streamsize n)266*44bedb31SLionel Sambuc gzfilebuf::setbuf(char_type* p,
267*44bedb31SLionel Sambuc std::streamsize n)
268*44bedb31SLionel Sambuc {
269*44bedb31SLionel Sambuc // First make sure stuff is sync'ed, for safety
270*44bedb31SLionel Sambuc if (this->sync() == -1)
271*44bedb31SLionel Sambuc return NULL;
272*44bedb31SLionel Sambuc // If buffering is turned off on purpose via setbuf(0,0), still allocate one...
273*44bedb31SLionel Sambuc // "Unbuffered" only really refers to put [27.8.1.4.10], while get needs at
274*44bedb31SLionel Sambuc // least a buffer of size 1 (very inefficient though, therefore make it bigger?)
275*44bedb31SLionel Sambuc // This follows from [27.5.2.4.3]/12 (gptr needs to point at something, it seems)
276*44bedb31SLionel Sambuc if (!p || !n)
277*44bedb31SLionel Sambuc {
278*44bedb31SLionel Sambuc // Replace existing buffer (if any) with small internal buffer
279*44bedb31SLionel Sambuc this->disable_buffer();
280*44bedb31SLionel Sambuc buffer = NULL;
281*44bedb31SLionel Sambuc buffer_size = 0;
282*44bedb31SLionel Sambuc own_buffer = true;
283*44bedb31SLionel Sambuc this->enable_buffer();
284*44bedb31SLionel Sambuc }
285*44bedb31SLionel Sambuc else
286*44bedb31SLionel Sambuc {
287*44bedb31SLionel Sambuc // Replace existing buffer (if any) with external buffer
288*44bedb31SLionel Sambuc this->disable_buffer();
289*44bedb31SLionel Sambuc buffer = p;
290*44bedb31SLionel Sambuc buffer_size = n;
291*44bedb31SLionel Sambuc own_buffer = false;
292*44bedb31SLionel Sambuc this->enable_buffer();
293*44bedb31SLionel Sambuc }
294*44bedb31SLionel Sambuc return this;
295*44bedb31SLionel Sambuc }
296*44bedb31SLionel Sambuc
297*44bedb31SLionel Sambuc // Write put area to gzipped file (i.e. ensures that put area is empty)
298*44bedb31SLionel Sambuc int
sync()299*44bedb31SLionel Sambuc gzfilebuf::sync()
300*44bedb31SLionel Sambuc {
301*44bedb31SLionel Sambuc return traits_type::eq_int_type(this->overflow(), traits_type::eof()) ? -1 : 0;
302*44bedb31SLionel Sambuc }
303*44bedb31SLionel Sambuc
304*44bedb31SLionel Sambuc /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
305*44bedb31SLionel Sambuc
306*44bedb31SLionel Sambuc // Allocate internal buffer
307*44bedb31SLionel Sambuc void
enable_buffer()308*44bedb31SLionel Sambuc gzfilebuf::enable_buffer()
309*44bedb31SLionel Sambuc {
310*44bedb31SLionel Sambuc // If internal buffer required, allocate one
311*44bedb31SLionel Sambuc if (own_buffer && !buffer)
312*44bedb31SLionel Sambuc {
313*44bedb31SLionel Sambuc // Check for buffered vs. "unbuffered"
314*44bedb31SLionel Sambuc if (buffer_size > 0)
315*44bedb31SLionel Sambuc {
316*44bedb31SLionel Sambuc // Allocate internal buffer
317*44bedb31SLionel Sambuc buffer = new char_type[buffer_size];
318*44bedb31SLionel Sambuc // Get area starts empty and will be expanded by underflow as need arises
319*44bedb31SLionel Sambuc this->setg(buffer, buffer, buffer);
320*44bedb31SLionel Sambuc // Setup entire internal buffer as put area.
321*44bedb31SLionel Sambuc // The one-past-end pointer actually points to the last element of the buffer,
322*44bedb31SLionel Sambuc // so that overflow(c) can safely add the extra character c to the sequence.
323*44bedb31SLionel Sambuc // These pointers remain in place for the duration of the buffer
324*44bedb31SLionel Sambuc this->setp(buffer, buffer + buffer_size - 1);
325*44bedb31SLionel Sambuc }
326*44bedb31SLionel Sambuc else
327*44bedb31SLionel Sambuc {
328*44bedb31SLionel Sambuc // Even in "unbuffered" case, (small?) get buffer is still required
329*44bedb31SLionel Sambuc buffer_size = SMALLBUFSIZE;
330*44bedb31SLionel Sambuc buffer = new char_type[buffer_size];
331*44bedb31SLionel Sambuc this->setg(buffer, buffer, buffer);
332*44bedb31SLionel Sambuc // "Unbuffered" means no put buffer
333*44bedb31SLionel Sambuc this->setp(0, 0);
334*44bedb31SLionel Sambuc }
335*44bedb31SLionel Sambuc }
336*44bedb31SLionel Sambuc else
337*44bedb31SLionel Sambuc {
338*44bedb31SLionel Sambuc // If buffer already allocated, reset buffer pointers just to make sure no
339*44bedb31SLionel Sambuc // stale chars are lying around
340*44bedb31SLionel Sambuc this->setg(buffer, buffer, buffer);
341*44bedb31SLionel Sambuc this->setp(buffer, buffer + buffer_size - 1);
342*44bedb31SLionel Sambuc }
343*44bedb31SLionel Sambuc }
344*44bedb31SLionel Sambuc
345*44bedb31SLionel Sambuc // Destroy internal buffer
346*44bedb31SLionel Sambuc void
disable_buffer()347*44bedb31SLionel Sambuc gzfilebuf::disable_buffer()
348*44bedb31SLionel Sambuc {
349*44bedb31SLionel Sambuc // If internal buffer exists, deallocate it
350*44bedb31SLionel Sambuc if (own_buffer && buffer)
351*44bedb31SLionel Sambuc {
352*44bedb31SLionel Sambuc // Preserve unbuffered status by zeroing size
353*44bedb31SLionel Sambuc if (!this->pbase())
354*44bedb31SLionel Sambuc buffer_size = 0;
355*44bedb31SLionel Sambuc delete[] buffer;
356*44bedb31SLionel Sambuc buffer = NULL;
357*44bedb31SLionel Sambuc this->setg(0, 0, 0);
358*44bedb31SLionel Sambuc this->setp(0, 0);
359*44bedb31SLionel Sambuc }
360*44bedb31SLionel Sambuc else
361*44bedb31SLionel Sambuc {
362*44bedb31SLionel Sambuc // Reset buffer pointers to initial state if external buffer exists
363*44bedb31SLionel Sambuc this->setg(buffer, buffer, buffer);
364*44bedb31SLionel Sambuc if (buffer)
365*44bedb31SLionel Sambuc this->setp(buffer, buffer + buffer_size - 1);
366*44bedb31SLionel Sambuc else
367*44bedb31SLionel Sambuc this->setp(0, 0);
368*44bedb31SLionel Sambuc }
369*44bedb31SLionel Sambuc }
370*44bedb31SLionel Sambuc
371*44bedb31SLionel Sambuc /*****************************************************************************/
372*44bedb31SLionel Sambuc
373*44bedb31SLionel Sambuc // Default constructor initializes stream buffer
gzifstream()374*44bedb31SLionel Sambuc gzifstream::gzifstream()
375*44bedb31SLionel Sambuc : std::istream(NULL), sb()
376*44bedb31SLionel Sambuc { this->init(&sb); }
377*44bedb31SLionel Sambuc
378*44bedb31SLionel Sambuc // Initialize stream buffer and open file
gzifstream(const char * name,std::ios_base::openmode mode)379*44bedb31SLionel Sambuc gzifstream::gzifstream(const char* name,
380*44bedb31SLionel Sambuc std::ios_base::openmode mode)
381*44bedb31SLionel Sambuc : std::istream(NULL), sb()
382*44bedb31SLionel Sambuc {
383*44bedb31SLionel Sambuc this->init(&sb);
384*44bedb31SLionel Sambuc this->open(name, mode);
385*44bedb31SLionel Sambuc }
386*44bedb31SLionel Sambuc
387*44bedb31SLionel Sambuc // Initialize stream buffer and attach to file
gzifstream(int fd,std::ios_base::openmode mode)388*44bedb31SLionel Sambuc gzifstream::gzifstream(int fd,
389*44bedb31SLionel Sambuc std::ios_base::openmode mode)
390*44bedb31SLionel Sambuc : std::istream(NULL), sb()
391*44bedb31SLionel Sambuc {
392*44bedb31SLionel Sambuc this->init(&sb);
393*44bedb31SLionel Sambuc this->attach(fd, mode);
394*44bedb31SLionel Sambuc }
395*44bedb31SLionel Sambuc
396*44bedb31SLionel Sambuc // Open file and go into fail() state if unsuccessful
397*44bedb31SLionel Sambuc void
open(const char * name,std::ios_base::openmode mode)398*44bedb31SLionel Sambuc gzifstream::open(const char* name,
399*44bedb31SLionel Sambuc std::ios_base::openmode mode)
400*44bedb31SLionel Sambuc {
401*44bedb31SLionel Sambuc if (!sb.open(name, mode | std::ios_base::in))
402*44bedb31SLionel Sambuc this->setstate(std::ios_base::failbit);
403*44bedb31SLionel Sambuc else
404*44bedb31SLionel Sambuc this->clear();
405*44bedb31SLionel Sambuc }
406*44bedb31SLionel Sambuc
407*44bedb31SLionel Sambuc // Attach to file and go into fail() state if unsuccessful
408*44bedb31SLionel Sambuc void
attach(int fd,std::ios_base::openmode mode)409*44bedb31SLionel Sambuc gzifstream::attach(int fd,
410*44bedb31SLionel Sambuc std::ios_base::openmode mode)
411*44bedb31SLionel Sambuc {
412*44bedb31SLionel Sambuc if (!sb.attach(fd, mode | std::ios_base::in))
413*44bedb31SLionel Sambuc this->setstate(std::ios_base::failbit);
414*44bedb31SLionel Sambuc else
415*44bedb31SLionel Sambuc this->clear();
416*44bedb31SLionel Sambuc }
417*44bedb31SLionel Sambuc
418*44bedb31SLionel Sambuc // Close file
419*44bedb31SLionel Sambuc void
close()420*44bedb31SLionel Sambuc gzifstream::close()
421*44bedb31SLionel Sambuc {
422*44bedb31SLionel Sambuc if (!sb.close())
423*44bedb31SLionel Sambuc this->setstate(std::ios_base::failbit);
424*44bedb31SLionel Sambuc }
425*44bedb31SLionel Sambuc
426*44bedb31SLionel Sambuc /*****************************************************************************/
427*44bedb31SLionel Sambuc
428*44bedb31SLionel Sambuc // Default constructor initializes stream buffer
gzofstream()429*44bedb31SLionel Sambuc gzofstream::gzofstream()
430*44bedb31SLionel Sambuc : std::ostream(NULL), sb()
431*44bedb31SLionel Sambuc { this->init(&sb); }
432*44bedb31SLionel Sambuc
433*44bedb31SLionel Sambuc // Initialize stream buffer and open file
gzofstream(const char * name,std::ios_base::openmode mode)434*44bedb31SLionel Sambuc gzofstream::gzofstream(const char* name,
435*44bedb31SLionel Sambuc std::ios_base::openmode mode)
436*44bedb31SLionel Sambuc : std::ostream(NULL), sb()
437*44bedb31SLionel Sambuc {
438*44bedb31SLionel Sambuc this->init(&sb);
439*44bedb31SLionel Sambuc this->open(name, mode);
440*44bedb31SLionel Sambuc }
441*44bedb31SLionel Sambuc
442*44bedb31SLionel Sambuc // Initialize stream buffer and attach to file
gzofstream(int fd,std::ios_base::openmode mode)443*44bedb31SLionel Sambuc gzofstream::gzofstream(int fd,
444*44bedb31SLionel Sambuc std::ios_base::openmode mode)
445*44bedb31SLionel Sambuc : std::ostream(NULL), sb()
446*44bedb31SLionel Sambuc {
447*44bedb31SLionel Sambuc this->init(&sb);
448*44bedb31SLionel Sambuc this->attach(fd, mode);
449*44bedb31SLionel Sambuc }
450*44bedb31SLionel Sambuc
451*44bedb31SLionel Sambuc // Open file and go into fail() state if unsuccessful
452*44bedb31SLionel Sambuc void
open(const char * name,std::ios_base::openmode mode)453*44bedb31SLionel Sambuc gzofstream::open(const char* name,
454*44bedb31SLionel Sambuc std::ios_base::openmode mode)
455*44bedb31SLionel Sambuc {
456*44bedb31SLionel Sambuc if (!sb.open(name, mode | std::ios_base::out))
457*44bedb31SLionel Sambuc this->setstate(std::ios_base::failbit);
458*44bedb31SLionel Sambuc else
459*44bedb31SLionel Sambuc this->clear();
460*44bedb31SLionel Sambuc }
461*44bedb31SLionel Sambuc
462*44bedb31SLionel Sambuc // Attach to file and go into fail() state if unsuccessful
463*44bedb31SLionel Sambuc void
attach(int fd,std::ios_base::openmode mode)464*44bedb31SLionel Sambuc gzofstream::attach(int fd,
465*44bedb31SLionel Sambuc std::ios_base::openmode mode)
466*44bedb31SLionel Sambuc {
467*44bedb31SLionel Sambuc if (!sb.attach(fd, mode | std::ios_base::out))
468*44bedb31SLionel Sambuc this->setstate(std::ios_base::failbit);
469*44bedb31SLionel Sambuc else
470*44bedb31SLionel Sambuc this->clear();
471*44bedb31SLionel Sambuc }
472*44bedb31SLionel Sambuc
473*44bedb31SLionel Sambuc // Close file
474*44bedb31SLionel Sambuc void
close()475*44bedb31SLionel Sambuc gzofstream::close()
476*44bedb31SLionel Sambuc {
477*44bedb31SLionel Sambuc if (!sb.close())
478*44bedb31SLionel Sambuc this->setstate(std::ios_base::failbit);
479*44bedb31SLionel Sambuc }
480