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