SeqAn3 3.4.0-rc.1
The Modern C++ library for sequence analysis.
Loading...
Searching...
No Matches
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 <cstdint>
24#include <cstring>
25#include <iostream>
26#include <vector>
27
28#if !defined(SEQAN3_HAS_BZIP2) && !defined(SEQAN3_HEADER_TEST)
29#error "This file cannot be used when building without BZIP2-support."
30#endif // !defined(SEQAN3_HAS_BZIP2) && !defined(SEQAN3_HEADER_TEST)
31
32#if defined(SEQAN3_HAS_BZIP2)
33
34#define BZ_NO_STDIO
35#include <bzlib.h>
36
37namespace seqan3::contrib
38{
39
40// --------------------------------------------------------------------------
41// Class basic_bz2_ostreambuf
42// --------------------------------------------------------------------------
43
44const size_t BZ2_OUTPUT_DEFAULT_BUFFER_SIZE = 4096;
45
46template<
47 typename Elem,
48 typename Tr = std::char_traits<Elem>,
49 typename ElemA = std::allocator<Elem>,
50 typename ByteT = char,
51 typename ByteAT = std::allocator<ByteT>
52>
53class basic_bz2_ostreambuf :
54 public std::basic_streambuf<Elem, Tr>
55{
56public:
57 typedef std::basic_streambuf< Elem, Tr > basic_streambuf_type;
58 typedef std::basic_ostream<Elem, Tr>& ostream_reference;
59 typedef ElemA char_allocator_type;
60 typedef ByteT byte_type;
61 typedef ByteAT byte_allocator_type;
62 typedef byte_type* byte_buffer_type;
63 typedef typename Tr::char_type char_type;
64 typedef typename Tr::int_type int_type;
65 typedef std::vector<byte_type, byte_allocator_type > byte_vector_type;
66 typedef std::vector<char_type, char_allocator_type > char_vector_type;
67
68 using basic_streambuf_type::epptr;
69 using basic_streambuf_type::pbase;
70 using basic_streambuf_type::pptr;
71
72 basic_bz2_ostreambuf(
73 ostream_reference ostream_,
74 size_t block_size_100k_ ,
75 size_t verbosity_ ,
76 size_t work_factor_,
77 size_t buffer_size_
78 );
79
80 ~basic_bz2_ostreambuf();
81
82 int sync ();
83 int_type overflow (int_type c);
84
85 std::streamsize flush(int flush_mode);
86 int get_zerr() const
87 { return m_err;};
88 uint64_t get_in_size() const
89 {
90 return ((uint64_t)m_bzip2_stream.total_in_hi32 << 32)
91 + m_bzip2_stream.total_in_lo32;
92 }
93 uint64_t get_out_size() const
94 {
95 return ((uint64_t)m_bzip2_stream.total_out_hi32 << 32)
96 + m_bzip2_stream.total_out_lo32;
97 }
98private:
99 bool bzip2_to_stream( char_type*, std::streamsize);
100 size_t fill_input_buffer();
101
102 ostream_reference m_ostream;
103 bz_stream m_bzip2_stream;
104 int m_err;
105 byte_vector_type m_output_buffer;
106 char_vector_type m_buffer;
107};
108
109// --------------------------------------------------------------------------
110// Class basic_bz2_ostreambuf implementation
111// --------------------------------------------------------------------------
112
113template<
114 typename Elem,
115 typename Tr,
116 typename ElemA,
117 typename ByteT,
118 typename ByteAT
119>
120basic_bz2_ostreambuf<
121 Elem,Tr,ElemA,ByteT,ByteAT
122 >:: basic_bz2_ostreambuf(
123 ostream_reference ostream_,
124 size_t block_size_100k_,
125 size_t verbosity_,
126 size_t work_factor_,
127 size_t buffer_size_
128 )
129:
130 m_ostream(ostream_),
131 m_output_buffer(buffer_size_,0),
132 m_buffer(buffer_size_,0)
133{
134 m_bzip2_stream.bzalloc=NULL;
135 m_bzip2_stream.bzfree=NULL;
136
137 m_bzip2_stream.next_in=NULL;
138 m_bzip2_stream.avail_in=0;
139 m_bzip2_stream.avail_out=0;
140 m_bzip2_stream.next_out=NULL;
141
142 m_err=BZ2_bzCompressInit(
143 &m_bzip2_stream,
144 std::min( 9, static_cast<int>(block_size_100k_) ),
145 std::min( 4, static_cast<int>(verbosity_) ),
146 std::min( 250, static_cast<int>(work_factor_) )
147 );
148
149 this->setp( &(m_buffer[0]), &(m_buffer[m_buffer.size()-1]));
150}
151
152template<
153 typename Elem,
154 typename Tr,
155 typename ElemA,
156 typename ByteT,
157 typename ByteAT
158>
159basic_bz2_ostreambuf<
160 Elem,Tr,ElemA,ByteT,ByteAT
161 >::~basic_bz2_ostreambuf()
162{
163 flush(BZ_FINISH);
164 m_ostream.flush();
165 m_err=BZ2_bzCompressEnd(&m_bzip2_stream);
166}
167
168template<
169 typename Elem,
170 typename Tr,
171 typename ElemA,
172 typename ByteT,
173 typename ByteAT
174>
175int basic_bz2_ostreambuf<
176 Elem,Tr,ElemA,ByteT,ByteAT
177 >::sync ()
178{
179 if ( this->pptr() && this->pptr() > this->pbase())
180 {
181 int c = overflow( EOF);
182
183 if ( c == EOF)
184 return -1;
185 }
186
187 return 0;
188}
189
190template<
191 typename Elem,
192 typename Tr,
193 typename ElemA,
194 typename ByteT,
195 typename ByteAT
196>
197typename basic_bz2_ostreambuf<
198 Elem,Tr,ElemA,ByteT,ByteAT
199 >::int_type
200 basic_bz2_ostreambuf<
201 Elem,Tr,ElemA,ByteT,ByteAT
202 >::overflow (
203 typename basic_bz2_ostreambuf<
204 Elem,Tr,ElemA,ByteT,ByteAT
205 >::int_type c
206 )
207{
208 int w = static_cast<int>(this->pptr() - this->pbase());
209 if (c != EOF) {
210 *this->pptr() = c;
211 ++w;
212 }
213 if ( bzip2_to_stream( this->pbase(), w)) {
214 this->setp( this->pbase(), this->epptr());
215 return c;
216 } else
217 return EOF;
218}
219
220template<
221 typename Elem,
222 typename Tr,
223 typename ElemA,
224 typename ByteT,
225 typename ByteAT
226>
227bool basic_bz2_ostreambuf<
228 Elem,Tr,ElemA,ByteT,ByteAT
229 >::bzip2_to_stream(
230 typename basic_bz2_ostreambuf<
231 Elem,Tr,ElemA,ByteT,ByteAT
232 >::char_type* buffer_,
233 std::streamsize buffer_size_
234 )
235{
236 std::streamsize written_byte_size=0;
237
238 m_bzip2_stream.next_in=(byte_buffer_type)buffer_;
239 m_bzip2_stream.avail_in=buffer_size_*sizeof(char_type);
240 m_bzip2_stream.avail_out=static_cast<unsigned int>(m_output_buffer.size());
241 m_bzip2_stream.next_out=&(m_output_buffer[0]);
242 size_t remainder=0;
243
244 do
245 {
246 m_err = BZ2_bzCompress (&m_bzip2_stream, BZ_RUN );
247
248 if (m_err == BZ_RUN_OK || m_err == BZ_STREAM_END)
249 {
250 written_byte_size= static_cast<std::streamsize>(m_output_buffer.size()) - m_bzip2_stream.avail_out;
251 // output 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
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
277template<
278 typename Elem,
279 typename Tr,
280 typename ElemA,
281 typename ByteT,
282 typename ByteAT
283>
284std::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 // output 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
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
338template<
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>
345class basic_bz2_ostreambase : virtual public std::basic_ios<Elem,Tr>
346{
347public:
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
366private:
367 bzip2_streambuf_type m_buf;
368};
369
370// --------------------------------------------------------------------------
371// Class basic_bz2_ostream
372// --------------------------------------------------------------------------
373
374template<
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>
381class basic_bz2_ostream :
382 public basic_bz2_ostreambase<Elem,Tr,ElemA,ByteT,ByteAT>,
383 public std::basic_ostream<Elem,Tr>
384{
385public:
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
412private:
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
422typedef basic_bz2_ostream<char> bz2_ostream;
423typedef basic_bz2_ostream<wchar_t> bz2_wostream;
424
425} // namespace seqan3::contrib
426
427#endif // defined(SEQAN3_HAS_BZIP2)
T flush(T... args)
T init(T... args)
T memmove(T... args)
T min(T... args)
T rdbuf(T... args)
T remainder(T... args)