24 #ifndef SEQAN3_HAS_ZLIB
25 #error "This file cannot be used when building without ZLIB-support."
36 namespace seqan3::contrib
40 const size_t GZ_OUTPUT_DEFAULT_BUFFER_SIZE = 921600;
50 StrategyHuffmanOnly = 2,
60 template <
typename Elem,
63 typename ByteT =
unsigned char,
66 class basic_gz_ostreambuf :
71 typedef ElemA char_allocator_type;
72 typedef ByteT byte_type;
73 typedef ByteAT byte_allocator_type;
74 typedef byte_type * byte_buffer_type;
75 typedef Tr traits_type;
76 typedef typename Tr::char_type char_type;
77 typedef typename Tr::int_type int_type;
83 basic_gz_ostreambuf(ostream_reference ostream_,
90 ~basic_gz_ostreambuf();
107 size_t fill_input_buffer();
111 ostream_reference m_ostream;
112 z_stream m_zip_stream;
114 byte_vector_type m_output_buffer;
115 char_vector_type m_buffer;
122 template <
typename Elem,
127 basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::basic_gz_ostreambuf(
128 ostream_reference ostream_,
132 size_t memory_level_,
136 m_output_buffer(buffer_size_, 0),
137 m_buffer(buffer_size_, 0)
139 m_zip_stream.zalloc = (alloc_func)0;
140 m_zip_stream.zfree = (free_func)0;
142 m_zip_stream.next_in = NULL;
143 m_zip_stream.avail_in = 0;
144 m_zip_stream.avail_out = 0;
145 m_zip_stream.next_out = NULL;
147 m_err = deflateInit2(
149 std::min(9, static_cast<int>(level_)),
151 static_cast<int>(window_size_),
152 std::min(9, static_cast<int>(memory_level_)),
153 static_cast<int>(strategy_)
156 this->setp(&(m_buffer[0]), &(m_buffer[m_buffer.size() - 1]));
159 template <
typename Elem,
164 basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::~basic_gz_ostreambuf()
168 m_err = deflateEnd(&m_zip_stream);
171 template <
typename Elem,
176 int basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::sync()
178 if (this->pptr() && this->pptr() > this->pbase())
180 if (traits_type::eq_int_type(overflow(traits_type::eof()), traits_type::eof()))
187 template <
typename Elem,
192 typename basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::int_type
193 basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::overflow(
194 typename basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::int_type c)
196 int w = static_cast<int>(this->pptr() - this->pbase());
198 if (!traits_type::eq_int_type(c, traits_type::eof()))
204 if (zip_to_stream(this->pbase(), w))
206 this->setp(this->pbase(), this->epptr() - 1);
211 return traits_type::eof();
215 template <
typename Elem,
220 bool basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::zip_to_stream(
221 typename basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::char_type * buffer_,
226 m_zip_stream.next_in = (byte_buffer_type)buffer_;
227 m_zip_stream.avail_in = static_cast<uInt>(buffer_size_ *
sizeof(
char_type));
228 m_zip_stream.avail_out = static_cast<uInt>(m_output_buffer.size());
229 m_zip_stream.next_out = &(m_output_buffer[0]);
234 m_err = deflate(&m_zip_stream, 0);
236 if (m_err == Z_OK || m_err == Z_STREAM_END)
238 written_byte_size = static_cast<std::streamsize>(m_output_buffer.size()) - m_zip_stream.avail_out;
239 total_written_byte_size += written_byte_size;
242 m_ostream.write((
const char_type *) &(m_output_buffer[0]),
243 static_cast<std::streamsize>(written_byte_size /
sizeof(
char_type)));
246 if ((remainder = written_byte_size %
sizeof(
char_type)) != 0)
250 &(m_output_buffer[written_byte_size - remainder]),
254 m_zip_stream.avail_out = static_cast<uInt>(m_output_buffer.size() -
remainder);
255 m_zip_stream.next_out = &m_output_buffer[
remainder];
258 while (m_zip_stream.avail_in != 0 && m_err == Z_OK);
260 return m_err == Z_OK;
263 template <
typename Elem,
268 std::streamsize basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::flush(
int flush_mode)
270 int const buffer_size = static_cast<int>(this->pptr() - this->pbase());
274 m_zip_stream.next_in = (byte_buffer_type) this->pbase();
275 m_zip_stream.avail_in = static_cast<uInt>(buffer_size *
sizeof(
char_type));
276 m_zip_stream.avail_out = static_cast<uInt>(m_output_buffer.size());
277 m_zip_stream.next_out = &(m_output_buffer[0]);
282 m_err = deflate(&m_zip_stream, flush_mode);
283 if (m_err == Z_OK || m_err == Z_STREAM_END)
285 written_byte_size = static_cast<std::streamsize>(m_output_buffer.size()) - m_zip_stream.avail_out;
286 total_written_byte_size += written_byte_size;
289 m_ostream.write((
const char_type *) &(m_output_buffer[0]),
290 static_cast<std::streamsize>(written_byte_size /
sizeof(
char_type) *
sizeof(byte_type)));
293 if ((remainder = written_byte_size %
sizeof(
char_type)) != 0)
297 &(m_output_buffer[written_byte_size - remainder]),
301 m_zip_stream.avail_out = static_cast<uInt>(m_output_buffer.size() -
remainder);
302 m_zip_stream.next_out = &m_output_buffer[
remainder];
305 while (m_err == Z_OK);
309 return total_written_byte_size;
312 template <
typename Elem,
317 std::streamsize basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::flush()
319 return flush(Z_SYNC_FLUSH);
322 template <
typename Elem,
327 std::streamsize basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::flush_finalize()
329 return flush(Z_FINISH);
338 template <
typename Elem,
341 typename ByteT =
unsigned char,
344 class basic_gz_ostreambase :
349 typedef basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT> zip_streambuf_type;
353 basic_gz_ostreambase(ostream_reference ostream_,
357 size_t memory_level_,
358 size_t buffer_size_) :
359 m_buf(ostream_, level_, strategy_, window_size_, memory_level_, buffer_size_)
365 zip_streambuf_type *
rdbuf() {
return &m_buf; }
368 zip_streambuf_type m_buf;
392 template <
typename Elem,
395 typename ByteT =
unsigned char,
398 class basic_gz_ostream :
399 public basic_gz_ostreambase<Elem, Tr, ElemA, ByteT, ByteAT>,
403 typedef basic_gz_ostreambase<Elem, Tr, ElemA, ByteT, ByteAT> zip_ostreambase_type;
405 typedef ostream_type & ostream_reference;
417 basic_gz_ostream(ostream_reference ostream_,
418 size_t level_ = Z_DEFAULT_COMPRESSION,
419 EStrategy strategy_ = DefaultStrategy,
420 size_t window_size_ = 31,
421 size_t memory_level_ = 8,
422 size_t buffer_size_ = GZ_OUTPUT_DEFAULT_BUFFER_SIZE) :
423 zip_ostreambase_type(ostream_, level_, strategy_, window_size_, memory_level_, buffer_size_),
424 ostream_type(this->rdbuf())
429 ostream_type::flush(); this->
rdbuf()->flush_finalize();
433 basic_gz_ostream<Elem, Tr> &
flush()
435 ostream_type::flush(); this->
rdbuf()->flush();
return *
this;
440 void _Add_vtordisp1() {}
441 void _Add_vtordisp2() {}
450 typedef basic_gz_ostream<char> gz_ostream;
452 typedef basic_gz_ostream<wchar_t> gz_wostream;