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 */