GNU Octave  8.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
gzfstream.h
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2005-2023 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 /*
27 
28  This file is adapted from the zlib 1.2.2 contrib/iostream3 code,
29  written by
30 
31  Ludwig Schwardt <schwardt@sun.ac.za>
32  original version by Kevin Ruland <kevin@rodin.wustl.edu>
33 
34 */
35 
36 #if ! defined (octave_zfsstream_h)
37 #define octave_zfsstream_h 1
38 
39 #include "octave-config.h"
40 
41 #if defined (HAVE_ZLIB)
42 
43 #include <iosfwd>
44 
45 #include "zlib.h"
46 
47 /**
48  * @brief Gzipped file stream buffer class.
49  *
50  * This class implements basic_filebuf for gzipped files. It doesn't yet
51  * support seeking (allowed by zlib but slow/limited), putback and read/write
52  * access * (tricky). Otherwise, it attempts to be a drop-in replacement for
53  * the standard file streambuf.
54 */
55 class gzfilebuf : public std::streambuf
56 {
57 public:
58  // Default constructor.
59  gzfilebuf ();
60 
61  // No copying!
62 
63  gzfilebuf (const gzfilebuf&) = delete;
64 
65  gzfilebuf& operator = (const gzfilebuf&) = delete;
66 
67  // Destructor.
68  virtual ~gzfilebuf ();
69 
70  /**
71  * @brief Set compression level and strategy on the fly.
72  * @param comp_level Compression level (see zlib.h for allowed values)
73  * @param comp_strategy Compression strategy (see zlib.h for allowed values)
74  * @return Z_OK on success, Z_STREAM_ERROR otherwise.
75  *
76  * Unfortunately, these parameters cannot be modified separately, as the
77  * previous zfstream version assumed. Since the strategy is seldom changed,
78  * it can default and setcompression(level) then becomes like the old
79  * setcompressionlevel(level).
80  */
81  int
82  setcompression (int comp_level,
83  int comp_strategy = Z_DEFAULT_STRATEGY);
84 
85  /**
86  * @brief Check if file is open.
87  * @return True if file is open.
88  */
89  bool
90  is_open () const { return (m_file != nullptr); }
91 
92  /**
93  * @brief Open gzipped file.
94  * @param name Filename.
95  * @param mode Open mode flags.
96  * @return @c this on success, NULL on failure.
97  */
98  gzfilebuf *
99  open (const char *name,
100  std::ios_base::openmode mode);
101 
102  /**
103  * @brief Attach to already open gzipped file.
104  * @param fd File descriptor.
105  * @param mode Open mode flags.
106  * @return @c this on success, NULL on failure.
107  */
108  gzfilebuf *
109  attach (int fd,
110  std::ios_base::openmode mode);
111 
112  /**
113  * @brief Close gzipped file.
114  * @return @c this on success, NULL on failure.
115  */
116  gzfilebuf *
117  close ();
118 
119 protected:
120  /**
121  * @brief Convert ios open mode int to mode string used by zlib.
122  * @return True if valid mode flag combination.
123  */
124  bool
125  open_mode (std::ios_base::openmode mode,
126  char *c_mode) const;
127 
128  /**
129  * @brief Number of characters available in stream buffer.
130  * @return Number of characters.
131  *
132  * This indicates number of characters in get area of stream buffer.
133  * These characters can be read without accessing the gzipped file.
134  */
135  virtual std::streamsize
136  showmanyc ();
137 
138  /**
139  * @brief Fill get area from gzipped file.
140  * @return First character in get area on success, EOF on error.
141  *
142  * This actually reads characters from gzipped file to stream
143  * buffer. Always buffered.
144  */
145  virtual int_type
146  underflow ();
147 
148  /**
149  * @brief Write put area to gzipped file.
150  * @param c Extra character to add to buffer contents.
151  * @return Non-EOF on success, EOF on error.
152  *
153  * This actually writes characters in stream buffer to
154  * gzipped file. With unbuffered output this is done one
155  * character at a time.
156  */
157  virtual int_type
158  overflow (int_type c = traits_type::eof ());
159 
160  /**
161  * @brief Installs external stream buffer.
162  * @param p Pointer to char buffer.
163  * @param n Size of external buffer.
164  * @return @c this on success, NULL on failure.
165  *
166  * Call setbuf(0,0) to enable unbuffered output.
167  */
168  virtual std::streambuf *
169  setbuf (char_type *p,
170  std::streamsize n);
171 
172  /**
173  * @brief Flush stream buffer to file.
174  * @return 0 on success, -1 on error.
175  *
176  * This calls underflow(EOF) to do the job.
177  */
178  virtual int
179  sync ();
180 
181  /**
182  * @brief Alters the stream positions.
183  *
184  * Each derived class provides its own appropriate behavior.
185  */
186  virtual pos_type
187  seekoff (off_type off, std::ios_base::seekdir way,
188  std::ios_base::openmode mode =
189  std::ios_base::in | std::ios_base::out);
190 
191  /**
192  * @brief Alters the stream positions.
193  *
194  * Each derived class provides its own appropriate behavior.
195  */
196  virtual pos_type
197  seekpos (pos_type sp, std::ios_base::openmode mode =
198  std::ios_base::in | std::ios_base::out);
199 
200  virtual int_type
201  pbackfail (int_type c = traits_type::eof ());
202 
203 //
204 // Some future enhancements
205 //
206 // virtual int_type uflow();
207 // virtual int_type pbackfail(int_type c = traits_type::eof());
208 
209 private:
210 
211  /**
212  * @brief Allocate internal buffer.
213  *
214  * This function is safe to call multiple times. It will ensure
215  * that a proper internal buffer exists if it is required. If the
216  * buffer already exists or is external, the buffer pointers will be
217  * reset to their original state.
218  */
219  void
220  enable_buffer ();
221 
222  /**
223  * @brief Destroy internal buffer.
224  *
225  * This function is safe to call multiple times. It will ensure
226  * that the internal buffer is deallocated if it exists. In any
227  * case, it will also reset the buffer pointers.
228  */
229  void
230  disable_buffer ();
231 
232  /**
233  * Underlying file pointer.
234  */
235  gzFile m_file;
236 
237  /**
238  * Mode in which file was opened.
239  */
240  std::ios_base::openmode m_io_mode;
241 
242  /**
243  * @brief True if this object owns file descriptor.
244  *
245  * This makes the class responsible for closing the file
246  * upon destruction.
247  */
248  bool m_own_fd;
249 
250  /**
251  * @brief Stream buffer.
252  *
253  * For simplicity this remains allocated on the free store for the
254  * entire life span of the gzfilebuf object, unless replaced by setbuf.
255  */
256  char_type *m_buffer;
257 
258  /**
259  * @brief Stream buffer size.
260  *
261  * Defaults to system default buffer size (typically 8192 bytes).
262  * Modified by setbuf.
263  */
264  std::streamsize m_buffer_size;
265 
266  /**
267  * @brief True if this object owns stream buffer.
268  *
269  * This makes the class responsible for deleting the buffer
270  * upon destruction.
271  */
273 };
274 
275 /**
276  * @brief Gzipped file input stream class.
277  *
278  * This class implements ifstream for gzipped files. Seeking and putback
279  * is not supported yet.
280 */
281 class gzifstream : public std::istream
282 {
283 public:
284  // Default constructor
285  gzifstream ();
286 
287  /**
288  * @brief Construct stream on gzipped file to be opened.
289  * @param name Filename.
290  * @param mode Open mode flags (forced to contain ios::in).
291  */
292  explicit
293  gzifstream (const char *name,
294  std::ios_base::openmode mode = std::ios_base::in);
295 
296  /**
297  * @brief Construct stream on already open gzipped file.
298  * @param fd File descriptor.
299  * @param mode Open mode flags (forced to contain ios::in).
300  */
301  explicit
302  gzifstream (int fd,
303  std::ios_base::openmode mode = std::ios_base::in);
304 
305  /**
306  * Obtain underlying stream buffer.
307  */
308  gzfilebuf *
309  rdbuf () const
310  { return const_cast<gzfilebuf *>(&m_sb); }
311 
312  /**
313  * @brief Check if file is open.
314  * @return True if file is open.
315  */
316  bool
317  is_open () { return m_sb.is_open (); }
318 
319  /**
320  * @brief Open gzipped file.
321  * @param name Filename.
322  * @param mode Open mode flags (forced to contain ios::in).
323  *
324  * Stream will be in state good() if file opens successfully;
325  * otherwise in state fail(). This differs from the behavior of
326  * ifstream, which never sets the state to good() and therefore
327  * won't allow you to reuse the stream for a second file unless
328  * you manually clear() the state. The choice is a matter of
329  * convenience.
330  */
331  void
332  open (const char *name,
333  std::ios_base::openmode mode = std::ios_base::in);
334 
335  /**
336  * @brief Attach to already open gzipped file.
337  * @param fd File descriptor.
338  * @param mode Open mode flags (forced to contain ios::in).
339  *
340  * Stream will be in state good() if attach succeeded; otherwise
341  * in state fail().
342  */
343  void
344  attach (int fd,
345  std::ios_base::openmode mode = std::ios_base::in);
346 
347  /**
348  * @brief Close gzipped file.
349  *
350  * Stream will be in state fail() if close failed.
351  */
352  void
353  close ();
354 
355 private:
356  /**
357  * Underlying stream buffer.
358  */
360 };
361 
362 /**
363  * @brief Gzipped file output stream class.
364  *
365  * This class implements ofstream for gzipped files. Seeking and putback
366  * is not supported yet.
367 */
368 class gzofstream : public std::ostream
369 {
370 public:
371  // Default constructor
372  gzofstream ();
373 
374  /**
375  * @brief Construct stream on gzipped file to be opened.
376  * @param name Filename.
377  * @param mode Open mode flags (forced to contain ios::out).
378  */
379  explicit
380  gzofstream (const char *name,
381  std::ios_base::openmode mode = std::ios_base::out);
382 
383  /**
384  * @brief Construct stream on already open gzipped file.
385  * @param fd File descriptor.
386  * @param mode Open mode flags (forced to contain ios::out).
387  */
388  explicit
389  gzofstream (int fd,
390  std::ios_base::openmode mode = std::ios_base::out);
391 
392  /**
393  * Obtain underlying stream buffer.
394  */
395  gzfilebuf *
396  rdbuf () const
397  { return const_cast<gzfilebuf *>(&m_sb); }
398 
399  /**
400  * @brief Check if file is open.
401  * @return True if file is open.
402  */
403  bool
404  is_open () { return m_sb.is_open (); }
405 
406  /**
407  * @brief Open gzipped file.
408  * @param name Filename.
409  * @param mode Open mode flags (forced to contain ios::out).
410  *
411  * Stream will be in state good() if file opens successfully;
412  * otherwise in state fail(). This differs from the behavior of
413  * ofstream, which never sets the state to good() and therefore
414  * won't allow you to reuse the stream for a second file unless
415  * you manually clear() the state. The choice is a matter of
416  * convenience.
417  */
418  void
419  open (const char *name,
420  std::ios_base::openmode mode = std::ios_base::out);
421 
422  /**
423  * @brief Attach to already open gzipped file.
424  * @param fd File descriptor.
425  * @param mode Open mode flags (forced to contain ios::out).
426  *
427  * Stream will be in state good() if attach succeeded; otherwise
428  * in state fail().
429  */
430  void
431  attach (int fd,
432  std::ios_base::openmode mode = std::ios_base::out);
433 
434  /**
435  * @brief Close gzipped file.
436  *
437  * Stream will be in state fail() if close failed.
438  */
439  void
440  close ();
441 
442 private:
443  /**
444  * Underlying stream buffer.
445  */
447 };
448 
449 /**
450  * @brief Gzipped file output stream manipulator class.
451  *
452  * This class defines a two-argument manipulator for gzofstream. It is used
453  * as base for the setcompression(int,int) manipulator.
454 */
455 template <typename T1, typename T2>
457 {
458 public:
459  // Allows insertor to peek at internals
460  template <typename Ta, typename Tb>
461  friend gzofstream&
463  const gzomanip2<Ta, Tb>&);
464 
465  // Constructor
466  gzomanip2 (gzofstream& (*f)(gzofstream&, T1, T2),
467  T1 v1,
468  T2 v2);
469 private:
470  // Underlying manipulator function
472  (*fcn)(gzofstream&, T1, T2);
473 
474  // Arguments for manipulator function
475  T1 val1;
476  T2 val2;
477 };
478 
479 // Manipulator function thunks through to stream buffer
480 inline gzofstream&
481 setcompression (gzofstream& gzs, int l, int s = Z_DEFAULT_STRATEGY)
482 {
483  (gzs.rdbuf ())->setcompression (l, s);
484  return gzs;
485 }
486 
487 // Manipulator constructor stores arguments
488 template <typename T1, typename T2>
489 inline
491  T1 v1,
492  T2 v2)
493  : fcn(f), val1(v1), val2(v2)
494 { }
495 
496 // Insertor applies underlying manipulator function to stream
497 template <typename T1, typename T2>
498 inline gzofstream&
500 { return (*m.fcn)(s, m.val1, m.val2); }
501 
502 // Insert this onto stream to simplify setting of compression level
503 inline gzomanip2<int, int>
504 setcompression (int l, int s = Z_DEFAULT_STRATEGY)
505 { return gzomanip2<int, int>(&setcompression, l, s); }
506 
507 #endif
508 
509 #endif
Gzipped file stream buffer class.
Definition: gzfstream.h:56
gzfilebuf(const gzfilebuf &)=delete
gzfilebuf * close()
Close gzipped file.
Definition: gzfstream.cc:142
bool m_own_fd
True if this object owns file descriptor.
Definition: gzfstream.h:248
bool is_open() const
Check if file is open.
Definition: gzfstream.h:90
virtual int_type underflow()
Fill get area from gzipped file.
Definition: gzfstream.cc:260
virtual int_type overflow(int_type c=traits_type::eof())
Write put area to gzipped file.
Definition: gzfstream.cc:303
char_type * m_buffer
Stream buffer.
Definition: gzfstream.h:256
virtual ~gzfilebuf()
Definition: gzfstream.cc:68
gzfilebuf & operator=(const gzfilebuf &)=delete
virtual pos_type seekoff(off_type off, std::ios_base::seekdir way, std::ios_base::openmode mode=std::ios_base::in|std::ios_base::out)
Alters the stream positions.
Definition: gzfstream.cc:467
std::ios_base::openmode m_io_mode
Mode in which file was opened.
Definition: gzfstream.h:240
virtual int_type pbackfail(int_type c=traits_type::eof())
Definition: gzfstream.cc:222
virtual std::streambuf * setbuf(char_type *p, std::streamsize n)
Installs external stream buffer.
Definition: gzfstream.cc:356
bool m_own_buffer
True if this object owns stream buffer.
Definition: gzfstream.h:272
void disable_buffer()
Destroy internal buffer.
Definition: gzfstream.cc:439
gzfilebuf * open(const char *name, std::ios_base::openmode mode)
Open gzipped file.
Definition: gzfstream.cc:88
virtual pos_type seekpos(pos_type sp, std::ios_base::openmode mode=std::ios_base::in|std::ios_base::out)
Alters the stream positions.
Definition: gzfstream.cc:504
bool open_mode(std::ios_base::openmode mode, char *c_mode) const
Convert ios open mode int to mode string used by zlib.
Definition: gzfstream.cc:166
int setcompression(int comp_level, int comp_strategy=Z_DEFAULT_STRATEGY)
Set compression level and strategy on the fly.
Definition: gzfstream.cc:81
void enable_buffer()
Allocate internal buffer.
Definition: gzfstream.cc:399
virtual int sync()
Flush stream buffer to file.
Definition: gzfstream.cc:389
gzfilebuf * attach(int fd, std::ios_base::openmode mode)
Attach to already open gzipped file.
Definition: gzfstream.cc:115
gzFile m_file
Underlying file pointer.
Definition: gzfstream.h:235
virtual std::streamsize showmanyc()
Number of characters available in stream buffer.
Definition: gzfstream.cc:205
std::streamsize m_buffer_size
Stream buffer size.
Definition: gzfstream.h:264
Gzipped file input stream class.
Definition: gzfstream.h:282
void close()
Close gzipped file.
Definition: gzfstream.cc:566
gzfilebuf * rdbuf() const
Obtain underlying stream buffer.
Definition: gzfstream.h:309
void attach(int fd, std::ios_base::openmode mode=std::ios_base::in)
Attach to already open gzipped file.
Definition: gzfstream.cc:556
gzfilebuf m_sb
Underlying stream buffer.
Definition: gzfstream.h:359
void open(const char *name, std::ios_base::openmode mode=std::ios_base::in)
Open gzipped file.
Definition: gzfstream.cc:546
bool is_open()
Check if file is open.
Definition: gzfstream.h:317
Gzipped file output stream class.
Definition: gzfstream.h:369
gzfilebuf * rdbuf() const
Obtain underlying stream buffer.
Definition: gzfstream.h:396
void close()
Close gzipped file.
Definition: gzfstream.cc:615
gzfilebuf m_sb
Underlying stream buffer.
Definition: gzfstream.h:446
void attach(int fd, std::ios_base::openmode mode=std::ios_base::out)
Attach to already open gzipped file.
Definition: gzfstream.cc:605
bool is_open()
Check if file is open.
Definition: gzfstream.h:404
void open(const char *name, std::ios_base::openmode mode=std::ios_base::out)
Open gzipped file.
Definition: gzfstream.cc:595
Gzipped file output stream manipulator class.
Definition: gzfstream.h:457
friend gzofstream & operator<<(gzofstream &, const gzomanip2< Ta, Tb > &)
gzomanip2(gzofstream &(*f)(gzofstream &, T1, T2), T1 v1, T2 v2)
Definition: gzfstream.h:490
gzofstream & operator<<(gzofstream &s, const gzomanip2< T1, T2 > &m)
Definition: gzfstream.h:499
gzofstream & setcompression(gzofstream &gzs, int l, int s=Z_DEFAULT_STRATEGY)
Definition: gzfstream.h:481
F77_RET_T const F77_DBLE const F77_DBLE * f
T octave_idx_type m
Definition: mx-inlines.cc:773
octave_idx_type n
Definition: mx-inlines.cc:753
const octave_char_matrix & v2