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