- some iostream -> iosfwd in headers
[platform/upstream/libzypp.git] / zypp / base / GzStream.h
1 /*---------------------------------------------------------------------\
2 |                                                                      |
3 |                      __   __    ____ _____ ____                      |
4 |                      \ \ / /_ _/ ___|_   _|___ \                     |
5 |                       \ V / _` \___ \ | |   __) |                    |
6 |                        | | (_| |___) || |  / __/                     |
7 |                        |_|\__,_|____/ |_| |_____|                    |
8 |                                                                      |
9 |                               core system                            |
10 |                                         (C) SuSE Linux Products GmbH |
11 \----------------------------------------------------------------------/
12
13   File:       GzStream.h
14
15   Author:     Michael Andres <ma@suse.de>
16   Maintainer: Michael Andres <ma@suse.de>
17
18   Purpose: Streams reading and writing gzip files.
19
20 /-*/
21 #ifndef ZYPP_BASE_GZSTREAM_H
22 #define ZYPP_BASE_GZSTREAM_H
23
24 #include <iosfwd>
25 #include <vector>
26 #include <zlib.h>
27
28 ///////////////////////////////////////////////////////////////////
29 namespace zypp
30 { /////////////////////////////////////////////////////////////////
31
32   ///////////////////////////////////////////////////////////////////
33   namespace gzstream_detail
34   { /////////////////////////////////////////////////////////////////
35
36     ///////////////////////////////////////////////////////////////////
37     //
38     //  CLASS NAME : ZlibError
39     /**
40      * @short Helper class to ship zlib errors.
41      **/
42     struct ZlibError
43     {
44       /**
45        * The zlib error code
46        **/
47       int _zError;
48
49       /**
50        * errno, valid if zError is Z_ERRNO
51        **/
52       int _errno;
53
54       ZlibError()
55       : _zError( 0 ), _errno( 0 )
56       {}
57
58       /**
59        * Return string describing the zlib error code
60        **/
61       std::string
62       strerror() const;
63     };
64     ///////////////////////////////////////////////////////////////////
65
66     ///////////////////////////////////////////////////////////////////
67     //
68     //  CLASS NAME : fgzstreambuf
69     /**
70      * @short Streambuffer reading or writing gzip files.
71      *
72      * Read and write mode are mutual exclusive. Seek is supported,
73      * but zlib restrictions appy (only forward seek in write mode;
74      * backward seek in read mode might be expensive).Putback is not
75      * supported.
76      *
77      * Reading plain (no gziped) files is possible as well.
78      *
79      * This streambuf is used in @ref ifgzstream and  @ref ofgzstream.
80      **/
81     class fgzstreambuf : public std::streambuf {
82
83     public:
84
85       fgzstreambuf( unsigned bufferSize_r = 512 )
86       : _fd( -1 )
87       ,_file( NULL )
88       , _mode( std::ios_base::openmode(0) )
89       , _buffer( (bufferSize_r?bufferSize_r:1), 0 )
90       {}
91
92       virtual
93       ~fgzstreambuf()
94       { close(); }
95
96       bool
97       isOpen() const
98       { return _file; }
99
100       bool
101       inReadMode() const
102       { return( _mode == std::ios_base::in ); }
103
104       bool
105       inWriteMode() const
106       { return( _mode == std::ios_base::out ); }
107
108       fgzstreambuf *
109       open( const char * name_r, std::ios_base::openmode mode_r = std::ios_base::in );
110
111         fgzstreambuf *
112         close();
113
114         //! Tell the file position in the compressed file.
115         //! Analogous to tell(2), complementary to gztell.
116         pos_type compressed_tell() const;
117
118         /**
119          * The last error returned fron zlib.
120          **/
121         ZlibError
122         zError() const
123         { return _error; }
124
125     protected:
126
127       virtual int
128       sync();
129
130       virtual int_type
131       overflow( int_type c = traits_type::eof() );
132
133       virtual int_type
134       underflow();
135
136       virtual pos_type
137       seekoff( off_type off_r, std::ios_base::seekdir way_r, std::ios_base::openmode /* ignored */ )
138       { return seekTo( off_r, way_r ); }
139
140       virtual pos_type
141       seekpos( pos_type pos_r, std::ios_base::openmode /* ignored */ )
142       { return seekTo( off_type(pos_r), std::ios_base::beg ); }
143
144     private:
145
146       typedef std::vector<char> buffer_type;
147
148       //! file descriptor of the compressed file
149       int                      _fd;
150
151       gzFile                   _file;
152
153       std::ios_base::openmode  _mode;
154
155       buffer_type              _buffer;
156
157       ZlibError                _error;
158
159     private:
160
161       void
162       setZError()
163       { gzerror( _file, &_error._zError ); }
164
165       std::streamsize
166       zReadTo( char * buffer_r, std::streamsize maxcount_r );
167
168       bool
169       zWriteFrom( const char * buffer_r, std::streamsize count_r );
170
171       pos_type
172       zSeekTo( off_type off_r, std::ios_base::seekdir way_r );
173
174       pos_type
175       zTell();
176
177       pos_type
178       seekTo( off_type off_r, std::ios_base::seekdir way_r );
179     };
180     ///////////////////////////////////////////////////////////////////
181
182     ///////////////////////////////////////////////////////////////////
183     //
184     //  CLASS NAME : fXstream<class _BStr,class _SBuf>
185     /**
186      * @short Common template to define ifgzstream/ofgzstream
187      * reading/writing gzip files.
188      *
189      * Don't use fXstream directly, but @ref ifgzstream or
190      * @ref ofgzstream. fXstream is just to avoid almost
191      * duplicate code.
192      **/
193     template<class _BStream,class _StreamBuf>
194       class fXstream : public _BStream
195       {
196       public:
197
198         typedef gzstream_detail::ZlibError ZlibError;
199         typedef _BStream                   stream_type;
200         typedef _StreamBuf                 streambuf_type;
201
202         fXstream()
203         : stream_type( NULL )
204         { this->init( &_streambuf ); }
205
206         explicit
207         fXstream( const char * file_r )
208         : stream_type( NULL )
209         { this->init( &_streambuf ); this->open( file_r ); }
210
211         virtual
212         ~fXstream()
213         {}
214
215         bool
216         is_open() const
217         { return _streambuf.isOpen(); }
218
219         void
220         open( const char * file_r )
221         {
222           if ( !_streambuf.open( file_r, defMode(*this) ) )
223             this->setstate(std::ios_base::failbit);
224           else
225             this->clear();
226         }
227
228         void
229         close()
230         {
231           if ( !_streambuf.close() )
232             this->setstate(std::ios_base::failbit);
233         }
234
235         /**
236          * The last error returned retuned fron zlib.
237          **/
238         ZlibError
239         zError() const
240         { return _streambuf.zError(); }
241
242         //! Similar to ios::rdbuf.
243         //! But it returns our specific type, not the generic streambuf *.
244         const streambuf_type&
245         getbuf() const
246         { return _streambuf; }
247
248       private:
249
250         streambuf_type _streambuf;
251
252         std::ios_base::openmode
253         defMode( const std::istream & str_r )
254         { return std::ios_base::in; }
255
256         std::ios_base::openmode
257         defMode( const std::ostream & str_r )
258         { return std::ios_base::out; }
259
260       };
261     ///////////////////////////////////////////////////////////////////
262
263     /////////////////////////////////////////////////////////////////
264   } // namespace gzstream_detail
265   ///////////////////////////////////////////////////////////////////
266
267   /**
268    * istream reading gzip files as well as plain files.
269    **/
270   typedef gzstream_detail::fXstream<std::istream,gzstream_detail::fgzstreambuf> ifgzstream;
271
272   /**
273    * ostream writing gzip files.
274    **/
275   typedef gzstream_detail::fXstream<std::ostream,gzstream_detail::fgzstreambuf> ofgzstream;
276
277   /////////////////////////////////////////////////////////////////
278 } // namespace zypp
279 ///////////////////////////////////////////////////////////////////
280
281 #endif // ZYPP_BASE_GZSTREAM_H