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