30#if !defined(SEQAN3_HAS_ZLIB) && !defined(SEQAN3_HEADER_TEST)
31#error "This file cannot be used when building without ZLIB-support."
34#if defined(SEQAN3_HAS_ZLIB)
38namespace seqan3::contrib
42const size_t GZ_OUTPUT_DEFAULT_BUFFER_SIZE = 921600;
52 StrategyHuffmanOnly = 2,
62template <
typename Elem,
65 typename ByteT =
unsigned char,
68class basic_gz_ostreambuf :
73 typedef ElemA char_allocator_type;
74 typedef ByteT byte_type;
75 typedef ByteAT byte_allocator_type;
76 typedef byte_type * byte_buffer_type;
77 typedef Tr traits_type;
78 typedef typename Tr::char_type char_type;
79 typedef typename Tr::int_type int_type;
85 basic_gz_ostreambuf(ostream_reference ostream_,
92 ~basic_gz_ostreambuf();
95 int_type overflow(int_type c);
109 size_t fill_input_buffer();
113 ostream_reference m_ostream;
114 z_stream m_zip_stream;
116 byte_vector_type m_output_buffer;
117 char_vector_type m_buffer;
124template <
typename Elem,
129basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::basic_gz_ostreambuf(
130 ostream_reference ostream_,
134 size_t memory_level_,
138 m_output_buffer(buffer_size_, 0),
139 m_buffer(buffer_size_, 0)
141 m_zip_stream.zalloc = (alloc_func)0;
142 m_zip_stream.zfree = (free_func)0;
144 m_zip_stream.next_in = NULL;
145 m_zip_stream.avail_in = 0;
146 m_zip_stream.avail_out = 0;
147 m_zip_stream.next_out = NULL;
149 m_err = deflateInit2(
151 std::min(9,
static_cast<int>(level_)),
153 static_cast<int>(window_size_),
154 std::min(9,
static_cast<int>(memory_level_)),
155 static_cast<int>(strategy_)
158 this->setp(&(m_buffer[0]), &(m_buffer[m_buffer.size() - 1]));
161template <
typename Elem,
166basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::~basic_gz_ostreambuf()
170 m_err = deflateEnd(&m_zip_stream);
173template <
typename Elem,
178int basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::sync()
180 if (this->pptr() && this->pptr() > this->pbase())
182 if (traits_type::eq_int_type(overflow(traits_type::eof()), traits_type::eof()))
189template <
typename Elem,
194typename basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::int_type
195basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::overflow(
196 typename basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::int_type c)
198 int w =
static_cast<int>(this->pptr() - this->pbase());
200 if (!traits_type::eq_int_type(c, traits_type::eof()))
206 if (zip_to_stream(this->pbase(), w))
208 this->setp(this->pbase(), this->epptr() - 1);
213 return traits_type::eof();
217template <
typename Elem,
222bool basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::zip_to_stream(
223 typename basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::char_type * buffer_,
228 m_zip_stream.next_in = (byte_buffer_type)buffer_;
229 m_zip_stream.avail_in =
static_cast<uInt
>(buffer_size_ *
sizeof(char_type));
230 m_zip_stream.avail_out =
static_cast<uInt
>(m_output_buffer.size());
231 m_zip_stream.next_out = &(m_output_buffer[0]);
236 m_err = deflate(&m_zip_stream, 0);
238 if (m_err == Z_OK || m_err == Z_STREAM_END)
240 written_byte_size =
static_cast<std::streamsize>(m_output_buffer.size()) - m_zip_stream.avail_out;
243 m_ostream.write((
const char_type *) &(m_output_buffer[0]),
247 if ((remainder = written_byte_size %
sizeof(char_type)) != 0)
251 &(m_output_buffer[written_byte_size - remainder]),
255 m_zip_stream.avail_out =
static_cast<uInt
>(m_output_buffer.size() -
remainder);
256 m_zip_stream.next_out = &m_output_buffer[
remainder];
259 while (m_zip_stream.avail_in != 0 && m_err == Z_OK);
261 return m_err == Z_OK;
264template <
typename Elem,
269std::streamsize basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::flush(
int flush_mode)
271 int const buffer_size =
static_cast<int>(this->pptr() - this->pbase());
275 m_zip_stream.next_in = (byte_buffer_type) this->pbase();
276 m_zip_stream.avail_in =
static_cast<uInt
>(buffer_size *
sizeof(char_type));
277 m_zip_stream.avail_out =
static_cast<uInt
>(m_output_buffer.size());
278 m_zip_stream.next_out = &(m_output_buffer[0]);
283 m_err = deflate(&m_zip_stream, flush_mode);
284 if (m_err == Z_OK || m_err == Z_STREAM_END)
286 written_byte_size =
static_cast<std::streamsize>(m_output_buffer.size()) - m_zip_stream.avail_out;
287 total_written_byte_size += written_byte_size;
290 m_ostream.write((
const char_type *) &(m_output_buffer[0]),
291 static_cast<std::streamsize>(written_byte_size /
sizeof(char_type) *
sizeof(byte_type)));
294 if ((remainder = written_byte_size %
sizeof(char_type)) != 0)
298 &(m_output_buffer[written_byte_size - remainder]),
302 m_zip_stream.avail_out =
static_cast<uInt
>(m_output_buffer.size() -
remainder);
303 m_zip_stream.next_out = &m_output_buffer[
remainder];
306 while (m_err == Z_OK);
310 return total_written_byte_size;
313template <
typename Elem,
318std::streamsize basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::flush()
320 return flush(Z_SYNC_FLUSH);
323template <
typename Elem,
328std::streamsize basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::flush_finalize()
330 return flush(Z_FINISH);
339template <
typename Elem,
342 typename ByteT =
unsigned char,
345class basic_gz_ostreambase :
350 typedef basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT> zip_streambuf_type;
354 basic_gz_ostreambase(ostream_reference ostream_,
358 size_t memory_level_,
359 size_t buffer_size_) :
360 m_buf(ostream_, level_, strategy_, window_size_, memory_level_, buffer_size_)
366 zip_streambuf_type *
rdbuf() {
return &m_buf; }
369 zip_streambuf_type m_buf;
393template <
typename Elem,
396 typename ByteT =
unsigned char,
399class basic_gz_ostream :
400 public basic_gz_ostreambase<Elem, Tr, ElemA, ByteT, ByteAT>,
404 typedef basic_gz_ostreambase<Elem, Tr, ElemA, ByteT, ByteAT> zip_ostreambase_type;
406 typedef ostream_type & ostream_reference;
418 basic_gz_ostream(ostream_reference ostream_,
419 size_t level_ = Z_DEFAULT_COMPRESSION,
420 EStrategy strategy_ = DefaultStrategy,
421 size_t window_size_ = 31,
422 size_t memory_level_ = 8,
423 size_t buffer_size_ = GZ_OUTPUT_DEFAULT_BUFFER_SIZE) :
424 zip_ostreambase_type(ostream_, level_, strategy_, window_size_, memory_level_, buffer_size_),
425 ostream_type(this->rdbuf())
430 ostream_type::flush(); this->
rdbuf()->flush_finalize();
434 basic_gz_ostream<Elem, Tr> &
flush()
436 ostream_type::flush(); this->
rdbuf()->flush();
return *
this;
441 void _Add_vtordisp1() {}
442 void _Add_vtordisp2() {}
451typedef basic_gz_ostream<char> gz_ostream;
453typedef basic_gz_ostream<wchar_t> gz_wostream;