OTest2
A C++ testing framework
bzip2istream.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2020 Ondrej Starek
3  *
4  * This file is part of OTest2.
5  *
6  * OTest2 is free software: you can redistribute it and/or modify it under
7  * the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License,
9  * or (at your option) any later version.
10  *
11  * OTest2 is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14  * License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with OTest2. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <bzip2istream.h>
21 
22 #include <assert.h>
23 #include <bzlib.h>
24 #include <cstring>
25 #include <streambuf>
26 
27 #include <utils.h>
28 
29 namespace OTest2 {
30 
31 class Bzip2IStream::Buffer : public std::streambuf {
32  private:
33  std::istream* decorated;
34 
35  enum { BUFFER_SIZE = 5000 };
36  char ibuffer[BUFFER_SIZE];
37  char obuffer[BUFFER_SIZE];
38  bz_stream bzip_stream;
39  bool eof;
40 
41  public:
42  /* -- avoid copying */
43  Buffer(
44  const Buffer&) = delete;
46  const Buffer&) = delete;
47 
48  explicit Buffer(
49  std::istream* decorated_);
50  virtual ~Buffer();
51 
52  private:
53  virtual int underflow() override;
54 };
55 
57  std::istream* decorated_) :
58  decorated(decorated_),
59  eof(false) {
60  assert(decorated != nullptr);
61 
62  /* -- initialize the bzip context */
63  std::memset(&bzip_stream, 0, sizeof(bzip_stream));
64  auto info_(BZ2_bzDecompressInit(&bzip_stream, 0, 0 /* -- no reducing of memory */));
65  assert(info_ == BZ_OK);
66 
67  /* -- there are no decompressed data yet, don't set the stream buffer pointers */
68 }
69 
71  BZ2_bzDecompressEnd(&bzip_stream);
72 }
73 
74 int Bzip2IStream::Buffer::underflow() {
75  /* -- the end of the stream has been already reached */
76  if(eof)
77  return traits_type::eof();
78 
79  /* -- prepare buffer for decompressed data */
80  bzip_stream.next_out = obuffer;
81  bzip_stream.avail_out = BUFFER_SIZE;
82 
83  int info_;
84  do {
85  /* -- move remaining input data at the beginning of the input buffer */
86  std::memmove(ibuffer, bzip_stream.next_in, bzip_stream.avail_in);
87 
88  /* -- read next data from the decorated stream */
89  decorated->read(ibuffer, BUFFER_SIZE - bzip_stream.avail_in);
90  auto read_bytes_(decorated->gcount());
91  if(read_bytes_ <= 0 && bzip_stream.avail_in == 0) {
92  eof = true;
93  return traits_type::eof();
94  }
95 
96  /* -- decompress data */
97  bzip_stream.next_in = ibuffer;
98  bzip_stream.avail_in += read_bytes_;
99  info_ = BZ2_bzDecompress(&bzip_stream);
100  assert(info_ == BZ_OK || info_ == BZ_STREAM_END);
101  }
102  while(info_ != BZ_STREAM_END && bzip_stream.next_out == obuffer);
103 
104  /* -- the stream is finished (the bzlib library detected the end of the
105  * compressed sequence. */
106  if(info_ == BZ_STREAM_END) {
107  eof = true;
108 
109  /* -- no output data are valid only at the end of the sequence */
110  if(obuffer == bzip_stream.next_out)
111  return traits_type::eof();
112  }
113  assert(obuffer != bzip_stream.next_out);
114 
115  /* -- set the stream buffer pointers */
116  setg(obuffer, obuffer, bzip_stream.next_out);
117 
118  return traits_type::to_int_type(*obuffer);
119 }
120 
122  std::istream* decorated_) :
123  buffer(new Buffer(decorated_)) {
124  rdbuf(buffer);
125 }
126 
128  odelete(buffer);
129 }
130 
131 } /* -- namespace OTest2 */
OTest2::Bzip2IStream::~Bzip2IStream
virtual ~Bzip2IStream()
Dtor.
Definition: bzip2istream.cpp:127
OTest2::Bzip2IStream::Buffer::~Buffer
virtual ~Buffer()
Definition: bzip2istream.cpp:70
utils.h
OTest2::Bzip2IStream::Buffer
Definition: bzip2istream.cpp:31
OTest2::Bzip2IStream::Buffer::Buffer
Buffer(const Buffer &)=delete
OTest2
Definition: assertbean.h:25
OTest2::Bzip2IStream::Buffer::operator=
Buffer & operator=(const Buffer &)=delete
OTest2::Bzip2IStream::Bzip2IStream
Bzip2IStream(std::istream *decorated_)
Ctor.
Definition: bzip2istream.cpp:121
bzip2istream.h
OTest2::odelete
void odelete(T_ *&object_)
Delete a pointer and set it invalid.
Definition: utils.h:34