Libosmium  2.1.0
Fast and flexible C++ library for working with OpenStreetMap data
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
bzip2_compression.hpp
Go to the documentation of this file.
1 #ifndef OSMIUM_IO_BZIP2_COMPRESSION_HPP
2 #define OSMIUM_IO_BZIP2_COMPRESSION_HPP
3 
4 /*
5 
6 This file is part of Osmium (http://osmcode.org/libosmium).
7 
8 Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
9 
10 Boost Software License - Version 1.0 - August 17th, 2003
11 
12 Permission is hereby granted, free of charge, to any person or organization
13 obtaining a copy of the software and accompanying documentation covered by
14 this license (the "Software") to use, reproduce, display, distribute,
15 execute, and transmit the Software, and to prepare derivative works of the
16 Software, and to permit third-parties to whom the Software is furnished to
17 do so, all subject to the following:
18 
19 The copyright notices in the Software and this entire statement, including
20 the above license grant, this restriction and the following disclaimer,
21 must be included in all copies of the Software, in whole or in part, and
22 all derivative works of the Software, unless such copies or derivative
23 works are solely in the form of machine-executable object code generated by
24 a source language processor.
25 
26 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
29 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
30 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
31 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
32 DEALINGS IN THE SOFTWARE.
33 
34 */
35 
45 #include <cerrno>
46 #include <cstddef>
47 #include <cstdio>
48 #include <stdexcept>
49 #include <string>
50 
51 #include <bzlib.h>
52 
53 #ifndef _MSC_VER
54 # include <unistd.h>
55 #endif
56 
59 #include <osmium/util/cast.hpp>
61 
62 namespace osmium {
63 
68  struct bzip2_error : public std::runtime_error {
69 
72 
73  bzip2_error(const std::string& what, int error_code) :
74  std::runtime_error(what),
75  bzip2_error_code(error_code),
76  system_errno(error_code == BZ_IO_ERROR ? errno : 0) {
77  }
78 
79  }; // struct bzip2_error
80 
81  namespace io {
82 
83  namespace detail {
84 
85  OSMIUM_NORETURN inline void throw_bzip2_error(BZFILE* bzfile, const char* msg, int bzlib_error=0) {
86  std::string error("bzip2 error: ");
87  error += msg;
88  error += ": ";
89  int errnum = bzlib_error;
90  if (bzlib_error) {
91  error += std::to_string(bzlib_error);
92  } else {
93  error += ::BZ2_bzerror(bzfile, &errnum);
94  }
95  throw osmium::bzip2_error(error, errnum);
96  }
97 
98  } // namespace detail
99 
100  class Bzip2Compressor : public Compressor {
101 
102  FILE* m_file;
104  BZFILE* m_bzfile;
105 
106  public:
107 
108  explicit Bzip2Compressor(int fd) :
109  Compressor(),
110  m_file(fdopen(dup(fd), "wb")),
111  m_bzerror(BZ_OK),
112  m_bzfile(::BZ2_bzWriteOpen(&m_bzerror, m_file, 6, 0, 0)) {
113  if (!m_bzfile) {
114  detail::throw_bzip2_error(m_bzfile, "write open failed", m_bzerror);
115  }
116  }
117 
118  ~Bzip2Compressor() override final {
119  close();
120  }
121 
122  void write(const std::string& data) override final {
123  int error;
124  ::BZ2_bzWrite(&error, m_bzfile, const_cast<char*>(data.data()), static_cast_with_assert<int>(data.size()));
125  if (error != BZ_OK && error != BZ_STREAM_END) {
126  detail::throw_bzip2_error(m_bzfile, "write failed", error);
127  }
128  }
129 
130  void close() override final {
131  if (m_bzfile) {
132  int error;
133  ::BZ2_bzWriteClose(&error, m_bzfile, 0, nullptr, nullptr);
134  m_bzfile = nullptr;
135  if (m_file) {
136  fclose(m_file);
137  }
138  if (error != BZ_OK) {
139  detail::throw_bzip2_error(m_bzfile, "write close failed", error);
140  }
141  }
142  }
143 
144  }; // class Bzip2Compressor
145 
147 
148  FILE* m_file;
150  BZFILE* m_bzfile;
151  bool m_stream_end {false};
152 
153  public:
154 
156  Decompressor(),
157  m_file(fdopen(dup(fd), "rb")),
158  m_bzerror(BZ_OK),
159  m_bzfile(::BZ2_bzReadOpen(&m_bzerror, m_file, 0, 0, nullptr, 0)) {
160  if (!m_bzfile) {
161  detail::throw_bzip2_error(m_bzfile, "read open failed", m_bzerror);
162  }
163  }
164 
165  ~Bzip2Decompressor() override final {
166  close();
167  }
168 
169  std::string read() override final {
170  std::string buffer;
171 
172  if (!m_stream_end) {
174  int error;
175  int nread = ::BZ2_bzRead(&error, m_bzfile, const_cast<char*>(buffer.data()), static_cast_with_assert<int>(buffer.size()));
176  if (error != BZ_OK && error != BZ_STREAM_END) {
177  detail::throw_bzip2_error(m_bzfile, "read failed", error);
178  }
179  if (error == BZ_STREAM_END) {
180  void* unused;
181  int nunused;
182  if (! feof(m_file)) {
183  ::BZ2_bzReadGetUnused(&error, m_bzfile, &unused, &nunused);
184  if (error != BZ_OK) {
185  detail::throw_bzip2_error(m_bzfile, "get unused failed", error);
186  }
187  std::string unused_data(static_cast<const char*>(unused), static_cast<std::string::size_type>(nunused));
188  ::BZ2_bzReadClose(&error, m_bzfile);
189  if (error != BZ_OK) {
190  detail::throw_bzip2_error(m_bzfile, "read close failed", error);
191  }
192  m_bzfile = ::BZ2_bzReadOpen(&error, m_file, 0, 0, const_cast<void*>(static_cast<const void*>(unused_data.data())), static_cast_with_assert<int>(unused_data.size()));
193  if (error != BZ_OK) {
194  detail::throw_bzip2_error(m_bzfile, "read open failed", error);
195  }
196  } else {
197  m_stream_end = true;
198  }
199  }
200  buffer.resize(static_cast<std::string::size_type>(nread));
201  }
202 
203  return buffer;
204  }
205 
206  void close() override final {
207  if (m_bzfile) {
208  int error;
209  ::BZ2_bzReadClose(&error, m_bzfile);
210  m_bzfile = nullptr;
211  if (m_file) {
212  fclose(m_file);
213  }
214  if (error != BZ_OK) {
215  detail::throw_bzip2_error(m_bzfile, "read close failed", error);
216  }
217  }
218  }
219 
220  }; // class Bzip2Decompressor
221 
223 
224  const char* m_buffer;
226  bz_stream m_bzstream;
227 
228  public:
229 
230  Bzip2BufferDecompressor(const char* buffer, size_t size) :
231  m_buffer(buffer),
232  m_buffer_size(size),
233  m_bzstream() {
234  m_bzstream.next_in = const_cast<char*>(buffer);
235  m_bzstream.avail_in = static_cast_with_assert<unsigned int>(size);
236  int result = BZ2_bzDecompressInit(&m_bzstream, 0, 0);
237  if (result != BZ_OK) {
238  std::string message("bzip2 error: decompression init failed: ");
239  throw bzip2_error(message, result);
240  }
241  }
242 
243  ~Bzip2BufferDecompressor() override final {
244  BZ2_bzDecompressEnd(&m_bzstream);
245  }
246 
247  std::string read() override final {
248  std::string output;
249 
250  if (m_buffer) {
251  const size_t buffer_size = 10240;
252  output.resize(buffer_size);
253  m_bzstream.next_out = const_cast<char*>(output.data());
254  m_bzstream.avail_out = buffer_size;
255  int result = BZ2_bzDecompress(&m_bzstream);
256 
257  if (result != BZ_OK) {
258  m_buffer = nullptr;
259  m_buffer_size = 0;
260  }
261 
262  if (result != BZ_OK && result != BZ_STREAM_END) {
263  std::string message("bzip2 error: decompress failed: ");
264  throw bzip2_error(message, result);
265  }
266 
267  output.resize(static_cast<unsigned long>(m_bzstream.next_out - output.data()));
268  }
269 
270  return output;
271  }
272 
273  }; // class Bzip2BufferDecompressor
274 
275  namespace {
276 
278  [](int fd) { return new osmium::io::Bzip2Compressor(fd); },
279  [](int fd) { return new osmium::io::Bzip2Decompressor(fd); },
280  [](const char* buffer, size_t size) { return new osmium::io::Bzip2BufferDecompressor(buffer, size); }
281  );
282 
283  } // anonymous namespace
284 
285  } // namespace io
286 
287 } // namespace osmium
288 
289 #endif // OSMIUM_IO_BZIP2_COMPRESSION_HPP
bz_stream m_bzstream
Definition: bzip2_compression.hpp:226
Definition: bzip2_compression.hpp:146
Bzip2Compressor(int fd)
Definition: bzip2_compression.hpp:108
int bzip2_error_code
Definition: bzip2_compression.hpp:70
#define OSMIUM_NORETURN
Definition: compatibility.hpp:44
int m_bzerror
Definition: bzip2_compression.hpp:149
const char * m_buffer
Definition: bzip2_compression.hpp:224
int m_bzerror
Definition: bzip2_compression.hpp:103
size_t m_buffer_size
Definition: bzip2_compression.hpp:225
bool m_stream_end
Definition: bzip2_compression.hpp:151
static CompressionFactory & instance()
Definition: compression.hpp:136
static constexpr unsigned int input_buffer_size
Definition: compression.hpp:78
Definition: reader_iterator.hpp:39
bzip2_error(const std::string &what, int error_code)
Definition: bzip2_compression.hpp:73
Definition: bzip2_compression.hpp:100
int system_errno
Definition: bzip2_compression.hpp:71
Definition: compression.hpp:74
void close() overridefinal
Definition: bzip2_compression.hpp:206
FILE * m_file
Definition: bzip2_compression.hpp:102
Definition: bzip2_compression.hpp:222
Namespace for everything in the Osmium library.
Definition: assembler.hpp:55
Bzip2BufferDecompressor(const char *buffer, size_t size)
Definition: bzip2_compression.hpp:230
~Bzip2Decompressor() overridefinal
Definition: bzip2_compression.hpp:165
BZFILE * m_bzfile
Definition: bzip2_compression.hpp:150
BZFILE * m_bzfile
Definition: bzip2_compression.hpp:104
std::string read() overridefinal
Definition: bzip2_compression.hpp:169
~Bzip2BufferDecompressor() overridefinal
Definition: bzip2_compression.hpp:243
void close() overridefinal
Definition: bzip2_compression.hpp:130
Definition: compression.hpp:59
FILE * m_file
Definition: bzip2_compression.hpp:148
bool register_compression(osmium::io::file_compression compression, create_compressor_type create_compressor, create_decompressor_type_fd create_decompressor_fd, create_decompressor_type_buffer create_decompressor_buffer)
Definition: compression.hpp:141
std::string read() overridefinal
Definition: bzip2_compression.hpp:247
Bzip2Decompressor(int fd)
Definition: bzip2_compression.hpp:155
~Bzip2Compressor() overridefinal
Definition: bzip2_compression.hpp:118
Definition: bzip2_compression.hpp:68
void write(const std::string &data) overridefinal
Definition: bzip2_compression.hpp:122