24 #ifndef SEQAN3_HAS_ZLIB
25 #error "This file cannot be used when building without ZLIB-support."
34 namespace seqan3::contrib
38 const size_t GZ_OUTPUT_DEFAULT_BUFFER_SIZE = 921600;
48 StrategyHuffmanOnly = 2,
58 template <
typename Elem,
61 typename ByteT =
unsigned char,
64 class basic_gz_ostreambuf :
69 typedef ElemA char_allocator_type;
70 typedef ByteT byte_type;
71 typedef ByteAT byte_allocator_type;
72 typedef byte_type * byte_buffer_type;
73 typedef Tr traits_type;
74 typedef typename Tr::char_type char_type;
75 typedef typename Tr::int_type int_type;
81 basic_gz_ostreambuf(ostream_reference ostream_,
88 ~basic_gz_ostreambuf();
105 size_t fill_input_buffer();
109 ostream_reference m_ostream;
110 z_stream m_zip_stream;
112 byte_vector_type m_output_buffer;
113 char_vector_type m_buffer;
120 template <
typename Elem,
125 basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::basic_gz_ostreambuf(
126 ostream_reference ostream_,
130 size_t memory_level_,
134 m_output_buffer(buffer_size_, 0),
135 m_buffer(buffer_size_, 0)
137 m_zip_stream.zalloc = (alloc_func)0;
138 m_zip_stream.zfree = (free_func)0;
140 m_zip_stream.next_in = NULL;
141 m_zip_stream.avail_in = 0;
142 m_zip_stream.avail_out = 0;
143 m_zip_stream.next_out = NULL;
145 m_err = deflateInit2(
147 std::min(9,
static_cast<int>(level_)),
149 static_cast<int>(window_size_),
150 std::min(9,
static_cast<int>(memory_level_)),
151 static_cast<int>(strategy_)
154 this->setp(&(m_buffer[0]), &(m_buffer[m_buffer.size() - 1]));
157 template <
typename Elem,
162 basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::~basic_gz_ostreambuf()
166 m_err = deflateEnd(&m_zip_stream);
169 template <
typename Elem,
174 int basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::sync()
176 if (this->pptr() && this->pptr() > this->pbase())
178 if (traits_type::eq_int_type(overflow(traits_type::eof()), traits_type::eof()))
185 template <
typename Elem,
190 typename basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::int_type
191 basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::overflow(
192 typename basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::int_type c)
194 int w =
static_cast<int>(this->pptr() - this->pbase());
196 if (!traits_type::eq_int_type(c, traits_type::eof()))
202 if (zip_to_stream(this->pbase(), w))
204 this->setp(this->pbase(), this->epptr() - 1);
209 return traits_type::eof();
213 template <
typename Elem,
218 bool basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::zip_to_stream(
219 typename basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::char_type * buffer_,
224 m_zip_stream.next_in = (byte_buffer_type)buffer_;
225 m_zip_stream.avail_in =
static_cast<uInt
>(buffer_size_ *
sizeof(
char_type));
226 m_zip_stream.avail_out =
static_cast<uInt
>(m_output_buffer.size());
227 m_zip_stream.next_out = &(m_output_buffer[0]);
232 m_err = deflate(&m_zip_stream, 0);
234 if (m_err == Z_OK || m_err == Z_STREAM_END)
236 written_byte_size =
static_cast<std::streamsize>(m_output_buffer.size()) - m_zip_stream.avail_out;
237 total_written_byte_size += written_byte_size;
240 m_ostream.write((
const char_type *) &(m_output_buffer[0]),
244 if ((remainder = written_byte_size %
sizeof(
char_type)) != 0)
248 &(m_output_buffer[written_byte_size - remainder]),
252 m_zip_stream.avail_out =
static_cast<uInt
>(m_output_buffer.size() -
remainder);
253 m_zip_stream.next_out = &m_output_buffer[
remainder];
256 while (m_zip_stream.avail_in != 0 && m_err == Z_OK);
258 return m_err == Z_OK;
261 template <
typename Elem,
266 std::streamsize basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::flush(
int flush_mode)
268 int const buffer_size =
static_cast<int>(this->pptr() - this->pbase());
272 m_zip_stream.next_in = (byte_buffer_type) this->pbase();
273 m_zip_stream.avail_in =
static_cast<uInt
>(buffer_size *
sizeof(
char_type));
274 m_zip_stream.avail_out =
static_cast<uInt
>(m_output_buffer.size());
275 m_zip_stream.next_out = &(m_output_buffer[0]);
280 m_err = deflate(&m_zip_stream, flush_mode);
281 if (m_err == Z_OK || m_err == Z_STREAM_END)
283 written_byte_size =
static_cast<std::streamsize>(m_output_buffer.size()) - m_zip_stream.avail_out;
284 total_written_byte_size += written_byte_size;
287 m_ostream.write((
const char_type *) &(m_output_buffer[0]),
291 if ((remainder = written_byte_size %
sizeof(
char_type)) != 0)
295 &(m_output_buffer[written_byte_size - remainder]),
299 m_zip_stream.avail_out =
static_cast<uInt
>(m_output_buffer.size() -
remainder);
300 m_zip_stream.next_out = &m_output_buffer[
remainder];
303 while (m_err == Z_OK);
307 return total_written_byte_size;
310 template <
typename Elem,
315 std::streamsize basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::flush()
317 return flush(Z_SYNC_FLUSH);
320 template <
typename Elem,
325 std::streamsize basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT>::flush_finalize()
327 return flush(Z_FINISH);
336 template <
typename Elem,
339 typename ByteT =
unsigned char,
342 class basic_gz_ostreambase :
347 typedef basic_gz_ostreambuf<Elem, Tr, ElemA, ByteT, ByteAT> zip_streambuf_type;
351 basic_gz_ostreambase(ostream_reference ostream_,
355 size_t memory_level_,
356 size_t buffer_size_) :
357 m_buf(ostream_, level_, strategy_, window_size_, memory_level_, buffer_size_)
363 zip_streambuf_type *
rdbuf() {
return &m_buf; }
366 zip_streambuf_type m_buf;
390 template <
typename Elem,
393 typename ByteT =
unsigned char,
396 class basic_gz_ostream :
397 public basic_gz_ostreambase<Elem, Tr, ElemA, ByteT, ByteAT>,
401 typedef basic_gz_ostreambase<Elem, Tr, ElemA, ByteT, ByteAT> zip_ostreambase_type;
403 typedef ostream_type & ostream_reference;
415 basic_gz_ostream(ostream_reference ostream_,
416 size_t level_ = Z_DEFAULT_COMPRESSION,
417 EStrategy strategy_ = DefaultStrategy,
418 size_t window_size_ = 31,
419 size_t memory_level_ = 8,
420 size_t buffer_size_ = GZ_OUTPUT_DEFAULT_BUFFER_SIZE) :
421 zip_ostreambase_type(ostream_, level_, strategy_, window_size_, memory_level_, buffer_size_),
422 ostream_type(this->rdbuf())
427 ostream_type::flush(); this->
rdbuf()->flush_finalize();
431 basic_gz_ostream<Elem, Tr> &
flush()
433 ostream_type::flush(); this->
rdbuf()->flush();
return *
this;
438 void _Add_vtordisp1() {}
439 void _Add_vtordisp2() {}
448 typedef basic_gz_ostream<char> gz_ostream;
450 typedef basic_gz_ostream<wchar_t> gz_wostream;