template <class charT, class traits>
basic_zip_streambuf<charT, traits>::basic_zip_streambuf(ostream_reference ostream,
int level,
EStrategy strategy,
int window_size,
int memory_level,
size_t buffer_size)
: _ostream(ostream),
_output_buffer(buffer_size, 0),
_buffer(buffer_size, 0),
_crc(0)
{
_zip_stream.zalloc = (alloc_func) nullptr;
_zip_stream.zfree = (free_func) nullptr;
_zip_stream.next_in = nullptr;
_zip_stream.avail_in = 0;
_zip_stream.avail_out = 0;
_zip_stream.next_out = nullptr;
if(level > 9)
level = 9;
if(memory_level > 9)
memory_level = 9;
_err=deflateInit2(&_zip_stream, level, Z_DEFLATED,
window_size, memory_level,
static_cast<int>(strategy));
this->setp( &(_buffer[0]), &(_buffer[_buffer.size()-1]));
}
template <class charT, class traits>
basic_zip_streambuf<charT, traits>::~basic_zip_streambuf()
{
flush();
_err=deflateEnd(&_zip_stream);
}
template <class charT, class traits>
int basic_zip_streambuf<charT, traits>::sync()
{
if(this->pptr() && this->pptr() > this->pbase())
{
overflow(EOF);
}
return 0;
}
template <class charT, class traits>
typename basic_zip_streambuf<charT, traits>::int_type
basic_zip_streambuf<charT, traits>::overflow(int_type c)
{
int w = static_cast<int>(this->pptr() - this->pbase());
if (c != EOF)
{
*this->pptr() = (char)c;
++w;
}
if (zip_to_stream(this->pbase(), w))
{
this->setp(this->pbase(), this->epptr() - 1);
return c;
}
else
{
return EOF;
}
}
template <class charT, class traits>
std::streamsize basic_zip_streambuf<charT, traits>::flush()
{
std::streamsize total_written_byte_size = 0;
_crc = crc32(_crc, _zip_stream.next_in,
_zip_stream.avail_in);
do
{
_err = deflate(&_zip_stream, Z_FINISH);
if(_err == Z_OK || _err == Z_STREAM_END)
{
std::streamsize written_byte_size = static_cast<std::streamsize>(_output_buffer.size()) - _zip_stream.avail_out;
total_written_byte_size += written_byte_size;
_ostream.write( (const char_type*) &(_output_buffer[0]),
static_cast<std::streamsize>(written_byte_size/sizeof(char_type)*sizeof(char)));
size_t remainder = written_byte_size%sizeof(char_type);
if(remainder != 0)
{
std::streamsize theDiff = written_byte_size-remainder;
memcpy(&(_output_buffer[0]),
&(_output_buffer[(unsigned int)theDiff]), remainder);
}
_zip_stream.avail_out = static_cast<uInt>(_output_buffer.size() - remainder);
_zip_stream.next_out = &_output_buffer[remainder];
}
}
while(_err == Z_OK);
_ostream.flush();
return total_written_byte_size;
}
template <class charT, class traits> inline
typename basic_zip_streambuf<charT, traits>::ostream_reference
basic_zip_streambuf<charT, traits>::get_ostream() const
{
return _ostream;
}
template <class charT, class traits> inline
int basic_zip_streambuf<charT, traits>::get_zerr() const
{
return _err;
}
template <class charT, class traits> inline
unsigned long
basic_zip_streambuf<charT, traits>:: get_crc() const
{
return _crc;
}
template <class charT, class traits> inline
unsigned long
basic_zip_streambuf<charT, traits>::get_in_size() const
{
return _zip_stream.total_in;
}
template <class charT, class traits> inline
long
basic_zip_streambuf<charT, traits>::get_out_size() const
{
return _zip_stream.total_out;
}
template <class charT, class traits>
bool basic_zip_streambuf<charT, traits>::zip_to_stream(
char_type *buffer,
std::streamsize buffer_size)
{
std::streamsize total_written_byte_size = 0;
_zip_stream.next_in = (byte_buffer_type) buffer;
_zip_stream.avail_in = static_cast<uInt>(buffer_size * sizeof(char_type));
_zip_stream.avail_out = static_cast<uInt>(_output_buffer.size());
_zip_stream.next_out = &_output_buffer[0];
_crc = crc32(_crc, _zip_stream.next_in,
_zip_stream.avail_in);
do
{
_err = deflate(&_zip_stream, 0);
if (_err == Z_OK || _err == Z_STREAM_END)
{
std::streamsize written_byte_size = static_cast<std::streamsize>(_output_buffer.size()) -
_zip_stream.avail_out;
total_written_byte_size += written_byte_size;
_ostream.write((const char_type*) &_output_buffer[0],
static_cast<std::streamsize>(written_byte_size / sizeof(char_type)));
size_t remainder = written_byte_size % sizeof(char_type);
if(remainder != 0)
{
std::streamsize theDiff = written_byte_size-remainder;
memcpy(&_output_buffer[0],
&_output_buffer[(unsigned int)theDiff],
remainder);
}
_zip_stream.avail_out = static_cast<uInt>(_output_buffer.size()-remainder);
_zip_stream.next_out = &_output_buffer[remainder];
}
}
while(_zip_stream.avail_in != 0 && _err == Z_OK);
(void)total_written_byte_size;
return _err == Z_OK;
}
template <class charT, class traits>
basic_unzip_streambuf<charT, traits>::basic_unzip_streambuf(istream_reference istream,
int window_size,
size_t read_buffer_size,
size_t input_buffer_size)
: _istream(istream),
_input_buffer(input_buffer_size),
_buffer(read_buffer_size),
_crc(0)
{
_zip_stream.zalloc = (alloc_func) nullptr;
_zip_stream.zfree = (free_func) nullptr;
_zip_stream.next_in = nullptr;
_zip_stream.avail_in = 0;
_zip_stream.avail_out = 0;
_zip_stream.next_out = nullptr;
_err = inflateInit2(&_zip_stream, window_size);
this->setg(&_buffer[0] + 4, &_buffer[0] + 4, &_buffer[0] + 4); }
template <class charT, class traits>
basic_unzip_streambuf<charT, traits>::~basic_unzip_streambuf()
{
inflateEnd(&_zip_stream);
}
template <class charT, class traits>
typename basic_unzip_streambuf<charT, traits>::int_type
basic_unzip_streambuf<charT, traits>::underflow()
{
if(this->gptr() && ( this->gptr() < this->egptr()))
return * reinterpret_cast<unsigned char *>(this->gptr());
int n_putback = static_cast<int>(this->gptr() - this->eback());
if(n_putback > 4)
n_putback = 4;
memcpy(&_buffer[0] + (4 - n_putback),
this->gptr() - n_putback,
n_putback * sizeof(char_type));
std::streamsize num =
unzip_from_stream(&_buffer[0] + 4,
static_cast<std::streamsize>((_buffer.size() - 4) *
sizeof(char_type)));
if(num <= 0) return EOF;
this->setg(&_buffer[0] + (4 - n_putback), &_buffer[0] + 4, &_buffer[0] + 4 + num);
return * reinterpret_cast<unsigned char *>(this->gptr());
}
template <class charT, class traits> inline
typename basic_unzip_streambuf<charT, traits>::istream_reference
basic_unzip_streambuf<charT, traits>::get_istream()
{
return _istream;
}
template <class charT, class traits> inline
z_stream &
basic_unzip_streambuf<charT, traits>::get_zip_stream()
{
return _zip_stream;
}
template <class charT, class traits> inline
int
basic_unzip_streambuf<charT, traits>::get_zerr() const
{
return _err;
}
template <class charT, class traits> inline
unsigned long
basic_unzip_streambuf<charT, traits>::get_crc() const
{
return _crc;
}
template <class charT, class traits> inline
long
basic_unzip_streambuf<charT, traits>::get_out_size() const
{
return _zip_stream.total_out;
}
template <class charT, class traits> inline
long
basic_unzip_streambuf<charT, traits>::get_in_size() const
{
return _zip_stream.total_in;
}
template <class charT, class traits> inline
void
basic_unzip_streambuf<charT, traits>::put_back_from_zip_stream()
{
if(_zip_stream.avail_in == 0)
return;
_istream.clear(std::ios::goodbit);
_istream.seekg(-intf(_zip_stream.avail_in),
std::ios_base::cur);
_zip_stream.avail_in = 0;
}
template <class charT, class traits> inline
std::streamsize
basic_unzip_streambuf<charT, traits>::unzip_from_stream(char_type* buffer,
std::streamsize buffer_size)
{
_zip_stream.next_out =
(byte_buffer_type) buffer;
_zip_stream.avail_out =
static_cast<uInt>(buffer_size * sizeof(char_type));
size_t count = _zip_stream.avail_in;
do
{
if(_zip_stream.avail_in == 0)
count=fill_input_buffer();
if(_zip_stream.avail_in)
{
_err = inflate(&_zip_stream, Z_SYNC_FLUSH);
}
}
while(_err==Z_OK && _zip_stream.avail_out != 0 && count != 0);
std::streamsize theSize = buffer_size - ((std::streamsize)_zip_stream.avail_out) / sizeof(char_type);
_crc = crc32(_crc, (byte_buffer_type) buffer,(uInt)theSize);
std::streamsize n_read =
buffer_size - _zip_stream.avail_out / sizeof(char_type);
if (_err == Z_STREAM_END)
put_back_from_zip_stream();
return n_read;
}
template <class charT, class traits> inline
size_t
basic_unzip_streambuf<charT, traits>::fill_input_buffer()
{
_zip_stream.next_in = &_input_buffer[0];
_istream.read((char_type*) &_input_buffer[0],
static_cast<std::streamsize>(_input_buffer.size() /
sizeof(char_type)));
std::streamsize nbytesread = _istream.gcount()*sizeof(char_type);
if( !_istream )
{
if( _istream.eof() )
{
gdcm_assert( nbytesread < (std::streamsize)(_input_buffer.size() / sizeof(char_type)) );
_input_buffer[ (unsigned int)nbytesread ] = 0;
++nbytesread;
}
}
return _zip_stream.avail_in = (uInt)nbytesread;
}
#if defined(_MSC_VER)
# pragma warning (push)
# pragma warning (disable:4355)
#endif
template <class charT, class traits> inline
basic_zip_ostream<charT, traits>::basic_zip_ostream(ostream_reference ostream,
bool isgzip,
int level,
EStrategy strategy,
int window_size,
int memory_level,
size_t buffer_size) :
basic_zip_streambuf<charT, traits>(ostream, level, strategy, window_size,
memory_level, buffer_size),
std::basic_ostream<charT, traits>(this),
_is_gzip(isgzip),
_added_footer(false)
{
if(_is_gzip)
add_header();
}
#if defined(_MSC_VER)
# pragma warning (pop)
#endif
template <class charT, class traits>
basic_zip_ostream<charT, traits>::~basic_zip_ostream()
{
add_footer();
}
template <class charT, class traits> inline
bool basic_zip_ostream<charT, traits>::is_gzip() const
{
return _is_gzip;
}
template <class charT, class traits> inline
basic_zip_ostream<charT, traits>& basic_zip_ostream<charT, traits>::zflush()
{
static_cast<std::basic_ostream<charT, traits> *>(this)->flush();
static_cast<basic_zip_streambuf<charT, traits> *>(this)->flush();
return *this;
}
template <class charT, class traits> inline
void basic_zip_ostream<charT, traits>::finished()
{
if(_is_gzip)
add_footer();
else
zflush();
}
template <class charT, class traits>
basic_zip_ostream<charT,traits>& basic_zip_ostream<charT, traits>::add_header()
{
char_type zero = 0;
this->get_ostream() << static_cast<char_type>(detail::gz_magic[0])
<< static_cast<char_type>(detail::gz_magic[1])
<< static_cast<char_type>(Z_DEFLATED)
<< zero << zero<<zero<<zero<<zero << zero << static_cast<char_type>(OS_CODE);
return *this;
}
template <class charT, class traits>
basic_zip_ostream<charT,traits>& basic_zip_ostream<charT, traits>::add_footer()
{
if(_added_footer)
return *this;
zflush();
_added_footer = true;
unsigned long crc = this->get_crc();
for(int n=0;n<4;++n)
{
this->get_ostream().put((char)(crc & 0xff));
crc >>= 8;
}
unsigned long length = this->get_in_size();
for(int m=0;m<4;++m)
{
this->get_ostream().put((char)(length & 0xff));
length >>= 8;
}
return *this;
}
#if defined(_MSC_VER)
# pragma warning (push)
# pragma warning (disable:4355)
#endif
template <class charT, class traits>
basic_zip_istream<charT, traits>::basic_zip_istream(istream_reference istream,
int window_size,
size_t read_buffer_size,
size_t input_buffer_size)
: basic_unzip_streambuf<charT, traits>(istream, window_size,
read_buffer_size, input_buffer_size),
std::basic_istream<charT, traits>(this),
_is_gzip(false),
_gzip_crc(0),
_gzip_data_size(0)
{
if(this->get_zerr() == Z_OK)
{
int check = check_header();(void)check;
}
}
#if defined(_MSC_VER)
# pragma warning (pop)
#endif
template <class charT, class traits> inline
bool
basic_zip_istream<charT, traits>::is_gzip() const
{
return _is_gzip;
}
template <class charT, class traits> inline
bool
basic_zip_istream<charT, traits>::check_crc()
{
read_footer();
return this->get_crc() == _gzip_crc;
}
template <class charT, class traits> inline
bool
basic_zip_istream<charT, traits>::check_data_size() const
{
return this->get_out_size() == _gzip_data_size;
}
template <class charT, class traits> inline
long
basic_zip_istream<charT, traits>::get_gzip_crc() const
{
return _gzip_crc;
}
template <class charT, class traits> inline
long
basic_zip_istream<charT, traits>::get_gzip_data_size() const
{
return _gzip_data_size;
}
template <class charT, class traits>
int
basic_zip_istream<charT, traits>::check_header()
{
int method;
int flagsbyte;
uInt len;
int c;
int err=0;
z_stream &zip_stream = this->get_zip_stream();
for(len = 0; len < 2; len++)
{
c = (int)this->get_istream().get();
if (c != detail::gz_magic[len])
{
if (len != 0)
this->get_istream().unget();
if (c!= EOF)
{
this->get_istream().unget();
}
err = zip_stream.avail_in != 0 ? Z_OK : Z_STREAM_END;
_is_gzip = false;
return err;
}
}
_is_gzip = true;
method = (int)this->get_istream().get();
flagsbyte = (int)this->get_istream().get();
if (method != Z_DEFLATED || (flagsbyte & detail::gz_reserved) != 0)
{
err = Z_DATA_ERROR;
return err;
}
for (len = 0; len < 6; len++)
this->get_istream().get();
if ((flagsbyte & detail::gz_extra_field) != 0)
{
len = (uInt)this->get_istream().get();
len += ((uInt)this->get_istream().get())<<8;
while (len-- != 0 && this->get_istream().get() != EOF) ;
}
if ((flagsbyte & detail::gz_orig_name) != 0)
{
while ((c = this->get_istream().get()) != 0 && c != EOF) ;
}
if ((flagsbyte & detail::gz_comment) != 0)
{
while ((c = this->get_istream().get()) != 0 && c != EOF) ;
}
if ((flagsbyte & detail::gz_head_crc) != 0)
{
for (len = 0; len < 2; len++)
this->get_istream().get();
}
err = this->get_istream().eof() ? Z_DATA_ERROR : Z_OK;
return err;
}
template <class charT, class traits>
void
basic_zip_istream<charT, traits>::read_footer()
{
if(_is_gzip)
{
_gzip_crc = 0;
for(int n=0;n<4;++n)
_gzip_crc += ((((int) this->get_istream().get()) & 0xff) << (8*n));
_gzip_data_size = 0;
for(int n=0;n<4;++n)
_gzip_data_size +=
((((int) this->get_istream().get()) & 0xff) << (8*n));
}
}