2
zipstream Library License:
3
--------------------------
5
The zlib/libpng License Copyright (c) 2003 Jonathan de Halleux.
7
This software is provided 'as-is', without any express or implied warranty. In
8
no event will the authors be held liable for any damages arising from the use
11
Permission is granted to anyone to use this software for any purpose,
12
including commercial applications, and to alter it and redistribute it freely,
13
subject to the following restrictions:
15
1. The origin of this software must not be misrepresented; you must not claim
16
that you wrote the original software. If you use this software in a
17
product, an acknowledgment in the product documentation would be
18
appreciated but is not required.
20
2. Altered source versions must be plainly marked as such, and must not be
21
misrepresented as being the original software.
23
3. This notice may not be removed or altered from any source distribution
25
Author: Jonathan de Halleux, dehalleux@pelikhan.com, 2003
27
Altered by: Andreas Zieringer 2003 for OpenSG project
28
made it platform independent, gzip conform, fixed gzip footer
30
Altered by: Geoffrey Hutchison 2005 for Open Babel project
31
minor namespace modifications, VC++ compatibility
34
//*****************************************************************************
35
// template class basic_zip_streambuf
36
//*****************************************************************************
38
//-----------------------------------------------------------------------------
40
//-----------------------------------------------------------------------------
42
/** Construct a zip stream
43
* More info on the following parameters can be found in the zlib documentation.
46
template <class charT, class traits>
47
basic_zip_streambuf<charT, traits>::basic_zip_streambuf(ostream_reference ostream,
54
_output_buffer(buffer_size, 0),
55
_buffer(buffer_size, 0),
58
_zip_stream.zalloc = (alloc_func) 0;
59
_zip_stream.zfree = (free_func) 0;
61
_zip_stream.next_in = NULL;
62
_zip_stream.avail_in = 0;
63
_zip_stream.avail_out = 0;
64
_zip_stream.next_out = NULL;
72
_err=deflateInit2(&_zip_stream, level, Z_DEFLATED,
73
window_size, memory_level,
74
static_cast<int>(strategy));
76
this->setp( &(_buffer[0]), &(_buffer[_buffer.size()-1]));
81
template <class charT, class traits>
82
basic_zip_streambuf<charT, traits>::~basic_zip_streambuf(void)
85
// _ostream.flush(); CM already done in flush()
86
_err=deflateEnd(&_zip_stream);
89
/** Do the synchronization
93
template <class charT, class traits>
94
int basic_zip_streambuf<charT, traits>::sync(void)
96
if(this->pptr() && this->pptr() > this->pbase())
98
/*int c =*/ overflow(EOF);
100
// ACHTUNG wenn das drin ist hoert er nach dem ersten endl auf!
110
/** <unknown purpose>
112
* document correctly!
114
template <class charT, class traits>
115
typename basic_zip_streambuf<charT, traits>::int_type
116
basic_zip_streambuf<charT, traits>::overflow(int_type c)
118
int w = static_cast<int>(this->pptr() - this->pbase());
124
if (zip_to_stream(this->pbase(), w))
126
this->setp(this->pbase(), this->epptr() - 1);
135
/** flushes the zip buffer and output buffer.
137
* This method should be called at the end of the compression. Calling flush
138
* multiple times, will lower the compression ratio.
140
template <class charT, class traits>
141
std::streamsize basic_zip_streambuf<charT, traits>::flush(void)
143
std::streamsize written_byte_size = 0, total_written_byte_size = 0;
145
size_t remainder = 0;
148
_crc = crc32(_crc, _zip_stream.next_in,
149
_zip_stream.avail_in);
153
_err = deflate(&_zip_stream, Z_FINISH);
154
if(_err == Z_OK || _err == Z_STREAM_END)
156
written_byte_size = static_cast<std::streamsize>(_output_buffer.size()) - _zip_stream.avail_out;
157
total_written_byte_size += written_byte_size;
158
// ouput buffer is full, dumping to ostream
159
_ostream.write( (const char_type*) &(_output_buffer[0]),
160
static_cast<std::streamsize>(written_byte_size/sizeof(char_type)*sizeof(char)));
162
// checking if some bytes were not written.
163
if((remainder = written_byte_size%sizeof(char_type)) != 0)
165
// copy to the beginning of the stream
166
memcpy(&(_output_buffer[0]),
167
&(_output_buffer[written_byte_size-remainder]), remainder);
171
_zip_stream.avail_out = static_cast<uInt>(_output_buffer.size() - remainder);
172
_zip_stream.next_out = &_output_buffer[remainder];
180
return total_written_byte_size;
183
/** returns a reference to the output stream
185
template <class charT, class traits> inline
186
typename basic_zip_streambuf<charT, traits>::ostream_reference
187
basic_zip_streambuf<charT, traits>::get_ostream(void) const
192
/** returns the latest zlib error status
194
template <class charT, class traits> inline
195
int basic_zip_streambuf<charT, traits>::get_zerr(void) const
200
/** returns the crc of the input data compressed so far.
202
template <class charT, class traits> inline
204
basic_zip_streambuf<charT, traits>:: get_crc(void) const
209
/** returns the size (bytes) of the input data compressed so far.
211
template <class charT, class traits> inline
213
basic_zip_streambuf<charT, traits>::get_in_size(void) const
215
return _zip_stream.total_in;
218
/** returns the size (bytes) of the compressed data so far.
220
template <class charT, class traits> inline
222
basic_zip_streambuf<charT, traits>::get_out_size(void) const
224
return _zip_stream.total_out;
227
//-----------------------------------------------------------------------------
229
//-----------------------------------------------------------------------------
235
template <class charT, class traits>
236
bool basic_zip_streambuf<charT, traits>::zip_to_stream(
238
std::streamsize buffer_size)
240
std::streamsize written_byte_size = 0, total_written_byte_size = 0;
242
_zip_stream.next_in = (byte_buffer_type) buffer;
243
_zip_stream.avail_in = static_cast<uInt>(buffer_size * sizeof(char_type));
244
_zip_stream.avail_out = static_cast<uInt>(_output_buffer.size());
245
_zip_stream.next_out = &_output_buffer[0];
246
size_t remainder = 0;
249
_crc = crc32(_crc, _zip_stream.next_in,
250
_zip_stream.avail_in);
254
_err = deflate(&_zip_stream, 0);
256
if (_err == Z_OK || _err == Z_STREAM_END)
258
written_byte_size= static_cast<std::streamsize>(_output_buffer.size()) -
259
_zip_stream.avail_out;
260
total_written_byte_size += written_byte_size;
261
// ouput buffer is full, dumping to ostream
263
_ostream.write((const char_type*) &_output_buffer[0],
264
static_cast<std::streamsize>(written_byte_size / sizeof(char_type)));
266
// checking if some bytes were not written.
267
if((remainder = written_byte_size % sizeof(char_type)) != 0)
269
// copy to the beginning of the stream
270
memcpy(&_output_buffer[0],
271
&_output_buffer[written_byte_size-remainder],
275
_zip_stream.avail_out = static_cast<uInt>(_output_buffer.size()-remainder);
276
_zip_stream.next_out = &_output_buffer[remainder];
279
while(_zip_stream.avail_in != 0 && _err == Z_OK);
290
//*****************************************************************************
291
// template class basic_unzip_streambuf
292
//*****************************************************************************
294
//-----------------------------------------------------------------------------
296
//-----------------------------------------------------------------------------
300
template <class charT, class traits>
301
basic_unzip_streambuf<charT, traits>::basic_unzip_streambuf(istream_reference istream,
303
size_t read_buffer_size,
304
size_t input_buffer_size)
306
_input_buffer(input_buffer_size),
307
_buffer(read_buffer_size),
310
// setting zalloc, zfree and opaque
311
_zip_stream.zalloc = (alloc_func) 0;
312
_zip_stream.zfree = (free_func) 0;
314
_zip_stream.next_in = NULL;
315
_zip_stream.avail_in = 0;
316
_zip_stream.avail_out = 0;
317
_zip_stream.next_out = NULL;
319
_err = inflateInit2(&_zip_stream, window_size);
321
this->setg(&_buffer[0] + 4, // beginning of putback area
322
&_buffer[0] + 4, // read position
323
&_buffer[0] + 4); // end position
329
template <class charT, class traits>
330
basic_unzip_streambuf<charT, traits>::~basic_unzip_streambuf(void)
332
inflateEnd(&_zip_stream);
339
template <class charT, class traits>
340
typename basic_unzip_streambuf<charT, traits>::int_type
341
basic_unzip_streambuf<charT, traits>::underflow(void)
343
if(this->gptr() && ( this->gptr() < this->egptr()))
344
return * reinterpret_cast<unsigned char *>(this->gptr());
346
int n_putback = static_cast<int>(this->gptr() - this->eback());
350
memcpy(&_buffer[0] + (4 - n_putback),
351
this->gptr() - n_putback,
352
n_putback * sizeof(char_type));
355
unzip_from_stream(&_buffer[0] + 4,
356
static_cast<std::streamsize>((_buffer.size() - 4) *
359
if(num <= 0) // ERROR or EOF
362
// reset buffer pointers
363
this->setg(&_buffer[0] + (4 - n_putback), // beginning of putback area
364
&_buffer[0] + 4, // read position
365
&_buffer[0] + 4 + num); // end of buffer
367
// return next character
368
return * reinterpret_cast<unsigned char *>(this->gptr());
371
/** returns the compressed input istream
373
template <class charT, class traits> inline
374
typename basic_unzip_streambuf<charT, traits>::istream_reference
375
basic_unzip_streambuf<charT, traits>::get_istream(void)
380
/** returns the zlib stream structure
382
template <class charT, class traits> inline
384
basic_unzip_streambuf<charT, traits>::get_zip_stream(void)
389
/** returns the latest zlib error state
391
template <class charT, class traits> inline
393
basic_unzip_streambuf<charT, traits>::get_zerr(void) const
398
/** returns the crc of the uncompressed data so far
400
template <class charT, class traits> inline
402
basic_unzip_streambuf<charT, traits>::get_crc(void) const
407
/** returns the number of uncompressed bytes
409
template <class charT, class traits> inline
411
basic_unzip_streambuf<charT, traits>::get_out_size(void) const
413
return _zip_stream.total_out;
416
/** returns the number of read compressed bytes
418
template <class charT, class traits> inline
420
basic_unzip_streambuf<charT, traits>::get_in_size(void) const
422
return _zip_stream.total_in;
426
//-----------------------------------------------------------------------------
428
//-----------------------------------------------------------------------------
432
template <class charT, class traits> inline
434
basic_unzip_streambuf<charT, traits>::put_back_from_zip_stream(void)
436
if(_zip_stream.avail_in == 0)
439
_istream.clear(std::ios::goodbit);
440
_istream.seekg(-intf(_zip_stream.avail_in),
443
_zip_stream.avail_in = 0;
448
template <class charT, class traits> inline
450
basic_unzip_streambuf<charT, traits>::unzip_from_stream(char_type* buffer,
451
std::streamsize buffer_size)
453
_zip_stream.next_out =
454
(byte_buffer_type) buffer;
455
_zip_stream.avail_out =
456
static_cast<uInt>(buffer_size * sizeof(char_type));
457
size_t count = _zip_stream.avail_in;
461
if(_zip_stream.avail_in == 0)
462
count=fill_input_buffer();
464
if(_zip_stream.avail_in)
466
_err = inflate(&_zip_stream, Z_SYNC_FLUSH);
469
while(_err==Z_OK && _zip_stream.avail_out != 0 && count != 0);
472
_crc = crc32(_crc, (byte_buffer_type) buffer,
473
buffer_size - _zip_stream.avail_out / sizeof(char_type));
475
std::streamsize n_read =
476
buffer_size - _zip_stream.avail_out / sizeof(char_type);
478
// check if it is the end
479
if (_err == Z_STREAM_END)
480
put_back_from_zip_stream();
488
template <class charT, class traits> inline
490
basic_unzip_streambuf<charT, traits>::fill_input_buffer(void)
492
_zip_stream.next_in = &_input_buffer[0];
493
_istream.read((char_type*) &_input_buffer[0],
494
static_cast<std::streamsize>(_input_buffer.size() /
497
return _zip_stream.avail_in = _istream.gcount()*sizeof(char_type);
506
//*****************************************************************************
507
// template class basic_zip_ostream
508
//*****************************************************************************
510
//-----------------------------------------------------------------------------
512
//-----------------------------------------------------------------------------
516
template <class charT, class traits> inline
517
basic_zip_ostream<charT, traits>::basic_zip_ostream(ostream_reference ostream,
523
size_t buffer_size) :
524
basic_zip_streambuf<charT, traits>(ostream, level, strategy, window_size,
525
memory_level, buffer_size),
526
std::basic_ostream<charT, traits>(this),
536
template <class charT, class traits>
537
basic_zip_ostream<charT, traits>::~basic_zip_ostream(void)
543
/** returns true if it is a gzip
545
template <class charT, class traits> inline
546
bool basic_zip_ostream<charT, traits>::is_gzip(void) const
551
/** flush inner buffer and zipper buffer
554
template <class charT, class traits> inline
555
basic_zip_ostream<charT, traits>& basic_zip_ostream<charT, traits>::zflush(void)
557
static_cast<std::basic_ostream<charT, traits> *>(this)->flush();
558
static_cast<basic_zip_streambuf<charT, traits> *>(this)->flush();
562
template <class charT, class traits> inline
563
void basic_zip_ostream<charT, traits>::finished(void)
572
//-----------------------------------------------------------------------------
574
//-----------------------------------------------------------------------------
579
template <class charT, class traits>
580
basic_zip_ostream<charT,traits>& basic_zip_ostream<charT, traits>::add_header(void)
584
this->get_ostream() << static_cast<char_type>(detail::gz_magic[0])
585
<< static_cast<char_type>(detail::gz_magic[1])
586
<< static_cast<char_type>(Z_DEFLATED)
588
<< zero<<zero<<zero<<zero // time
590
<< static_cast<char_type>(OS_CODE);
598
template <class charT, class traits>
599
basic_zip_ostream<charT,traits>& basic_zip_ostream<charT, traits>::add_footer(void)
606
_added_footer = true;
608
// Writes crc and length in LSB order to the stream.
609
unsigned long crc = this->get_crc();
612
this->get_ostream().put((int)(crc & 0xff));
616
unsigned long length = this->get_in_size();
619
this->get_ostream().put((int)(length & 0xff));
631
//*****************************************************************************
632
// template class basic_zip_istream
633
//*****************************************************************************
635
//-----------------------------------------------------------------------------
637
//-----------------------------------------------------------------------------
641
template <class charT, class traits>
642
basic_zip_istream<charT, traits>::basic_zip_istream(istream_reference istream,
644
size_t read_buffer_size,
645
size_t input_buffer_size)
646
: basic_unzip_streambuf<charT, traits>(istream, window_size,
647
read_buffer_size, input_buffer_size),
648
std::basic_istream<charT, traits>(this),
653
if(this->get_zerr() == Z_OK)
657
/** returns true if it is a gzip file
659
template <class charT, class traits> inline
661
basic_zip_istream<charT, traits>::is_gzip(void) const
666
/** return crc check result
668
* This must be called after the reading of compressed data is finished! This
669
* method compares it to the crc of the uncompressed data.
671
* \return true if crc check is succesful
673
template <class charT, class traits> inline
675
basic_zip_istream<charT, traits>::check_crc(void)
678
return this->get_crc() == _gzip_crc;
681
/** return data size check
683
template <class charT, class traits> inline
685
basic_zip_istream<charT, traits>::check_data_size(void) const
687
return this->get_out_size() == _gzip_data_size;
690
/** return the crc value in the file
692
template <class charT, class traits> inline
694
basic_zip_istream<charT, traits>::get_gzip_crc(void) const
699
/** return the data size in the file
701
template <class charT, class traits> inline
703
basic_zip_istream<charT, traits>::get_gzip_data_size(void) const
705
return _gzip_data_size;
708
//-----------------------------------------------------------------------------
710
//-----------------------------------------------------------------------------
715
template <class charT, class traits>
717
basic_zip_istream<charT, traits>::check_header(void)
719
int method; /* method byte */
720
int flags; /* flags byte */
724
z_stream &zip_stream = this->get_zip_stream();
726
/* Check the gzip magic header */
727
for(len = 0; len < 2; len++)
729
c = (int)this->get_istream().get();
730
if (c != detail::gz_magic[len])
733
this->get_istream().unget();
736
this->get_istream().unget();
739
err = zip_stream.avail_in != 0 ? Z_OK : Z_STREAM_END;
746
method = (int)this->get_istream().get();
747
flags = (int)this->get_istream().get();
748
if (method != Z_DEFLATED || (flags & detail::gz_reserved) != 0)
754
/* Discard time, xflags and OS code: */
755
for (len = 0; len < 6; len++)
756
this->get_istream().get();
758
if ((flags & detail::gz_extra_field) != 0)
760
/* skip the extra field */
761
len = (uInt)this->get_istream().get();
762
len += ((uInt)this->get_istream().get())<<8;
763
/* len is garbage if EOF but the loop below will quit anyway */
764
while (len-- != 0 && this->get_istream().get() != EOF) ;
766
if ((flags & detail::gz_orig_name) != 0)
768
/* skip the original file name */
769
while ((c = this->get_istream().get()) != 0 && c != EOF) ;
771
if ((flags & detail::gz_comment) != 0)
773
/* skip the .gz file comment */
774
while ((c = this->get_istream().get()) != 0 && c != EOF) ;
776
if ((flags & detail::gz_head_crc) != 0)
777
{ /* skip the header crc */
778
for (len = 0; len < 2; len++)
779
this->get_istream().get();
781
err = this->get_istream().eof() ? Z_DATA_ERROR : Z_OK;
789
template <class charT, class traits>
791
basic_zip_istream<charT, traits>::read_footer(void)
797
_gzip_crc += ((((int) this->get_istream().get()) & 0xff) << (8*n));
802
((((int) this->get_istream().get()) & 0xff) << (8*n));