SeqAn3  3.0.2
The Modern C++ library for sequence analysis.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
bz2_ostream.hpp
1 // bzip2stream Library License:
2 // --------------------------
3 //
4 // The zlib/libpng License Copyright (c) 2003 Jonathan de Halleux.
5 //
6 // This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
7 //
8 // Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
9 //
10 // 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
11 //
12 // 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 //
14 // 3. This notice may not be removed or altered from any source distribution
15 //
16 // Author: Jonathan de Halleux, dehalleux@pelikhan.com, 2003
17 // Altered bzip2_stream header
18 // Author: Hannes Hauswedell <hannes.hauswedell@fu-berlin.de>
19 
20 #pragma once
21 
22 #include <algorithm>
23 #include <cstring>
24 #include <iostream>
25 #include <vector>
26 
27 #ifndef SEQAN3_HAS_BZIP2
28 #error "This file cannot be used when building without BZIP2-support."
29 #endif
30 
31 #define BZ_NO_STDIO
32 #include <bzlib.h>
33 
34 namespace seqan3::contrib
35 {
36 
37 // --------------------------------------------------------------------------
38 // Class basic_bz2_ostreambuf
39 // --------------------------------------------------------------------------
40 
41 const size_t BZ2_OUTPUT_DEFAULT_BUFFER_SIZE = 4096;
42 
43 template<
44  typename Elem,
45  typename Tr = std::char_traits<Elem>,
46  typename ElemA = std::allocator<Elem>,
47  typename ByteT = char,
48  typename ByteAT = std::allocator<ByteT>
49 >
50 class basic_bz2_ostreambuf :
51  public std::basic_streambuf<Elem, Tr>
52 {
53 public:
54  typedef std::basic_streambuf< Elem, Tr > basic_streambuf_type;
55  typedef std::basic_ostream<Elem, Tr>& ostream_reference;
56  typedef ElemA char_allocator_type;
57  typedef ByteT byte_type;
58  typedef ByteAT byte_allocator_type;
59  typedef byte_type* byte_buffer_type;
60  typedef typename Tr::char_type char_type;
61  typedef typename Tr::int_type int_type;
62  typedef std::vector<byte_type, byte_allocator_type > byte_vector_type;
63  typedef std::vector<char_type, char_allocator_type > char_vector_type;
64 
68 
69  basic_bz2_ostreambuf(
70  ostream_reference ostream_,
71  size_t block_size_100k_ ,
72  size_t verbosity_ ,
73  size_t work_factor_,
74  size_t buffer_size_
75  );
76 
77  ~basic_bz2_ostreambuf();
78 
79  int sync ();
80  int_type overflow (int_type c);
81 
82  std::streamsize flush(int flush_mode);
83  int get_zerr() const
84  { return m_err;};
85  uint64_t get_in_size() const
86  {
87  return ((uint64_t)m_bzip2_stream.total_in_hi32 << 32)
88  + m_bzip2_stream.total_in_lo32;
89  }
90  uint64_t get_out_size() const
91  {
92  return ((uint64_t)m_bzip2_stream.total_out_hi32 << 32)
93  + m_bzip2_stream.total_out_lo32;
94  }
95 private:
96  bool bzip2_to_stream( char_type*, std::streamsize);
97  size_t fill_input_buffer();
98 
99  ostream_reference m_ostream;
100  bz_stream m_bzip2_stream;
101  int m_err;
102  byte_vector_type m_output_buffer;
103  char_vector_type m_buffer;
104 };
105 
106 // --------------------------------------------------------------------------
107 // Class basic_bz2_ostreambuf implementation
108 // --------------------------------------------------------------------------
109 
110 template<
111  typename Elem,
112  typename Tr,
113  typename ElemA,
114  typename ByteT,
115  typename ByteAT
116 >
117 basic_bz2_ostreambuf<
118  Elem,Tr,ElemA,ByteT,ByteAT
119  >:: basic_bz2_ostreambuf(
120  ostream_reference ostream_,
121  size_t block_size_100k_,
122  size_t verbosity_,
123  size_t work_factor_,
124  size_t buffer_size_
125  )
126 :
127  m_ostream(ostream_),
128  m_output_buffer(buffer_size_,0),
129  m_buffer(buffer_size_,0)
130 {
131  m_bzip2_stream.bzalloc=NULL;
132  m_bzip2_stream.bzfree=NULL;
133 
134  m_bzip2_stream.next_in=NULL;
135  m_bzip2_stream.avail_in=0;
136  m_bzip2_stream.avail_out=0;
137  m_bzip2_stream.next_out=NULL;
138 
139  m_err=BZ2_bzCompressInit(
140  &m_bzip2_stream,
141  std::min( 9, static_cast<int>(block_size_100k_) ),
142  std::min( 4, static_cast<int>(verbosity_) ),
143  std::min( 250, static_cast<int>(work_factor_) )
144  );
145 
146  this->setp( &(m_buffer[0]), &(m_buffer[m_buffer.size()-1]));
147 }
148 
149 template<
150  typename Elem,
151  typename Tr,
152  typename ElemA,
153  typename ByteT,
154  typename ByteAT
155 >
156 basic_bz2_ostreambuf<
157  Elem,Tr,ElemA,ByteT,ByteAT
158  >::~basic_bz2_ostreambuf()
159 {
160  flush(BZ_FINISH);
161  m_ostream.flush();
162  m_err=BZ2_bzCompressEnd(&m_bzip2_stream);
163 }
164 
165 template<
166  typename Elem,
167  typename Tr,
168  typename ElemA,
169  typename ByteT,
170  typename ByteAT
171 >
172 int basic_bz2_ostreambuf<
173  Elem,Tr,ElemA,ByteT,ByteAT
174  >::sync ()
175 {
176  if ( this->pptr() && this->pptr() > this->pbase())
177  {
178  int c = overflow( EOF);
179 
180  if ( c == EOF)
181  return -1;
182  }
183 
184  return 0;
185 }
186 
187 template<
188  typename Elem,
189  typename Tr,
190  typename ElemA,
191  typename ByteT,
192  typename ByteAT
193 >
194 typename basic_bz2_ostreambuf<
195  Elem,Tr,ElemA,ByteT,ByteAT
196  >::int_type
197  basic_bz2_ostreambuf<
198  Elem,Tr,ElemA,ByteT,ByteAT
199  >::overflow (
200  typename basic_bz2_ostreambuf<
201  Elem,Tr,ElemA,ByteT,ByteAT
202  >::int_type c
203  )
204 {
205  int w = static_cast<int>(this->pptr() - this->pbase());
206  if (c != EOF) {
207  *this->pptr() = c;
208  ++w;
209  }
210  if ( bzip2_to_stream( this->pbase(), w)) {
211  this->setp( this->pbase(), this->epptr());
212  return c;
213  } else
214  return EOF;
215 }
216 
217 template<
218  typename Elem,
219  typename Tr,
220  typename ElemA,
221  typename ByteT,
222  typename ByteAT
223 >
224 bool basic_bz2_ostreambuf<
225  Elem,Tr,ElemA,ByteT,ByteAT
226  >::bzip2_to_stream(
227  typename basic_bz2_ostreambuf<
228  Elem,Tr,ElemA,ByteT,ByteAT
229  >::char_type* buffer_,
230  std::streamsize buffer_size_
231  )
232 {
233  std::streamsize written_byte_size=0, total_written_byte_size = 0;
234 
235  m_bzip2_stream.next_in=(byte_buffer_type)buffer_;
236  m_bzip2_stream.avail_in=buffer_size_*sizeof(char_type);
237  m_bzip2_stream.avail_out=static_cast<unsigned int>(m_output_buffer.size());
238  m_bzip2_stream.next_out=&(m_output_buffer[0]);
239  size_t remainder=0;
240 
241  do
242  {
243  m_err = BZ2_bzCompress (&m_bzip2_stream, BZ_RUN );
244 
245  if (m_err == BZ_RUN_OK || m_err == BZ_STREAM_END)
246  {
247  written_byte_size= static_cast<std::streamsize>(m_output_buffer.size()) - m_bzip2_stream.avail_out;
248  total_written_byte_size+=written_byte_size;
249  // ouput buffer is full, dumping to ostream
250  m_ostream.write(
251  (const char_type*) &(m_output_buffer[0]),
252  static_cast<std::streamsize>( written_byte_size/sizeof(char_type) )
253  );
254 
255  // checking if some bytes were not written.
256  if ( (remainder = written_byte_size%sizeof(char_type))!=0)
257  {
258  // copy to the beginning of the stream
259  std::memmove(
260  &(m_output_buffer[0]),
261  &(m_output_buffer[written_byte_size-remainder]),
262  remainder);
263 
264  }
265 
266  m_bzip2_stream.avail_out=static_cast<unsigned int>(m_output_buffer.size()-remainder);
267  m_bzip2_stream.next_out=&m_output_buffer[remainder];
268  }
269  }
270  while (m_bzip2_stream.avail_in != 0 && m_err == BZ_RUN_OK);
271 
272  return m_err == BZ_RUN_OK || m_err == BZ_FLUSH_OK;
273 }
274 
275 template<
276  typename Elem,
277  typename Tr,
278  typename ElemA,
279  typename ByteT,
280  typename ByteAT
281 >
282 std::streamsize basic_bz2_ostreambuf<
283  Elem,Tr,ElemA,ByteT,ByteAT
284  >::flush(int flush_mode)
285 {
286  std::streamsize written_byte_size=0, total_written_byte_size=0;
287 
288  int const buffer_size = static_cast< int >( pptr() - pbase() ); // amount of data currently in buffer
289 
290  m_bzip2_stream.next_in=(byte_buffer_type)pbase();
291  m_bzip2_stream.avail_in=static_cast< unsigned int >(buffer_size*sizeof(char_type));
292  m_bzip2_stream.avail_out=static_cast< unsigned int >(m_output_buffer.size());
293  m_bzip2_stream.next_out=&(m_output_buffer[0]);
294  size_t remainder=0;
295 
296  do
297  {
298  m_err = BZ2_bzCompress (&m_bzip2_stream, flush_mode);
299  if (m_err == BZ_FINISH_OK || m_err == BZ_STREAM_END)
300  {
301  written_byte_size=
302  static_cast<std::streamsize>(m_output_buffer.size())
303  - m_bzip2_stream.avail_out;
304  total_written_byte_size+=written_byte_size;
305  // ouput buffer is full, dumping to ostream
306  m_ostream.write(
307  (const char_type*) &(m_output_buffer[0]),
308  static_cast<std::streamsize>( written_byte_size/sizeof(char_type)*sizeof(char) )
309  );
310 
311  // checking if some bytes were not written.
312  if ( (remainder = written_byte_size%sizeof(char_type))!=0)
313  {
314  // copy to the beginning of the stream
315  std::memmove(
316  &(m_output_buffer[0]),
317  &(m_output_buffer[written_byte_size-remainder]),
318  remainder);
319 
320  }
321 
322  m_bzip2_stream.avail_out=static_cast<unsigned int>(m_output_buffer.size()-remainder);
323  m_bzip2_stream.next_out=&(m_output_buffer[remainder]);
324  }
325  } while (m_err == BZ_FINISH_OK);
326 
327  m_ostream.flush();
328 
329  return total_written_byte_size;
330 }
331 
332 // --------------------------------------------------------------------------
333 // Class basic_bz2_ostreambase
334 // --------------------------------------------------------------------------
335 
336 template<
337  typename Elem,
338  typename Tr = std::char_traits<Elem>,
339  typename ElemA = std::allocator<Elem>,
340  typename ByteT = char,
341  typename ByteAT = std::allocator<ByteT>
342 >
343 class basic_bz2_ostreambase : virtual public std::basic_ios<Elem,Tr>
344 {
345 public:
346  typedef std::basic_ostream<Elem, Tr>& ostream_reference;
347  typedef basic_bz2_ostreambuf<
348  Elem,Tr,ElemA,ByteT,ByteAT> bzip2_streambuf_type;
349 
350  basic_bz2_ostreambase(
351  ostream_reference ostream_,
352  size_t block_size_100k_ ,
353  size_t verbosity_ ,
354  size_t work_factor_,
355  size_t buffer_size_
356  )
357  : m_buf(ostream_,block_size_100k_, verbosity_, work_factor_, buffer_size_)
358  {
359  this->init(&m_buf );
360  };
361 
362  bzip2_streambuf_type* rdbuf() { return &m_buf; };
363 
364 private:
365  bzip2_streambuf_type m_buf;
366 };
367 
368 // --------------------------------------------------------------------------
369 // Class basic_bz2_ostream
370 // --------------------------------------------------------------------------
371 
372 template<
373  typename Elem,
374  typename Tr = std::char_traits<Elem>,
375  typename ElemA = std::allocator<Elem>,
376  typename ByteT = char,
377  typename ByteAT = std::allocator<ByteT>
378 >
379 class basic_bz2_ostream :
380  public basic_bz2_ostreambase<Elem,Tr,ElemA,ByteT,ByteAT>,
381  public std::basic_ostream<Elem,Tr>
382 {
383 public:
384  typedef basic_bz2_ostreambase<
385  Elem,Tr,ElemA,ByteT,ByteAT> bzip2_ostreambase_type;
386  typedef std::basic_ostream<Elem,Tr> ostream_type;
387  typedef ostream_type& ostream_reference;
388 
389  basic_bz2_ostream(
390  ostream_reference ostream_,
391  size_t block_size_100k_ = 9,
392  size_t verbosity_ = 0,
393  size_t work_factor_ = 30,
394  size_t buffer_size_ = BZ2_OUTPUT_DEFAULT_BUFFER_SIZE
395  )
396  :
397  bzip2_ostreambase_type(ostream_,block_size_100k_, verbosity_, work_factor_,buffer_size_),
398  ostream_type(bzip2_ostreambase_type::rdbuf())
399  {
400 
401  };
402 
403  basic_bz2_ostream& add_header();
404  basic_bz2_ostream& zflush()
405  {
406  this->flush(); this->rdbuf()->flush(); return *this;
407  };
408 
409 #ifdef _WIN32
410 private:
411  void _Add_vtordisp1() { } // Required to avoid VC++ warning C4250
412  void _Add_vtordisp2() { } // Required to avoid VC++ warning C4250
413 #endif
414 };
415 
416 // --------------------------------------------------------------------------
417 // Typedefs
418 // --------------------------------------------------------------------------
419 
420 typedef basic_bz2_ostream<char> bz2_ostream;
421 typedef basic_bz2_ostream<wchar_t> bz2_wostream;
422 
423 } // namespace seqan3::contrib
std::basic_ios::rdbuf
T rdbuf(T... args)
cstring
output_stream_over::int_type
typename stream::int_type int_type
Declares the associated int type.
output_stream_over::char_type
typename stream::char_type char_type
Declares the associated char type.
vector
std::basic_streambuf::epptr
T epptr(T... args)
std::remainder
T remainder(T... args)
std::basic_streambuf
iostream
std::basic_streambuf< Elem, std::char_traits< Elem > >::sync
T sync(T... args)
std::char_traits
std::streamsize
std::basic_ostream
std::flush
T flush(T... args)
std::basic_ios::init
T init(T... args)
std::min
T min(T... args)
std::basic_streambuf< Elem, std::char_traits< Elem > >::overflow
T overflow(T... args)
std::allocator
std::memmove
T memmove(T... args)
std::basic_ios