]> git.donarmstrong.com Git - flightcrew.git/blob - src/zipios/src/deflateoutputstreambuf.cpp
update changelog, target experimental
[flightcrew.git] / src / zipios / src / deflateoutputstreambuf.cpp
1
2 #include "zipios++/zipios-config.h"
3
4 #include "zipios++/meta-iostreams.h"
5
6 #include <zlib.h>
7
8 #include "zipios++/fcollexceptions.h"
9 #include "zipios++/deflateoutputstreambuf.h"
10
11 #include "outputstringstream.h"
12
13 namespace zipios {
14
15 using std::cerr ;
16 using std::endl ;
17
18 DeflateOutputStreambuf::DeflateOutputStreambuf( streambuf *outbuf, bool user_init, 
19                                                 bool del_outbuf ) 
20   : FilterOutputStreambuf( outbuf, del_outbuf ),
21     _zs_initialized ( false            ),
22     _invecsize      ( 1000             ),
23     _invec          ( _invecsize       ),
24     _outvecsize     ( 1000             ),
25     _outvec         ( _outvecsize      )
26 {
27   // NOTICE: It is important that this constructor and the methods it
28   // calls doesn't do anything with the output streambuf _outbuf The
29   // reason is that this class can be subclassed, and the subclass
30   // should get a chance to write to the buffer first
31
32   // zlib init:
33   _zs.zalloc = Z_NULL ;
34   _zs.zfree  = Z_NULL ;
35   _zs.opaque = Z_NULL ;
36
37   if ( user_init && ! init() )
38     cerr << "DeflateOutputStreambuf::reset() failed!\n" ; // FIXME: throw something
39
40 }
41
42
43 DeflateOutputStreambuf::~DeflateOutputStreambuf() {
44   closeStream() ;
45 }
46
47
48 // This method is called in the constructor, so it must not write
49 // anything to the output streambuf _outbuf (see notice in
50 // constructor)
51 bool DeflateOutputStreambuf::init( int comp_level ) {
52   static const int default_mem_level = 8 ;
53
54   // _zs.next_in and avail_in must be set according to
55   // zlib.h (inline doc).
56   _zs.next_in  = reinterpret_cast< unsigned char * >( &( _invec[ 0 ] ) ) ;
57   _zs.avail_in = 0 ;
58
59   _zs.next_out  = reinterpret_cast< unsigned char * >( &( _outvec[ 0 ] ) ) ;
60   _zs.avail_out = _outvecsize ;
61
62   int err ;
63   if( _zs_initialized ) {                    // just reset it
64     endDeflation() ;
65     err = deflateReset( &_zs ) ;
66     // FIXME: bug, for deflateReset we do not update the compression level
67   } else {                                   // init it
68     err = deflateInit2( &_zs, comp_level, Z_DEFLATED, -MAX_WBITS, 
69                         default_mem_level, Z_DEFAULT_STRATEGY ) ;
70     /* windowBits is passed < 0 to tell that no zlib header should be
71        written. */
72     _zs_initialized = true ;
73   }
74
75   // streambuf init:
76   setp( &( _invec[ 0 ] ), &( _invec[ 0 ] ) + _invecsize ) ;
77
78   _crc32 = crc32( 0, Z_NULL, 0 ) ;
79   _overflown_bytes = 0 ;
80
81   if ( err == Z_OK )
82     return true ;
83   else
84     return false ;
85 }
86
87
88 bool DeflateOutputStreambuf::closeStream() {
89   int err = Z_OK ;
90   if( _zs_initialized ) {
91     endDeflation() ;
92     err = deflateEnd( &_zs ) ;
93     _zs_initialized = false ;
94   }
95   
96   if ( err == Z_OK )
97     return true ;
98   else {
99     cerr << "DeflateOutputStreambuf::closeStream(): deflateEnd failed" ;
100 #ifdef HAVE_ZERROR
101     cerr << ": " << zError( err ) ;
102 #endif
103     cerr << endl ;
104     return false ;
105   }
106 }
107
108
109 int DeflateOutputStreambuf::overflow( int c ) {
110   _zs.avail_in = static_cast< uInt >( pptr() - pbase() ) ;
111   _zs.next_in = reinterpret_cast< unsigned char * >( &( _invec[ 0 ] ) ) ;
112
113   _crc32 = crc32( _crc32, _zs.next_in, _zs.avail_in ) ; // update crc32
114   _overflown_bytes += _zs.avail_in ;
115
116   _zs.next_out  = reinterpret_cast< unsigned char * >( &( _outvec[ 0 ] ) ) ;
117   _zs.avail_out = _outvecsize ;
118
119   // Deflate until _invec is empty.
120   int err = Z_OK ;
121   while ( ( _zs.avail_in > 0 || _zs.avail_out == 0 ) && err == Z_OK ) {
122     if ( _zs.avail_out == 0 )
123       flushOutvec() ;
124
125     err = deflate( &_zs, Z_NO_FLUSH ) ;
126   }
127
128   flushOutvec() ;
129   
130   // Update 'put' pointers
131   setp( &( _invec[ 0 ] ), &( _invec[ 0 ] ) + _invecsize ) ;
132   
133   if( err != Z_OK && err != Z_STREAM_END ) {
134 #if defined (HAVE_STD_IOSTREAM) && defined (USE_STD_IOSTREAM)
135     // Throw an exception to make istream set badbit
136     OutputStringStream msgs ;
137     msgs << "Deflation failed" ;
138 #ifdef HAVE_ZERROR
139     msgs << ": " << zError( err ) ;
140 #endif
141     throw IOException( msgs.str() ) ;
142 #endif
143     cerr << "Deflation failed\n" ;
144     return EOF ;
145   }
146
147   if ( c != EOF ) {
148     *pptr() = c ;
149     pbump( 1 ) ;
150   }
151
152   return 0 ;
153 }
154
155 int DeflateOutputStreambuf::sync() {
156   // FIXME: Do something
157 //    return overflow() ;
158   return 0 ;
159 }
160
161
162 bool DeflateOutputStreambuf::flushOutvec() {
163   int deflated_bytes = _outvecsize - _zs.avail_out ;
164   int bc = static_cast< int >( _outbuf->sputn( &( _outvec[ 0 ] ), deflated_bytes ) ) ;
165
166   _zs.next_out = reinterpret_cast< unsigned char * >( &( _outvec[ 0 ] ) ) ;
167   _zs.avail_out = _outvecsize ;
168
169   return deflated_bytes == bc ;
170 }
171
172
173 void DeflateOutputStreambuf::endDeflation() {
174   overflow() ;
175
176   _zs.next_out  = reinterpret_cast< unsigned char * >( &( _outvec[ 0 ] ) ) ;
177   _zs.avail_out = _outvecsize ;
178
179   // Deflate until _invec is empty.
180   int err = Z_OK ;
181
182   while ( err == Z_OK ) {
183     if ( _zs.avail_out == 0 )
184       flushOutvec() ;
185
186     err = deflate( &_zs, Z_FINISH ) ;
187   }
188
189   flushOutvec() ;
190
191   if ( err != Z_STREAM_END ) {
192     cerr << "DeflateOutputStreambuf::endDeflation(): deflation failed:\n" ;
193 #ifdef HAVE_ZERROR
194     cerr << ": " << zError( err ) ;
195 #endif
196     cerr << endl ;
197   }
198 }
199
200
201 } // namespace
202
203 /** \file
204     Implementation of DeflateOutputStreambuf.
205 */
206
207 /*
208   Zipios++ - a small C++ library that provides easy access to .zip files.
209   Copyright (C) 2000  Thomas Søndergaard
210   
211   This library is free software; you can redistribute it and/or
212   modify it under the terms of the GNU Lesser General Public
213   License as published by the Free Software Foundation; either
214   version 2 of the License, or (at your option) any later version.
215   
216   This library is distributed in the hope that it will be useful,
217   but WITHOUT ANY WARRANTY; without even the implied warranty of
218   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
219   Lesser General Public License for more details.
220   
221   You should have received a copy of the GNU Lesser General Public
222   License along with this library; if not, write to the Free Software
223   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
224 */