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;
241 m_ostream.write((
const char_type *) &(m_output_buffer[0]),
245 if ((remainder = written_byte_size %
sizeof(char_type)) != 0)
249 &(m_output_buffer[written_byte_size - remainder]),
253 m_zip_stream.avail_out =
static_cast<uInt
>(m_output_buffer.size() -
remainder);
254 m_zip_stream.next_out = &m_output_buffer[
remainder];
257 while (m_zip_stream.avail_in != 0 && m_err == Z_OK);
259 return m_err == Z_OK;
262template <
typename Elem,
267std::streamsize basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::flush(
int flush_mode)
269 int const buffer_size =
static_cast<int>(this->pptr() - this->pbase());
273 m_zip_stream.next_in = (byte_buffer_type) this->pbase();
274 m_zip_stream.avail_in =
static_cast<uInt
>(buffer_size *
sizeof(char_type));
275 m_zip_stream.avail_out =
static_cast<uInt
>(m_output_buffer.size());
276 m_zip_stream.next_out = &(m_output_buffer[0]);
281 m_err = deflate(&m_zip_stream, flush_mode);
282 if (m_err == Z_OK || m_err == Z_STREAM_END)
284 written_byte_size =
static_cast<std::streamsize>(m_output_buffer.size()) - m_zip_stream.avail_out;
285 total_written_byte_size += written_byte_size;
288 m_ostream.write((
const char_type *) &(m_output_buffer[0]),
289 static_cast<std::streamsize>(written_byte_size /
sizeof(char_type) *
sizeof(byte_type)));
292 if ((remainder = written_byte_size %
sizeof(char_type)) != 0)
296 &(m_output_buffer[written_byte_size - remainder]),
300 m_zip_stream.avail_out =
static_cast<uInt
>(m_output_buffer.size() -
remainder);
301 m_zip_stream.next_out = &m_output_buffer[
remainder];
304 while (m_err == Z_OK);
308 return total_written_byte_size;
311template <
typename Elem,
316std::streamsize basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::flush()
318 return flush(Z_SYNC_FLUSH);
321template <
typename Elem,
326std::streamsize basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::flush_finalize()
328 return flush(Z_FINISH);
337template <
typename Elem,
340 typename ByteT =
unsigned char,
343class basic_gz_ostreambase :
348 typedef basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT> zip_streambuf_type;
352 basic_gz_ostreambase(ostream_reference ostream_,
356 size_t memory_level_,
357 size_t buffer_size_) :
358 m_buf(ostream_, level_, strategy_, window_size_, memory_level_, buffer_size_)
364 zip_streambuf_type *
rdbuf() {
return &m_buf; }
367 zip_streambuf_type m_buf;
391template <
typename Elem,
394 typename ByteT =
unsigned char,
397class basic_gz_ostream :
398 public basic_gz_ostreambase<Elem, Tr, ElemA, ByteT, ByteAT>,
402 typedef basic_gz_ostreambase<Elem, Tr, ElemA, ByteT, ByteAT> zip_ostreambase_type;
404 typedef ostream_type & ostream_reference;
416 basic_gz_ostream(ostream_reference ostream_,
417 size_t level_ = Z_DEFAULT_COMPRESSION,
418 EStrategy strategy_ = DefaultStrategy,
419 size_t window_size_ = 31,
420 size_t memory_level_ = 8,
421 size_t buffer_size_ = GZ_OUTPUT_DEFAULT_BUFFER_SIZE) :
422 zip_ostreambase_type(ostream_, level_, strategy_, window_size_, memory_level_, buffer_size_),
423 ostream_type(this->rdbuf())
428 ostream_type::flush(); this->
rdbuf()->flush_finalize();
432 basic_gz_ostream<Elem, Tr> &
flush()
434 ostream_type::flush(); this->
rdbuf()->flush();
return *
this;
439 void _Add_vtordisp1() {}
440 void _Add_vtordisp2() {}
449typedef basic_gz_ostream<char> gz_ostream;
451typedef basic_gz_ostream<wchar_t> gz_wostream;