1275793eaSopenharmony_ci/*
2275793eaSopenharmony_ci * A C++ I/O streams interface to the zlib gz* functions
3275793eaSopenharmony_ci *
4275793eaSopenharmony_ci * by Ludwig Schwardt <schwardt@sun.ac.za>
5275793eaSopenharmony_ci * original version by Kevin Ruland <kevin@rodin.wustl.edu>
6275793eaSopenharmony_ci *
7275793eaSopenharmony_ci * This version is standard-compliant and compatible with gcc 3.x.
8275793eaSopenharmony_ci */
9275793eaSopenharmony_ci
10275793eaSopenharmony_ci#include "zfstream.h"
11275793eaSopenharmony_ci#include <cstring>          // for strcpy, strcat, strlen (mode strings)
12275793eaSopenharmony_ci#include <cstdio>           // for BUFSIZ
13275793eaSopenharmony_ci
14275793eaSopenharmony_ci// Internal buffer sizes (default and "unbuffered" versions)
15275793eaSopenharmony_ci#define BIGBUFSIZE BUFSIZ
16275793eaSopenharmony_ci#define SMALLBUFSIZE 1
17275793eaSopenharmony_ci
18275793eaSopenharmony_ci/*****************************************************************************/
19275793eaSopenharmony_ci
20275793eaSopenharmony_ci// Default constructor
21275793eaSopenharmony_cigzfilebuf::gzfilebuf()
22275793eaSopenharmony_ci: file(NULL), io_mode(std::ios_base::openmode(0)), own_fd(false),
23275793eaSopenharmony_ci  buffer(NULL), buffer_size(BIGBUFSIZE), own_buffer(true)
24275793eaSopenharmony_ci{
25275793eaSopenharmony_ci  // No buffers to start with
26275793eaSopenharmony_ci  this->disable_buffer();
27275793eaSopenharmony_ci}
28275793eaSopenharmony_ci
29275793eaSopenharmony_ci// Destructor
30275793eaSopenharmony_cigzfilebuf::~gzfilebuf()
31275793eaSopenharmony_ci{
32275793eaSopenharmony_ci  // Sync output buffer and close only if responsible for file
33275793eaSopenharmony_ci  // (i.e. attached streams should be left open at this stage)
34275793eaSopenharmony_ci  this->sync();
35275793eaSopenharmony_ci  if (own_fd)
36275793eaSopenharmony_ci    this->close();
37275793eaSopenharmony_ci  // Make sure internal buffer is deallocated
38275793eaSopenharmony_ci  this->disable_buffer();
39275793eaSopenharmony_ci}
40275793eaSopenharmony_ci
41275793eaSopenharmony_ci// Set compression level and strategy
42275793eaSopenharmony_ciint
43275793eaSopenharmony_cigzfilebuf::setcompression(int comp_level,
44275793eaSopenharmony_ci                          int comp_strategy)
45275793eaSopenharmony_ci{
46275793eaSopenharmony_ci  return gzsetparams(file, comp_level, comp_strategy);
47275793eaSopenharmony_ci}
48275793eaSopenharmony_ci
49275793eaSopenharmony_ci// Open gzipped file
50275793eaSopenharmony_cigzfilebuf*
51275793eaSopenharmony_cigzfilebuf::open(const char *name,
52275793eaSopenharmony_ci                std::ios_base::openmode mode)
53275793eaSopenharmony_ci{
54275793eaSopenharmony_ci  // Fail if file already open
55275793eaSopenharmony_ci  if (this->is_open())
56275793eaSopenharmony_ci    return NULL;
57275793eaSopenharmony_ci  // Don't support simultaneous read/write access (yet)
58275793eaSopenharmony_ci  if ((mode & std::ios_base::in) && (mode & std::ios_base::out))
59275793eaSopenharmony_ci    return NULL;
60275793eaSopenharmony_ci
61275793eaSopenharmony_ci  // Build mode string for gzopen and check it [27.8.1.3.2]
62275793eaSopenharmony_ci  char char_mode[6] = "\0\0\0\0\0";
63275793eaSopenharmony_ci  if (!this->open_mode(mode, char_mode))
64275793eaSopenharmony_ci    return NULL;
65275793eaSopenharmony_ci
66275793eaSopenharmony_ci  // Attempt to open file
67275793eaSopenharmony_ci  if ((file = gzopen(name, char_mode)) == NULL)
68275793eaSopenharmony_ci    return NULL;
69275793eaSopenharmony_ci
70275793eaSopenharmony_ci  // On success, allocate internal buffer and set flags
71275793eaSopenharmony_ci  this->enable_buffer();
72275793eaSopenharmony_ci  io_mode = mode;
73275793eaSopenharmony_ci  own_fd = true;
74275793eaSopenharmony_ci  return this;
75275793eaSopenharmony_ci}
76275793eaSopenharmony_ci
77275793eaSopenharmony_ci// Attach to gzipped file
78275793eaSopenharmony_cigzfilebuf*
79275793eaSopenharmony_cigzfilebuf::attach(int fd,
80275793eaSopenharmony_ci                  std::ios_base::openmode mode)
81275793eaSopenharmony_ci{
82275793eaSopenharmony_ci  // Fail if file already open
83275793eaSopenharmony_ci  if (this->is_open())
84275793eaSopenharmony_ci    return NULL;
85275793eaSopenharmony_ci  // Don't support simultaneous read/write access (yet)
86275793eaSopenharmony_ci  if ((mode & std::ios_base::in) && (mode & std::ios_base::out))
87275793eaSopenharmony_ci    return NULL;
88275793eaSopenharmony_ci
89275793eaSopenharmony_ci  // Build mode string for gzdopen and check it [27.8.1.3.2]
90275793eaSopenharmony_ci  char char_mode[6] = "\0\0\0\0\0";
91275793eaSopenharmony_ci  if (!this->open_mode(mode, char_mode))
92275793eaSopenharmony_ci    return NULL;
93275793eaSopenharmony_ci
94275793eaSopenharmony_ci  // Attempt to attach to file
95275793eaSopenharmony_ci  if ((file = gzdopen(fd, char_mode)) == NULL)
96275793eaSopenharmony_ci    return NULL;
97275793eaSopenharmony_ci
98275793eaSopenharmony_ci  // On success, allocate internal buffer and set flags
99275793eaSopenharmony_ci  this->enable_buffer();
100275793eaSopenharmony_ci  io_mode = mode;
101275793eaSopenharmony_ci  own_fd = false;
102275793eaSopenharmony_ci  return this;
103275793eaSopenharmony_ci}
104275793eaSopenharmony_ci
105275793eaSopenharmony_ci// Close gzipped file
106275793eaSopenharmony_cigzfilebuf*
107275793eaSopenharmony_cigzfilebuf::close()
108275793eaSopenharmony_ci{
109275793eaSopenharmony_ci  // Fail immediately if no file is open
110275793eaSopenharmony_ci  if (!this->is_open())
111275793eaSopenharmony_ci    return NULL;
112275793eaSopenharmony_ci  // Assume success
113275793eaSopenharmony_ci  gzfilebuf* retval = this;
114275793eaSopenharmony_ci  // Attempt to sync and close gzipped file
115275793eaSopenharmony_ci  if (this->sync() == -1)
116275793eaSopenharmony_ci    retval = NULL;
117275793eaSopenharmony_ci  if (gzclose(file) < 0)
118275793eaSopenharmony_ci    retval = NULL;
119275793eaSopenharmony_ci  // File is now gone anyway (postcondition [27.8.1.3.8])
120275793eaSopenharmony_ci  file = NULL;
121275793eaSopenharmony_ci  own_fd = false;
122275793eaSopenharmony_ci  // Destroy internal buffer if it exists
123275793eaSopenharmony_ci  this->disable_buffer();
124275793eaSopenharmony_ci  return retval;
125275793eaSopenharmony_ci}
126275793eaSopenharmony_ci
127275793eaSopenharmony_ci/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
128275793eaSopenharmony_ci
129275793eaSopenharmony_ci// Convert int open mode to mode string
130275793eaSopenharmony_cibool
131275793eaSopenharmony_cigzfilebuf::open_mode(std::ios_base::openmode mode,
132275793eaSopenharmony_ci                     char* c_mode) const
133275793eaSopenharmony_ci{
134275793eaSopenharmony_ci  bool testb = mode & std::ios_base::binary;
135275793eaSopenharmony_ci  bool testi = mode & std::ios_base::in;
136275793eaSopenharmony_ci  bool testo = mode & std::ios_base::out;
137275793eaSopenharmony_ci  bool testt = mode & std::ios_base::trunc;
138275793eaSopenharmony_ci  bool testa = mode & std::ios_base::app;
139275793eaSopenharmony_ci
140275793eaSopenharmony_ci  // Check for valid flag combinations - see [27.8.1.3.2] (Table 92)
141275793eaSopenharmony_ci  // Original zfstream hardcoded the compression level to maximum here...
142275793eaSopenharmony_ci  // Double the time for less than 1% size improvement seems
143275793eaSopenharmony_ci  // excessive though - keeping it at the default level
144275793eaSopenharmony_ci  // To change back, just append "9" to the next three mode strings
145275793eaSopenharmony_ci  if (!testi && testo && !testt && !testa)
146275793eaSopenharmony_ci    strcpy(c_mode, "w");
147275793eaSopenharmony_ci  if (!testi && testo && !testt && testa)
148275793eaSopenharmony_ci    strcpy(c_mode, "a");
149275793eaSopenharmony_ci  if (!testi && testo && testt && !testa)
150275793eaSopenharmony_ci    strcpy(c_mode, "w");
151275793eaSopenharmony_ci  if (testi && !testo && !testt && !testa)
152275793eaSopenharmony_ci    strcpy(c_mode, "r");
153275793eaSopenharmony_ci  // No read/write mode yet
154275793eaSopenharmony_ci//  if (testi && testo && !testt && !testa)
155275793eaSopenharmony_ci//    strcpy(c_mode, "r+");
156275793eaSopenharmony_ci//  if (testi && testo && testt && !testa)
157275793eaSopenharmony_ci//    strcpy(c_mode, "w+");
158275793eaSopenharmony_ci
159275793eaSopenharmony_ci  // Mode string should be empty for invalid combination of flags
160275793eaSopenharmony_ci  if (strlen(c_mode) == 0)
161275793eaSopenharmony_ci    return false;
162275793eaSopenharmony_ci  if (testb)
163275793eaSopenharmony_ci    strcat(c_mode, "b");
164275793eaSopenharmony_ci  return true;
165275793eaSopenharmony_ci}
166275793eaSopenharmony_ci
167275793eaSopenharmony_ci// Determine number of characters in internal get buffer
168275793eaSopenharmony_cistd::streamsize
169275793eaSopenharmony_cigzfilebuf::showmanyc()
170275793eaSopenharmony_ci{
171275793eaSopenharmony_ci  // Calls to underflow will fail if file not opened for reading
172275793eaSopenharmony_ci  if (!this->is_open() || !(io_mode & std::ios_base::in))
173275793eaSopenharmony_ci    return -1;
174275793eaSopenharmony_ci  // Make sure get area is in use
175275793eaSopenharmony_ci  if (this->gptr() && (this->gptr() < this->egptr()))
176275793eaSopenharmony_ci    return std::streamsize(this->egptr() - this->gptr());
177275793eaSopenharmony_ci  else
178275793eaSopenharmony_ci    return 0;
179275793eaSopenharmony_ci}
180275793eaSopenharmony_ci
181275793eaSopenharmony_ci// Fill get area from gzipped file
182275793eaSopenharmony_cigzfilebuf::int_type
183275793eaSopenharmony_cigzfilebuf::underflow()
184275793eaSopenharmony_ci{
185275793eaSopenharmony_ci  // If something is left in the get area by chance, return it
186275793eaSopenharmony_ci  // (this shouldn't normally happen, as underflow is only supposed
187275793eaSopenharmony_ci  // to be called when gptr >= egptr, but it serves as error check)
188275793eaSopenharmony_ci  if (this->gptr() && (this->gptr() < this->egptr()))
189275793eaSopenharmony_ci    return traits_type::to_int_type(*(this->gptr()));
190275793eaSopenharmony_ci
191275793eaSopenharmony_ci  // If the file hasn't been opened for reading, produce error
192275793eaSopenharmony_ci  if (!this->is_open() || !(io_mode & std::ios_base::in))
193275793eaSopenharmony_ci    return traits_type::eof();
194275793eaSopenharmony_ci
195275793eaSopenharmony_ci  // Attempt to fill internal buffer from gzipped file
196275793eaSopenharmony_ci  // (buffer must be guaranteed to exist...)
197275793eaSopenharmony_ci  int bytes_read = gzread(file, buffer, buffer_size);
198275793eaSopenharmony_ci  // Indicates error or EOF
199275793eaSopenharmony_ci  if (bytes_read <= 0)
200275793eaSopenharmony_ci  {
201275793eaSopenharmony_ci    // Reset get area
202275793eaSopenharmony_ci    this->setg(buffer, buffer, buffer);
203275793eaSopenharmony_ci    return traits_type::eof();
204275793eaSopenharmony_ci  }
205275793eaSopenharmony_ci  // Make all bytes read from file available as get area
206275793eaSopenharmony_ci  this->setg(buffer, buffer, buffer + bytes_read);
207275793eaSopenharmony_ci
208275793eaSopenharmony_ci  // Return next character in get area
209275793eaSopenharmony_ci  return traits_type::to_int_type(*(this->gptr()));
210275793eaSopenharmony_ci}
211275793eaSopenharmony_ci
212275793eaSopenharmony_ci// Write put area to gzipped file
213275793eaSopenharmony_cigzfilebuf::int_type
214275793eaSopenharmony_cigzfilebuf::overflow(int_type c)
215275793eaSopenharmony_ci{
216275793eaSopenharmony_ci  // Determine whether put area is in use
217275793eaSopenharmony_ci  if (this->pbase())
218275793eaSopenharmony_ci  {
219275793eaSopenharmony_ci    // Double-check pointer range
220275793eaSopenharmony_ci    if (this->pptr() > this->epptr() || this->pptr() < this->pbase())
221275793eaSopenharmony_ci      return traits_type::eof();
222275793eaSopenharmony_ci    // Add extra character to buffer if not EOF
223275793eaSopenharmony_ci    if (!traits_type::eq_int_type(c, traits_type::eof()))
224275793eaSopenharmony_ci    {
225275793eaSopenharmony_ci      *(this->pptr()) = traits_type::to_char_type(c);
226275793eaSopenharmony_ci      this->pbump(1);
227275793eaSopenharmony_ci    }
228275793eaSopenharmony_ci    // Number of characters to write to file
229275793eaSopenharmony_ci    int bytes_to_write = this->pptr() - this->pbase();
230275793eaSopenharmony_ci    // Overflow doesn't fail if nothing is to be written
231275793eaSopenharmony_ci    if (bytes_to_write > 0)
232275793eaSopenharmony_ci    {
233275793eaSopenharmony_ci      // If the file hasn't been opened for writing, produce error
234275793eaSopenharmony_ci      if (!this->is_open() || !(io_mode & std::ios_base::out))
235275793eaSopenharmony_ci        return traits_type::eof();
236275793eaSopenharmony_ci      // If gzipped file won't accept all bytes written to it, fail
237275793eaSopenharmony_ci      if (gzwrite(file, this->pbase(), bytes_to_write) != bytes_to_write)
238275793eaSopenharmony_ci        return traits_type::eof();
239275793eaSopenharmony_ci      // Reset next pointer to point to pbase on success
240275793eaSopenharmony_ci      this->pbump(-bytes_to_write);
241275793eaSopenharmony_ci    }
242275793eaSopenharmony_ci  }
243275793eaSopenharmony_ci  // Write extra character to file if not EOF
244275793eaSopenharmony_ci  else if (!traits_type::eq_int_type(c, traits_type::eof()))
245275793eaSopenharmony_ci  {
246275793eaSopenharmony_ci    // If the file hasn't been opened for writing, produce error
247275793eaSopenharmony_ci    if (!this->is_open() || !(io_mode & std::ios_base::out))
248275793eaSopenharmony_ci      return traits_type::eof();
249275793eaSopenharmony_ci    // Impromptu char buffer (allows "unbuffered" output)
250275793eaSopenharmony_ci    char_type last_char = traits_type::to_char_type(c);
251275793eaSopenharmony_ci    // If gzipped file won't accept this character, fail
252275793eaSopenharmony_ci    if (gzwrite(file, &last_char, 1) != 1)
253275793eaSopenharmony_ci      return traits_type::eof();
254275793eaSopenharmony_ci  }
255275793eaSopenharmony_ci
256275793eaSopenharmony_ci  // If you got here, you have succeeded (even if c was EOF)
257275793eaSopenharmony_ci  // The return value should therefore be non-EOF
258275793eaSopenharmony_ci  if (traits_type::eq_int_type(c, traits_type::eof()))
259275793eaSopenharmony_ci    return traits_type::not_eof(c);
260275793eaSopenharmony_ci  else
261275793eaSopenharmony_ci    return c;
262275793eaSopenharmony_ci}
263275793eaSopenharmony_ci
264275793eaSopenharmony_ci// Assign new buffer
265275793eaSopenharmony_cistd::streambuf*
266275793eaSopenharmony_cigzfilebuf::setbuf(char_type* p,
267275793eaSopenharmony_ci                  std::streamsize n)
268275793eaSopenharmony_ci{
269275793eaSopenharmony_ci  // First make sure stuff is sync'ed, for safety
270275793eaSopenharmony_ci  if (this->sync() == -1)
271275793eaSopenharmony_ci    return NULL;
272275793eaSopenharmony_ci  // If buffering is turned off on purpose via setbuf(0,0), still allocate one...
273275793eaSopenharmony_ci  // "Unbuffered" only really refers to put [27.8.1.4.10], while get needs at
274275793eaSopenharmony_ci  // least a buffer of size 1 (very inefficient though, therefore make it bigger?)
275275793eaSopenharmony_ci  // This follows from [27.5.2.4.3]/12 (gptr needs to point at something, it seems)
276275793eaSopenharmony_ci  if (!p || !n)
277275793eaSopenharmony_ci  {
278275793eaSopenharmony_ci    // Replace existing buffer (if any) with small internal buffer
279275793eaSopenharmony_ci    this->disable_buffer();
280275793eaSopenharmony_ci    buffer = NULL;
281275793eaSopenharmony_ci    buffer_size = 0;
282275793eaSopenharmony_ci    own_buffer = true;
283275793eaSopenharmony_ci    this->enable_buffer();
284275793eaSopenharmony_ci  }
285275793eaSopenharmony_ci  else
286275793eaSopenharmony_ci  {
287275793eaSopenharmony_ci    // Replace existing buffer (if any) with external buffer
288275793eaSopenharmony_ci    this->disable_buffer();
289275793eaSopenharmony_ci    buffer = p;
290275793eaSopenharmony_ci    buffer_size = n;
291275793eaSopenharmony_ci    own_buffer = false;
292275793eaSopenharmony_ci    this->enable_buffer();
293275793eaSopenharmony_ci  }
294275793eaSopenharmony_ci  return this;
295275793eaSopenharmony_ci}
296275793eaSopenharmony_ci
297275793eaSopenharmony_ci// Write put area to gzipped file (i.e. ensures that put area is empty)
298275793eaSopenharmony_ciint
299275793eaSopenharmony_cigzfilebuf::sync()
300275793eaSopenharmony_ci{
301275793eaSopenharmony_ci  return traits_type::eq_int_type(this->overflow(), traits_type::eof()) ? -1 : 0;
302275793eaSopenharmony_ci}
303275793eaSopenharmony_ci
304275793eaSopenharmony_ci/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
305275793eaSopenharmony_ci
306275793eaSopenharmony_ci// Allocate internal buffer
307275793eaSopenharmony_civoid
308275793eaSopenharmony_cigzfilebuf::enable_buffer()
309275793eaSopenharmony_ci{
310275793eaSopenharmony_ci  // If internal buffer required, allocate one
311275793eaSopenharmony_ci  if (own_buffer && !buffer)
312275793eaSopenharmony_ci  {
313275793eaSopenharmony_ci    // Check for buffered vs. "unbuffered"
314275793eaSopenharmony_ci    if (buffer_size > 0)
315275793eaSopenharmony_ci    {
316275793eaSopenharmony_ci      // Allocate internal buffer
317275793eaSopenharmony_ci      buffer = new char_type[buffer_size];
318275793eaSopenharmony_ci      // Get area starts empty and will be expanded by underflow as need arises
319275793eaSopenharmony_ci      this->setg(buffer, buffer, buffer);
320275793eaSopenharmony_ci      // Setup entire internal buffer as put area.
321275793eaSopenharmony_ci      // The one-past-end pointer actually points to the last element of the buffer,
322275793eaSopenharmony_ci      // so that overflow(c) can safely add the extra character c to the sequence.
323275793eaSopenharmony_ci      // These pointers remain in place for the duration of the buffer
324275793eaSopenharmony_ci      this->setp(buffer, buffer + buffer_size - 1);
325275793eaSopenharmony_ci    }
326275793eaSopenharmony_ci    else
327275793eaSopenharmony_ci    {
328275793eaSopenharmony_ci      // Even in "unbuffered" case, (small?) get buffer is still required
329275793eaSopenharmony_ci      buffer_size = SMALLBUFSIZE;
330275793eaSopenharmony_ci      buffer = new char_type[buffer_size];
331275793eaSopenharmony_ci      this->setg(buffer, buffer, buffer);
332275793eaSopenharmony_ci      // "Unbuffered" means no put buffer
333275793eaSopenharmony_ci      this->setp(0, 0);
334275793eaSopenharmony_ci    }
335275793eaSopenharmony_ci  }
336275793eaSopenharmony_ci  else
337275793eaSopenharmony_ci  {
338275793eaSopenharmony_ci    // If buffer already allocated, reset buffer pointers just to make sure no
339275793eaSopenharmony_ci    // stale chars are lying around
340275793eaSopenharmony_ci    this->setg(buffer, buffer, buffer);
341275793eaSopenharmony_ci    this->setp(buffer, buffer + buffer_size - 1);
342275793eaSopenharmony_ci  }
343275793eaSopenharmony_ci}
344275793eaSopenharmony_ci
345275793eaSopenharmony_ci// Destroy internal buffer
346275793eaSopenharmony_civoid
347275793eaSopenharmony_cigzfilebuf::disable_buffer()
348275793eaSopenharmony_ci{
349275793eaSopenharmony_ci  // If internal buffer exists, deallocate it
350275793eaSopenharmony_ci  if (own_buffer && buffer)
351275793eaSopenharmony_ci  {
352275793eaSopenharmony_ci    // Preserve unbuffered status by zeroing size
353275793eaSopenharmony_ci    if (!this->pbase())
354275793eaSopenharmony_ci      buffer_size = 0;
355275793eaSopenharmony_ci    delete[] buffer;
356275793eaSopenharmony_ci    buffer = NULL;
357275793eaSopenharmony_ci    this->setg(0, 0, 0);
358275793eaSopenharmony_ci    this->setp(0, 0);
359275793eaSopenharmony_ci  }
360275793eaSopenharmony_ci  else
361275793eaSopenharmony_ci  {
362275793eaSopenharmony_ci    // Reset buffer pointers to initial state if external buffer exists
363275793eaSopenharmony_ci    this->setg(buffer, buffer, buffer);
364275793eaSopenharmony_ci    if (buffer)
365275793eaSopenharmony_ci      this->setp(buffer, buffer + buffer_size - 1);
366275793eaSopenharmony_ci    else
367275793eaSopenharmony_ci      this->setp(0, 0);
368275793eaSopenharmony_ci  }
369275793eaSopenharmony_ci}
370275793eaSopenharmony_ci
371275793eaSopenharmony_ci/*****************************************************************************/
372275793eaSopenharmony_ci
373275793eaSopenharmony_ci// Default constructor initializes stream buffer
374275793eaSopenharmony_cigzifstream::gzifstream()
375275793eaSopenharmony_ci: std::istream(NULL), sb()
376275793eaSopenharmony_ci{ this->init(&sb); }
377275793eaSopenharmony_ci
378275793eaSopenharmony_ci// Initialize stream buffer and open file
379275793eaSopenharmony_cigzifstream::gzifstream(const char* name,
380275793eaSopenharmony_ci                       std::ios_base::openmode mode)
381275793eaSopenharmony_ci: std::istream(NULL), sb()
382275793eaSopenharmony_ci{
383275793eaSopenharmony_ci  this->init(&sb);
384275793eaSopenharmony_ci  this->open(name, mode);
385275793eaSopenharmony_ci}
386275793eaSopenharmony_ci
387275793eaSopenharmony_ci// Initialize stream buffer and attach to file
388275793eaSopenharmony_cigzifstream::gzifstream(int fd,
389275793eaSopenharmony_ci                       std::ios_base::openmode mode)
390275793eaSopenharmony_ci: std::istream(NULL), sb()
391275793eaSopenharmony_ci{
392275793eaSopenharmony_ci  this->init(&sb);
393275793eaSopenharmony_ci  this->attach(fd, mode);
394275793eaSopenharmony_ci}
395275793eaSopenharmony_ci
396275793eaSopenharmony_ci// Open file and go into fail() state if unsuccessful
397275793eaSopenharmony_civoid
398275793eaSopenharmony_cigzifstream::open(const char* name,
399275793eaSopenharmony_ci                 std::ios_base::openmode mode)
400275793eaSopenharmony_ci{
401275793eaSopenharmony_ci  if (!sb.open(name, mode | std::ios_base::in))
402275793eaSopenharmony_ci    this->setstate(std::ios_base::failbit);
403275793eaSopenharmony_ci  else
404275793eaSopenharmony_ci    this->clear();
405275793eaSopenharmony_ci}
406275793eaSopenharmony_ci
407275793eaSopenharmony_ci// Attach to file and go into fail() state if unsuccessful
408275793eaSopenharmony_civoid
409275793eaSopenharmony_cigzifstream::attach(int fd,
410275793eaSopenharmony_ci                   std::ios_base::openmode mode)
411275793eaSopenharmony_ci{
412275793eaSopenharmony_ci  if (!sb.attach(fd, mode | std::ios_base::in))
413275793eaSopenharmony_ci    this->setstate(std::ios_base::failbit);
414275793eaSopenharmony_ci  else
415275793eaSopenharmony_ci    this->clear();
416275793eaSopenharmony_ci}
417275793eaSopenharmony_ci
418275793eaSopenharmony_ci// Close file
419275793eaSopenharmony_civoid
420275793eaSopenharmony_cigzifstream::close()
421275793eaSopenharmony_ci{
422275793eaSopenharmony_ci  if (!sb.close())
423275793eaSopenharmony_ci    this->setstate(std::ios_base::failbit);
424275793eaSopenharmony_ci}
425275793eaSopenharmony_ci
426275793eaSopenharmony_ci/*****************************************************************************/
427275793eaSopenharmony_ci
428275793eaSopenharmony_ci// Default constructor initializes stream buffer
429275793eaSopenharmony_cigzofstream::gzofstream()
430275793eaSopenharmony_ci: std::ostream(NULL), sb()
431275793eaSopenharmony_ci{ this->init(&sb); }
432275793eaSopenharmony_ci
433275793eaSopenharmony_ci// Initialize stream buffer and open file
434275793eaSopenharmony_cigzofstream::gzofstream(const char* name,
435275793eaSopenharmony_ci                       std::ios_base::openmode mode)
436275793eaSopenharmony_ci: std::ostream(NULL), sb()
437275793eaSopenharmony_ci{
438275793eaSopenharmony_ci  this->init(&sb);
439275793eaSopenharmony_ci  this->open(name, mode);
440275793eaSopenharmony_ci}
441275793eaSopenharmony_ci
442275793eaSopenharmony_ci// Initialize stream buffer and attach to file
443275793eaSopenharmony_cigzofstream::gzofstream(int fd,
444275793eaSopenharmony_ci                       std::ios_base::openmode mode)
445275793eaSopenharmony_ci: std::ostream(NULL), sb()
446275793eaSopenharmony_ci{
447275793eaSopenharmony_ci  this->init(&sb);
448275793eaSopenharmony_ci  this->attach(fd, mode);
449275793eaSopenharmony_ci}
450275793eaSopenharmony_ci
451275793eaSopenharmony_ci// Open file and go into fail() state if unsuccessful
452275793eaSopenharmony_civoid
453275793eaSopenharmony_cigzofstream::open(const char* name,
454275793eaSopenharmony_ci                 std::ios_base::openmode mode)
455275793eaSopenharmony_ci{
456275793eaSopenharmony_ci  if (!sb.open(name, mode | std::ios_base::out))
457275793eaSopenharmony_ci    this->setstate(std::ios_base::failbit);
458275793eaSopenharmony_ci  else
459275793eaSopenharmony_ci    this->clear();
460275793eaSopenharmony_ci}
461275793eaSopenharmony_ci
462275793eaSopenharmony_ci// Attach to file and go into fail() state if unsuccessful
463275793eaSopenharmony_civoid
464275793eaSopenharmony_cigzofstream::attach(int fd,
465275793eaSopenharmony_ci                   std::ios_base::openmode mode)
466275793eaSopenharmony_ci{
467275793eaSopenharmony_ci  if (!sb.attach(fd, mode | std::ios_base::out))
468275793eaSopenharmony_ci    this->setstate(std::ios_base::failbit);
469275793eaSopenharmony_ci  else
470275793eaSopenharmony_ci    this->clear();
471275793eaSopenharmony_ci}
472275793eaSopenharmony_ci
473275793eaSopenharmony_ci// Close file
474275793eaSopenharmony_civoid
475275793eaSopenharmony_cigzofstream::close()
476275793eaSopenharmony_ci{
477275793eaSopenharmony_ci  if (!sb.close())
478275793eaSopenharmony_ci    this->setstate(std::ios_base::failbit);
479275793eaSopenharmony_ci}
480