GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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