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_istream.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 #ifndef SEQAN3_HAS_BZIP2
23 #error "This file cannot be used when building without BZIP2-support."
24 #endif
25 
26 #include <algorithm>
27 #include <cstring>
28 #include <iostream>
29 #include <vector>
30 
31 #define BZ_NO_STDIO
32 #include <bzlib.h>
33 
34 namespace seqan3::contrib
35 {
36 
37 // --------------------------------------------------------------------------
38 // Class basic_bz2_istreambuf
39 // --------------------------------------------------------------------------
40 
41 const size_t BZ2_INPUT_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_istreambuf :
51  public std::basic_streambuf<Elem, Tr>
52 {
53 public:
54  typedef std::basic_istream<Elem, Tr>& istream_reference;
55  typedef ElemA char_allocator_type;
56  typedef ByteT byte_type;
57  typedef ByteAT byte_allocator_type;
58  typedef byte_type* byte_buffer_type;
59  typedef typename Tr::char_type char_type;
60  typedef typename Tr::int_type int_type;
61  typedef std::vector<byte_type, byte_allocator_type > byte_vector_type;
62  typedef std::vector<char_type, char_allocator_type > char_vector_type;
63 
64  basic_bz2_istreambuf(
65  istream_reference istream_,
66  size_t verbosity_,
67  bool small_,
68  size_t read_buffer_size_,
69  size_t input_buffer_size_
70  );
71 
72  ~basic_bz2_istreambuf();
73 
74  int_type underflow();
75 
76  istream_reference get_istream() { return m_istream;};
77  bz_stream& get_bzip2_stream() { return m_bzip2_stream;};
78  int get_zerr() const { return m_err;};
79 private:
80  std::streamsize unbzip2_from_stream( char_type*, std::streamsize);
81  void put_back_from_bzip2_stream();
82  size_t fill_input_buffer();
83 
84  istream_reference m_istream;
85  bz_stream m_bzip2_stream;
86  int m_err;
87  byte_vector_type m_input_buffer;
88  char_vector_type m_buffer;
89 };
90 
91 // --------------------------------------------------------------------------
92 // Class basic_bz2_istreambuf implementation
93 // --------------------------------------------------------------------------
94 
95 template<
96  typename Elem,
97  typename Tr,
98  typename ElemA,
99  typename ByteT,
100  typename ByteAT
101 >
102 basic_bz2_istreambuf<
103  Elem,Tr,ElemA,ByteT,ByteAT
104  >::basic_bz2_istreambuf(
105  istream_reference istream_,
106  size_t verbosity_,
107  bool small_,
108  size_t read_buffer_size_,
109  size_t input_buffer_size_
110 )
111 :
112  m_istream(istream_),
113  m_input_buffer(input_buffer_size_),
114  m_buffer(read_buffer_size_)
115 {
116  // setting zalloc, zfree and opaque
117  m_bzip2_stream.bzalloc=NULL;
118  m_bzip2_stream.bzfree=NULL;
119 
120  m_bzip2_stream.next_in=NULL;
121  m_bzip2_stream.avail_in=0;
122  m_bzip2_stream.avail_out=0;
123  m_bzip2_stream.next_out=NULL;
124 
125 
126  m_err=BZ2_bzDecompressInit (
127  &m_bzip2_stream,
128  std::min(4, static_cast<int>(verbosity_)),
129  static_cast<int>(small_)
130  );
131 
132  this->setg(
133  &(m_buffer[0])+4, // beginning of putback area
134  &(m_buffer[0])+4, // read position
135  &(m_buffer[0])+4); // end position
136 }
137 
138 template<
139  typename Elem,
140  typename Tr,
141  typename ElemA,
142  typename ByteT,
143  typename ByteAT
144 >
145 size_t basic_bz2_istreambuf<
146  Elem,Tr,ElemA,ByteT,ByteAT
147  >::fill_input_buffer()
148 {
149  m_bzip2_stream.next_in=&(m_input_buffer[0]);
150  m_istream.read(
151  (char_type*)(&(m_input_buffer[0])),
152  static_cast<std::streamsize>(m_input_buffer.size()/sizeof(char_type))
153  );
154  return m_bzip2_stream.avail_in=m_istream.gcount()*sizeof(char_type);
155 }
156 
157 template<
158  typename Elem,
159  typename Tr,
160  typename ElemA,
161  typename ByteT,
162  typename ByteAT
163 >
164 void basic_bz2_istreambuf<
165  Elem,Tr,ElemA,ByteT,ByteAT
166  >::put_back_from_bzip2_stream()
167 {
168  if (m_bzip2_stream.avail_in==0)
169  return;
170 
171  m_istream.clear( std::ios::goodbit );
172  m_istream.seekg(
173  -static_cast<int>(m_bzip2_stream.avail_in),
174  std::ios_base::cur
175  );
176 
177  m_bzip2_stream.avail_in=0;
178 }
179 
180 
181 template<
182  typename Elem,
183  typename Tr,
184  typename ElemA,
185  typename ByteT,
186  typename ByteAT
187 >
188 basic_bz2_istreambuf<
189  Elem,Tr,ElemA,ByteT,ByteAT
190  >::~basic_bz2_istreambuf()
191 {
192  BZ2_bzDecompressEnd(&m_bzip2_stream);
193 }
194 
195 template<
196  typename Elem,
197  typename Tr,
198  typename ElemA,
199  typename ByteT,
200  typename ByteAT
201 >
202 typename basic_bz2_istreambuf<
203  Elem,Tr,ElemA,ByteT,ByteAT
204  >::int_type
205  basic_bz2_istreambuf<
206  Elem,Tr,ElemA,ByteT,ByteAT
207  >::underflow()
208 {
209  if ( this->gptr() && ( this->gptr() < this->egptr()))
210  return * reinterpret_cast<unsigned char *>( this->gptr());
211 
212  int n_putback = static_cast<int>(this->gptr() - this->eback());
213  if ( n_putback > 4)
214  n_putback = 4;
215  std::memmove(
216  &(m_buffer[0]) + (4 - n_putback),
217  this->gptr() - n_putback,
218  n_putback*sizeof(char_type)
219  );
220 
221  int num = unbzip2_from_stream(
222  &(m_buffer[0])+4,
223  static_cast<std::streamsize>((m_buffer.size()-4)*sizeof(char_type))
224  );
225  if (num <= 0) // ERROR or EOF
226  return EOF;
227 
228  // reset buffer pointers
229  this->setg(
230  &(m_buffer[0]) + (4 - n_putback), // beginning of putback area
231  &(m_buffer[0]) + 4, // read position
232  &(m_buffer[0]) + 4 + num); // end of buffer
233 
234  // return next character
235  return* reinterpret_cast<unsigned char *>( this->gptr());
236  }
237 
238 
239 template<
240  typename Elem,
241  typename Tr,
242  typename ElemA,
243  typename ByteT,
244  typename ByteAT
245 >
246 std::streamsize basic_bz2_istreambuf<
247  Elem,Tr,ElemA,ByteT,ByteAT
248  >::unbzip2_from_stream(
249  char_type* buffer_,
250  std::streamsize buffer_size_
251  )
252 {
253  m_bzip2_stream.next_out=(byte_buffer_type)buffer_;
254  m_bzip2_stream.avail_out=buffer_size_*sizeof(char_type);
255  size_t count =m_bzip2_stream.avail_in;
256 
257  do
258  {
259  if (m_bzip2_stream.avail_in==0)
260  count=fill_input_buffer();
261 
262  if (m_bzip2_stream.avail_in)
263  {
264  m_err = BZ2_bzDecompress( &m_bzip2_stream );
265  }
266  } while (m_err==BZ_OK && m_bzip2_stream.avail_out != 0 && count != 0);
267 
268  if (m_err == BZ_STREAM_END)
269  put_back_from_bzip2_stream();
270 
271  return buffer_size_ - m_bzip2_stream.avail_out/sizeof(char_type);
272 }
273 
274 // --------------------------------------------------------------------------
275 // Class basic_bz2_istreambase
276 // --------------------------------------------------------------------------
277 
278 template<
279  typename Elem,
280  typename Tr = std::char_traits<Elem>,
281  typename ElemA = std::allocator<Elem>,
282  typename ByteT = char,
283  typename ByteAT = std::allocator<ByteT>
284 >
285 class basic_bz2_istreambase : virtual public std::basic_ios<Elem,Tr>
286 {
287 public:
288  typedef std::basic_istream<Elem, Tr>& istream_reference;
289  typedef basic_bz2_istreambuf<
290  Elem,Tr,ElemA,ByteT,ByteAT> unbzip2_streambuf_type;
291 
292  basic_bz2_istreambase(
293  istream_reference ostream_,
294  size_t verbosity_,
295  bool small_,
296  size_t read_buffer_size_,
297  size_t input_buffer_size_
298  )
299  : m_buf(
300  ostream_,
301  verbosity_,
302  small_,
303  read_buffer_size_,
304  input_buffer_size_
305  )
306  {
307  this->init(&m_buf );
308  };
309 
310  unbzip2_streambuf_type* rdbuf() { return &m_buf; };
311 
312 private:
313  unbzip2_streambuf_type m_buf;
314 };
315 
316 // --------------------------------------------------------------------------
317 // Class basic_bz2_istream
318 // --------------------------------------------------------------------------
319 
320 template<
321  typename Elem,
322  typename Tr = std::char_traits<Elem>,
323  typename ElemA = std::allocator<Elem>,
324  typename ByteT = char,
325  typename ByteAT = std::allocator<ByteT>
326 >
327 class basic_bz2_istream :
328  public basic_bz2_istreambase<Elem,Tr,ElemA,ByteT,ByteAT>,
329  public std::basic_istream<Elem,Tr>
330 {
331 public:
332  typedef basic_bz2_istreambase<
333  Elem,Tr,ElemA,ByteT,ByteAT> bzip2_istreambase_type;
334  typedef std::basic_istream<Elem,Tr> istream_type;
335  typedef istream_type& istream_reference;
336  typedef unsigned char byte_type;
337 
338  basic_bz2_istream(
339  istream_reference istream_,
340  size_t verbosity_ = 0,
341  bool small_ = false,
342  size_t read_buffer_size_ = BZ2_INPUT_DEFAULT_BUFFER_SIZE,
343  size_t input_buffer_size_ = BZ2_INPUT_DEFAULT_BUFFER_SIZE
344  )
345  :
346  bzip2_istreambase_type(istream_,verbosity_, small_, read_buffer_size_, input_buffer_size_),
347  istream_type(bzip2_istreambase_type::rdbuf())
348  {};
349 #ifdef _WIN32
350 private:
351  void _Add_vtordisp1() { } // Required to avoid VC++ warning C4250
352  void _Add_vtordisp2() { } // Required to avoid VC++ warning C4250
353 #endif
354 };
355 
356 // --------------------------------------------------------------------------
357 // typedefs
358 // --------------------------------------------------------------------------
359 
360 typedef basic_bz2_istream<char> bz2_istream;
361 typedef basic_bz2_istream<wchar_t> bz2_wistream;
362 
363 } // 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
iostream
std::basic_streambuf< Elem, std::char_traits< Elem > >::underflow
T underflow(T... args)
std::char_traits
std::streamsize
std::basic_ios::init
T init(T... args)
std::min
T min(T... args)
std::allocator
std::memmove
T memmove(T... args)
std::basic_istream
seqan3::pack_traits::count
constexpr ptrdiff_t count
Count the occurrences of a type in a pack.
Definition: traits.hpp:134
std::basic_ios