Zipios++
deflateoutputstreambuf.cpp
Go to the documentation of this file.
1 
2 #include "zipios++/zipios-config.h"
3 
4 #include "zipios++/meta-iostreams.h"
5 
6 #include <zlib.h>
7 
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 
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 = 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 
163  int deflated_bytes = _outvecsize - _zs.avail_out ;
164  int bc = _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 
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 
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 */
DeflateOutputStreambuf(streambuf *outbuf, bool user_init=false, bool del_outbuf=false)
DeflateOutputStreambuf constructor.
bool flushOutvec()
Flushes _outvec and updates _zs.next_out and _zs.avail_out.
Header file that defines OutputStringStream.
Header file that defines DeflateOutputStreambuf.
virtual ~DeflateOutputStreambuf()
Destructor.
Header file that defines a number of exceptions used by FileCollection and its subclasses.
A FilterOutputStreambuf is a streambuf that filters the data that is written to it before it passes i...
void endDeflation()
Flushes the remaining data in the zlib buffers, after which the only possible operations are deflateE...