Libosmium  2.4.1
Fast and flexible C++ library for working with OpenStreetMap data
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
gzip_compression.hpp
Go to the documentation of this file.
1 #ifndef OSMIUM_IO_GZIP_COMPRESSION_HPP
2 #define OSMIUM_IO_GZIP_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 <stdexcept>
46 #include <string>
47 
48 #include <errno.h>
49 #include <zlib.h>
50 
53 #include <osmium/util/cast.hpp>
55 
56 namespace osmium {
57 
62  struct gzip_error : public std::runtime_error {
63 
66 
67  gzip_error(const std::string& what, int error_code) :
68  std::runtime_error(what),
69  gzip_error_code(error_code),
70  system_errno(error_code == Z_ERRNO ? errno : 0) {
71  }
72 
73  }; // struct gzip_error
74 
75  namespace io {
76 
77  namespace detail {
78 
79  OSMIUM_NORETURN inline void throw_gzip_error(gzFile gzfile, const char* msg, int zlib_error = 0) {
80  std::string error("gzip error: ");
81  error += msg;
82  error += ": ";
83  int errnum = zlib_error;
84  if (zlib_error) {
85  error += std::to_string(zlib_error);
86  } else {
87  error += ::gzerror(gzfile, &errnum);
88  }
89  throw osmium::gzip_error(error, errnum);
90  }
91 
92  } // namespace detail
93 
94  class GzipCompressor : public Compressor {
95 
96  gzFile m_gzfile;
97 
98  public:
99 
100  explicit GzipCompressor(int fd) :
101  Compressor(),
102  m_gzfile(::gzdopen(fd, "w")) {
103  if (!m_gzfile) {
104  detail::throw_gzip_error(m_gzfile, "write initialization failed");
105  }
106  }
107 
108  ~GzipCompressor() override final {
109  close();
110  }
111 
112  void write(const std::string& data) override final {
113  if (!data.empty()) {
114  int nwrite = ::gzwrite(m_gzfile, data.data(), static_cast_with_assert<unsigned int>(data.size()));
115  if (nwrite == 0) {
116  detail::throw_gzip_error(m_gzfile, "write failed");
117  }
118  }
119  }
120 
121  void close() override final {
122  if (m_gzfile) {
123  int result = ::gzclose(m_gzfile);
124  m_gzfile = nullptr;
125  if (result != Z_OK) {
126  detail::throw_gzip_error(m_gzfile, "write close failed", result);
127  }
128  }
129  }
130 
131  }; // class GzipCompressor
132 
134 
135  gzFile m_gzfile;
136 
137  public:
138 
139  explicit GzipDecompressor(int fd) :
140  Decompressor(),
141  m_gzfile(::gzdopen(fd, "r")) {
142  if (!m_gzfile) {
143  detail::throw_gzip_error(m_gzfile, "read initialization failed");
144  }
145  }
146 
147  ~GzipDecompressor() override final {
148  close();
149  }
150 
151  std::string read() override final {
152  std::string buffer(osmium::io::Decompressor::input_buffer_size, '\0');
153  int nread = ::gzread(m_gzfile, const_cast<char*>(buffer.data()), static_cast_with_assert<unsigned int>(buffer.size()));
154  if (nread < 0) {
155  detail::throw_gzip_error(m_gzfile, "read failed");
156  }
157  buffer.resize(static_cast<std::string::size_type>(nread));
158  return buffer;
159  }
160 
161  void close() override final {
162  if (m_gzfile) {
163  int result = ::gzclose(m_gzfile);
164  m_gzfile = nullptr;
165  if (result != Z_OK) {
166  detail::throw_gzip_error(m_gzfile, "read close failed", result);
167  }
168  }
169  }
170 
171  }; // class GzipDecompressor
172 
174 
175  const char* m_buffer;
177  z_stream m_zstream;
178 
179  public:
180 
181  GzipBufferDecompressor(const char* buffer, size_t size) :
182  m_buffer(buffer),
183  m_buffer_size(size),
184  m_zstream() {
185  m_zstream.next_in = reinterpret_cast<unsigned char*>(const_cast<char*>(buffer));
186  m_zstream.avail_in = static_cast_with_assert<unsigned int>(size);
187  int result = inflateInit2(&m_zstream, MAX_WBITS | 32);
188  if (result != Z_OK) {
189  std::string message("gzip error: decompression init failed: ");
190  if (m_zstream.msg) {
191  message.append(m_zstream.msg);
192  }
193  throw osmium::gzip_error(message, result);
194  }
195  }
196 
197  ~GzipBufferDecompressor() override final {
198  inflateEnd(&m_zstream);
199  }
200 
201  std::string read() override final {
202  std::string output;
203 
204  if (m_buffer) {
205  const size_t buffer_size = 10240;
206  output.append(buffer_size, '\0');
207  m_zstream.next_out = reinterpret_cast<unsigned char*>(const_cast<char*>(output.data()));
208  m_zstream.avail_out = buffer_size;
209  int result = inflate(&m_zstream, Z_SYNC_FLUSH);
210 
211  if (result != Z_OK) {
212  m_buffer = nullptr;
213  m_buffer_size = 0;
214  }
215 
216  if (result != Z_OK && result != Z_STREAM_END) {
217  std::string message("gzip error: inflate failed: ");
218  if (m_zstream.msg) {
219  message.append(m_zstream.msg);
220  }
221  throw osmium::gzip_error(message, result);
222  }
223 
224  output.resize(static_cast<unsigned long>(m_zstream.next_out - reinterpret_cast<const unsigned char*>(output.data())));
225  }
226 
227  return output;
228  }
229 
230  }; // class GzipBufferDecompressor
231 
232  namespace {
233 
234 // we want the register_compression() function to run, setting the variable
235 // is only a side-effect, it will never be used
236 #pragma GCC diagnostic push
237 #pragma GCC diagnostic ignored "-Wunused-variable"
239  [](int fd) { return new osmium::io::GzipCompressor(fd); },
240  [](int fd) { return new osmium::io::GzipDecompressor(fd); },
241  [](const char* buffer, size_t size) { return new osmium::io::GzipBufferDecompressor(buffer, size); }
242  );
243 #pragma GCC diagnostic pop
244 
245  } // anonymous namespace
246 
247  } // namespace io
248 
249 } // namespace osmium
250 
251 #endif // OSMIUM_IO_GZIP_COMPRESSION_HPP
gzFile m_gzfile
Definition: gzip_compression.hpp:96
Definition: gzip_compression.hpp:173
gzip_error(const std::string &what, int error_code)
Definition: gzip_compression.hpp:67
gzFile m_gzfile
Definition: gzip_compression.hpp:135
#define OSMIUM_NORETURN
Definition: compatibility.hpp:44
Definition: gzip_compression.hpp:94
z_stream m_zstream
Definition: gzip_compression.hpp:177
static CompressionFactory & instance()
Definition: compression.hpp:136
~GzipBufferDecompressor() overridefinal
Definition: gzip_compression.hpp:197
static constexpr unsigned int input_buffer_size
Definition: compression.hpp:78
std::string read() overridefinal
Definition: gzip_compression.hpp:151
Definition: reader_iterator.hpp:39
void close() overridefinal
Definition: gzip_compression.hpp:121
size_t m_buffer_size
Definition: gzip_compression.hpp:176
Definition: gzip_compression.hpp:133
Definition: compression.hpp:74
GzipBufferDecompressor(const char *buffer, size_t size)
Definition: gzip_compression.hpp:181
Namespace for everything in the Osmium library.
Definition: assembler.hpp:55
~GzipCompressor() overridefinal
Definition: gzip_compression.hpp:108
const char * m_buffer
Definition: gzip_compression.hpp:175
void close() overridefinal
Definition: gzip_compression.hpp:161
int system_errno
Definition: gzip_compression.hpp:65
Definition: gzip_compression.hpp:62
~GzipDecompressor() overridefinal
Definition: gzip_compression.hpp:147
int gzip_error_code
Definition: gzip_compression.hpp:64
GzipDecompressor(int fd)
Definition: gzip_compression.hpp:139
Definition: compression.hpp:59
void write(const std::string &data) overridefinal
Definition: gzip_compression.hpp:112
std::string read() overridefinal
Definition: gzip_compression.hpp:201
GzipCompressor(int fd)
Definition: gzip_compression.hpp:100
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