SeqAn3  3.0.1
The Modern C++ library for sequence analysis.
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 #include <seqan3/core/platform.hpp>
35 
36 namespace seqan3::contrib
37 {
38 
39 // --------------------------------------------------------------------------
40 // Class basic_bz2_ostreambuf
41 // --------------------------------------------------------------------------
42 
43 const size_t BZ2_OUTPUT_DEFAULT_BUFFER_SIZE = 4096;
44 
45 template<
46  typename Elem,
47  typename Tr = std::char_traits<Elem>,
48  typename ElemA = std::allocator<Elem>,
49  typename ByteT = char,
50  typename ByteAT = std::allocator<ByteT>
51 >
52 class basic_bz2_ostreambuf :
53  public std::basic_streambuf<Elem, Tr>
54 {
55 public:
56  typedef std::basic_streambuf< Elem, Tr > basic_streambuf_type;
57  typedef std::basic_ostream<Elem, Tr>& ostream_reference;
58  typedef ElemA char_allocator_type;
59  typedef ByteT byte_type;
60  typedef ByteAT byte_allocator_type;
61  typedef byte_type* byte_buffer_type;
62  typedef typename Tr::char_type char_type;
63  typedef typename Tr::int_type int_type;
64  typedef std::vector<byte_type, byte_allocator_type > byte_vector_type;
65  typedef std::vector<char_type, char_allocator_type > char_vector_type;
66 
70 
71  basic_bz2_ostreambuf(
72  ostream_reference ostream_,
73  size_t block_size_100k_ ,
74  size_t verbosity_ ,
75  size_t work_factor_,
76  size_t buffer_size_
77  );
78 
79  ~basic_bz2_ostreambuf();
80 
81  int sync ();
82  int_type overflow (int_type c);
83 
84  std::streamsize flush(int flush_mode);
85  int get_zerr() const
86  { return m_err;};
87  uint64_t get_in_size() const
88  {
89  return ((uint64_t)m_bzip2_stream.total_in_hi32 << 32)
90  + m_bzip2_stream.total_in_lo32;
91  }
92  uint64_t get_out_size() const
93  {
94  return ((uint64_t)m_bzip2_stream.total_out_hi32 << 32)
95  + m_bzip2_stream.total_out_lo32;
96  }
97 private:
98  bool bzip2_to_stream( char_type*, std::streamsize);
99  size_t fill_input_buffer();
100 
101  ostream_reference m_ostream;
102  bz_stream m_bzip2_stream;
103  int m_err;
104  byte_vector_type m_output_buffer;
105  char_vector_type m_buffer;
106 };
107 
108 // --------------------------------------------------------------------------
109 // Class basic_bz2_ostreambuf implementation
110 // --------------------------------------------------------------------------
111 
112 template<
113  typename Elem,
114  typename Tr,
115  typename ElemA,
116  typename ByteT,
117  typename ByteAT
118 >
119 basic_bz2_ostreambuf<
120  Elem,Tr,ElemA,ByteT,ByteAT
121  >:: basic_bz2_ostreambuf(
122  ostream_reference ostream_,
123  size_t block_size_100k_,
124  size_t verbosity_,
125  size_t work_factor_,
126  size_t buffer_size_
127  )
128 :
129  m_ostream(ostream_),
130  m_output_buffer(buffer_size_,0),
131  m_buffer(buffer_size_,0)
132 {
133  m_bzip2_stream.bzalloc=NULL;
134  m_bzip2_stream.bzfree=NULL;
135 
136  m_bzip2_stream.next_in=NULL;
137  m_bzip2_stream.avail_in=0;
138  m_bzip2_stream.avail_out=0;
139  m_bzip2_stream.next_out=NULL;
140 
141  m_err=BZ2_bzCompressInit(
142  &m_bzip2_stream,
143  std::min( 9, static_cast<int>(block_size_100k_) ),
144  std::min( 4, static_cast<int>(verbosity_) ),
145  std::min( 250, static_cast<int>(work_factor_) )
146  );
147 
148  this->setp( &(m_buffer[0]), &(m_buffer[m_buffer.size()-1]));
149 }
150 
151 template<
152  typename Elem,
153  typename Tr,
154  typename ElemA,
155  typename ByteT,
156  typename ByteAT
157 >
158 basic_bz2_ostreambuf<
159  Elem,Tr,ElemA,ByteT,ByteAT
160  >::~basic_bz2_ostreambuf()
161 {
162  flush(BZ_FINISH);
163  m_ostream.flush();
164  m_err=BZ2_bzCompressEnd(&m_bzip2_stream);
165 }
166 
167 template<
168  typename Elem,
169  typename Tr,
170  typename ElemA,
171  typename ByteT,
172  typename ByteAT
173 >
174 int basic_bz2_ostreambuf<
175  Elem,Tr,ElemA,ByteT,ByteAT
176  >::sync ()
177 {
178  if ( this->pptr() && this->pptr() > this->pbase())
179  {
180  int c = overflow( EOF);
181 
182  if ( c == EOF)
183  return -1;
184  }
185 
186  return 0;
187 }
188 
189 template<
190  typename Elem,
191  typename Tr,
192  typename ElemA,
193  typename ByteT,
194  typename ByteAT
195 >
196 typename basic_bz2_ostreambuf<
197  Elem,Tr,ElemA,ByteT,ByteAT
198  >::int_type
199  basic_bz2_ostreambuf<
200  Elem,Tr,ElemA,ByteT,ByteAT
201  >::overflow (
202  typename basic_bz2_ostreambuf<
203  Elem,Tr,ElemA,ByteT,ByteAT
204  >::int_type c
205  )
206 {
207  int w = static_cast<int>(this->pptr() - this->pbase());
208  if (c != EOF) {
209  *this->pptr() = c;
210  ++w;
211  }
212  if ( bzip2_to_stream( this->pbase(), w)) {
213  this->setp( this->pbase(), this->epptr());
214  return c;
215  } else
216  return EOF;
217 }
218 
219 template<
220  typename Elem,
221  typename Tr,
222  typename ElemA,
223  typename ByteT,
224  typename ByteAT
225 >
226 bool basic_bz2_ostreambuf<
227  Elem,Tr,ElemA,ByteT,ByteAT
228  >::bzip2_to_stream(
229  typename basic_bz2_ostreambuf<
230  Elem,Tr,ElemA,ByteT,ByteAT
231  >::char_type* buffer_,
232  std::streamsize buffer_size_
233  )
234 {
235  std::streamsize written_byte_size=0, total_written_byte_size = 0;
236 
237  m_bzip2_stream.next_in=(byte_buffer_type)buffer_;
238  m_bzip2_stream.avail_in=buffer_size_*sizeof(char_type);
239  m_bzip2_stream.avail_out=static_cast<unsigned int>(m_output_buffer.size());
240  m_bzip2_stream.next_out=&(m_output_buffer[0]);
241  size_t remainder=0;
242 
243  do
244  {
245  m_err = BZ2_bzCompress (&m_bzip2_stream, BZ_RUN );
246 
247  if (m_err == BZ_RUN_OK || m_err == BZ_STREAM_END)
248  {
249  written_byte_size= static_cast<std::streamsize>(m_output_buffer.size()) - m_bzip2_stream.avail_out;
250  total_written_byte_size+=written_byte_size;
251  // ouput buffer is full, dumping to ostream
252  m_ostream.write(
253  (const char_type*) &(m_output_buffer[0]),
254  static_cast<std::streamsize>( written_byte_size/sizeof(char_type) )
255  );
256 
257  // checking if some bytes were not written.
258  if ( (remainder = written_byte_size%sizeof(char_type))!=0)
259  {
260  // copy to the beginning of the stream
261  std::memmove(
262  &(m_output_buffer[0]),
263  &(m_output_buffer[written_byte_size-remainder]),
264  remainder);
265 
266  }
267 
268  m_bzip2_stream.avail_out=static_cast<unsigned int>(m_output_buffer.size()-remainder);
269  m_bzip2_stream.next_out=&m_output_buffer[remainder];
270  }
271  }
272  while (m_bzip2_stream.avail_in != 0 && m_err == BZ_RUN_OK);
273 
274  return m_err == BZ_RUN_OK || m_err == BZ_FLUSH_OK;
275 }
276 
277 template<
278  typename Elem,
279  typename Tr,
280  typename ElemA,
281  typename ByteT,
282  typename ByteAT
283 >
284 std::streamsize basic_bz2_ostreambuf<
285  Elem,Tr,ElemA,ByteT,ByteAT
286  >::flush(int flush_mode)
287 {
288  std::streamsize written_byte_size=0, total_written_byte_size=0;
289 
290  int const buffer_size = static_cast< int >( pptr() - pbase() ); // amount of data currently in buffer
291 
292  m_bzip2_stream.next_in=(byte_buffer_type)pbase();
293  m_bzip2_stream.avail_in=static_cast< unsigned int >(buffer_size*sizeof(char_type));
294  m_bzip2_stream.avail_out=static_cast< unsigned int >(m_output_buffer.size());
295  m_bzip2_stream.next_out=&(m_output_buffer[0]);
296  size_t remainder=0;
297 
298  do
299  {
300  m_err = BZ2_bzCompress (&m_bzip2_stream, flush_mode);
301  if (m_err == BZ_FINISH_OK || m_err == BZ_STREAM_END)
302  {
303  written_byte_size=
304  static_cast<std::streamsize>(m_output_buffer.size())
305  - m_bzip2_stream.avail_out;
306  total_written_byte_size+=written_byte_size;
307  // ouput buffer is full, dumping to ostream
308  m_ostream.write(
309  (const char_type*) &(m_output_buffer[0]),
310  static_cast<std::streamsize>( written_byte_size/sizeof(char_type)*sizeof(char) )
311  );
312 
313  // checking if some bytes were not written.
314  if ( (remainder = written_byte_size%sizeof(char_type))!=0)
315  {
316  // copy to the beginning of the stream
317  std::memmove(
318  &(m_output_buffer[0]),
319  &(m_output_buffer[written_byte_size-remainder]),
320  remainder);
321 
322  }
323 
324  m_bzip2_stream.avail_out=static_cast<unsigned int>(m_output_buffer.size()-remainder);
325  m_bzip2_stream.next_out=&(m_output_buffer[remainder]);
326  }
327  } while (m_err == BZ_FINISH_OK);
328 
329  m_ostream.flush();
330 
331  return total_written_byte_size;
332 }
333 
334 // --------------------------------------------------------------------------
335 // Class basic_bz2_ostreambase
336 // --------------------------------------------------------------------------
337 
338 template<
339  typename Elem,
340  typename Tr = std::char_traits<Elem>,
341  typename ElemA = std::allocator<Elem>,
342  typename ByteT = char,
343  typename ByteAT = std::allocator<ByteT>
344 >
345 class basic_bz2_ostreambase : virtual public std::basic_ios<Elem,Tr>
346 {
347 public:
348  typedef std::basic_ostream<Elem, Tr>& ostream_reference;
349  typedef basic_bz2_ostreambuf<
350  Elem,Tr,ElemA,ByteT,ByteAT> bzip2_streambuf_type;
351 
352  basic_bz2_ostreambase(
353  ostream_reference ostream_,
354  size_t block_size_100k_ ,
355  size_t verbosity_ ,
356  size_t work_factor_,
357  size_t buffer_size_
358  )
359  : m_buf(ostream_,block_size_100k_, verbosity_, work_factor_, buffer_size_)
360  {
361  this->init(&m_buf );
362  };
363 
364  bzip2_streambuf_type* rdbuf() { return &m_buf; };
365 
366 private:
367  bzip2_streambuf_type m_buf;
368 };
369 
370 // --------------------------------------------------------------------------
371 // Class basic_bz2_ostream
372 // --------------------------------------------------------------------------
373 
374 template<
375  typename Elem,
376  typename Tr = std::char_traits<Elem>,
377  typename ElemA = std::allocator<Elem>,
378  typename ByteT = char,
379  typename ByteAT = std::allocator<ByteT>
380 >
381 class basic_bz2_ostream :
382  public basic_bz2_ostreambase<Elem,Tr,ElemA,ByteT,ByteAT>,
383  public std::basic_ostream<Elem,Tr>
384 {
385 public:
386  typedef basic_bz2_ostreambase<
387  Elem,Tr,ElemA,ByteT,ByteAT> bzip2_ostreambase_type;
388  typedef std::basic_ostream<Elem,Tr> ostream_type;
389  typedef ostream_type& ostream_reference;
390 
391  basic_bz2_ostream(
392  ostream_reference ostream_,
393  size_t block_size_100k_ = 9,
394  size_t verbosity_ = 0,
395  size_t work_factor_ = 30,
396  size_t buffer_size_ = BZ2_OUTPUT_DEFAULT_BUFFER_SIZE
397  )
398  :
399  bzip2_ostreambase_type(ostream_,block_size_100k_, verbosity_, work_factor_,buffer_size_),
400  ostream_type(bzip2_ostreambase_type::rdbuf())
401  {
402 
403  };
404 
405  basic_bz2_ostream& add_header();
406  basic_bz2_ostream& zflush()
407  {
408  this->flush(); this->rdbuf()->flush(); return *this;
409  };
410 
411 #ifdef _WIN32
412 private:
413  void _Add_vtordisp1() { } // Required to avoid VC++ warning C4250
414  void _Add_vtordisp2() { } // Required to avoid VC++ warning C4250
415 #endif
416 };
417 
418 // --------------------------------------------------------------------------
419 // Typedefs
420 // --------------------------------------------------------------------------
421 
422 typedef basic_bz2_ostream<char> bz2_ostream;
423 typedef basic_bz2_ostream<wchar_t> bz2_wostream;
424 
425 } // 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< Elem, Tr >::epptr
T epptr(T... args)
std::remainder
T remainder(T... args)
std::basic_streambuf
iostream
std::basic_streambuf< Elem, Tr >::sync
T sync(T... args)
std::char_traits
std::streamsize
std::basic_ostream< Elem, Tr >
std::flush
T flush(T... args)
std::basic_ios::init
T init(T... args)
std::min
T min(T... args)
std::basic_streambuf< Elem, Tr >::overflow
T overflow(T... args)
platform.hpp
Provides platform and dependency checks.
std::allocator
std::memmove
T memmove(T... args)
std::basic_ios