28#if !defined(SEQAN3_HAS_ZLIB) && !defined(SEQAN3_HEADER_TEST)
29#error "This file cannot be used when building without ZLIB-support."
32#if defined(SEQAN3_HAS_ZLIB)
36namespace seqan3::contrib
40const size_t GZ_OUTPUT_DEFAULT_BUFFER_SIZE = 921600;
50 StrategyHuffmanOnly = 2,
60template <
typename Elem,
63 typename ByteT =
unsigned char,
66class 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();
93 int_type overflow(int_type c);
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;
122template <
typename Elem,
127basic_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]));
159template <
typename Elem,
164basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::~basic_gz_ostreambuf()
168 m_err = deflateEnd(&m_zip_stream);
171template <
typename Elem,
176int 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()))
187template <
typename Elem,
192typename basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::int_type
193basic_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();
215template <
typename Elem,
220bool 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]),
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;
263template <
typename Elem,
268std::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]),
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;
312template <
typename Elem,
317std::streamsize basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::flush()
319 return flush(Z_SYNC_FLUSH);
322template <
typename Elem,
327std::streamsize basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::flush_finalize()
329 return flush(Z_FINISH);
338template <
typename Elem,
341 typename ByteT =
unsigned char,
344class 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;
392template <
typename Elem,
395 typename ByteT =
unsigned char,
398class 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() {}
450typedef basic_gz_ostream<char> gz_ostream;
452typedef basic_gz_ostream<wchar_t> gz_wostream;
typename stream::char_type char_type
Declares the associated char type.