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