Compression (#147)
* enable header detection in util::decompress and also use it for gziped data * expose zlib windowBits so mbgl::util::compress can be used for different formats * also expose windowBits in decompress function for consistency
This commit is contained in:
@@ -5,8 +5,10 @@
|
||||
namespace mbgl {
|
||||
namespace util {
|
||||
|
||||
std::string compress(const std::string& raw);
|
||||
std::string decompress(const std::string& raw);
|
||||
enum CompressionFormat { ZLIB = 15, GZIP = 15 + 16, DEFLATE = -15, DETECT = 15 + 32 };
|
||||
|
||||
std::string compress(const std::string& raw, int windowBits = CompressionFormat::ZLIB);
|
||||
std::string decompress(const std::string& raw, int windowBits = CompressionFormat::DETECT);
|
||||
|
||||
} // namespace util
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <mbgl/util/thread.hpp>
|
||||
#include <mbgl/util/url.hpp>
|
||||
#include <mbgl/util/chrono.hpp>
|
||||
#include <mbgl/util/compression.hpp>
|
||||
|
||||
#include <mbgl/storage/sqlite3.hpp>
|
||||
|
||||
@@ -75,47 +76,6 @@ public:
|
||||
return (((uint8_t) v[0]) == 0x1f) && (((uint8_t) v[1]) == 0x8b);
|
||||
}
|
||||
|
||||
// Some Mbtiles store GZIP-ed tile data, this function is used for decompression
|
||||
std::string decompress_string(const std::string &data) {
|
||||
|
||||
constexpr uint32_t OUT_SIZE = 8192;
|
||||
|
||||
int ret;
|
||||
char outbuffer[OUT_SIZE];
|
||||
std::string outstring;
|
||||
|
||||
z_stream zs{};
|
||||
|
||||
// Init inflate to gzip mode
|
||||
if (inflateInit2(&zs, (16 + MAX_WBITS)) != Z_OK)
|
||||
return "";
|
||||
|
||||
zs.next_in = (Bytef *) data.data();
|
||||
zs.avail_in = (unsigned int) data.size();
|
||||
|
||||
|
||||
// get the decompressed bytes blockwise using repeated calls to inflate
|
||||
do {
|
||||
zs.next_out = reinterpret_cast<Bytef *>(outbuffer);
|
||||
zs.avail_out = OUT_SIZE;
|
||||
|
||||
ret = inflate(&zs, 0);
|
||||
|
||||
if (outstring.size() < zs.total_out) {
|
||||
outstring.append(outbuffer, zs.total_out - outstring.size());
|
||||
}
|
||||
|
||||
} while (ret == Z_OK);
|
||||
|
||||
inflateEnd(&zs);
|
||||
|
||||
if (ret != Z_STREAM_END) { // an error occurred that was not EOF
|
||||
return "";
|
||||
}
|
||||
|
||||
return outstring;
|
||||
}
|
||||
|
||||
// Generate a tilejson resource from .mbtiles file
|
||||
void request_tilejson(const Resource &resource, ActorRef<FileSourceRequest> req) {
|
||||
auto path = url_to_path(resource.url);
|
||||
@@ -258,7 +218,7 @@ public:
|
||||
response.error.release();
|
||||
|
||||
if (is_compressed(*response.data)) {
|
||||
response.data = std::make_shared<std::string>(decompress_string(*response.data));
|
||||
response.data = std::make_shared<std::string>(util::decompress(*response.data));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,12 +37,12 @@ namespace util {
|
||||
// cause a link error.
|
||||
#undef compress
|
||||
|
||||
std::string compress(const std::string &raw) {
|
||||
std::string compress(const std::string &raw, int windowBits) {
|
||||
z_stream deflate_stream;
|
||||
memset(&deflate_stream, 0, sizeof(deflate_stream));
|
||||
|
||||
// TODO: reuse z_streams
|
||||
if (deflateInit(&deflate_stream, Z_DEFAULT_COMPRESSION) != Z_OK) {
|
||||
if (deflateInit2(&deflate_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, windowBits, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
|
||||
throw std::runtime_error("failed to initialize deflate");
|
||||
}
|
||||
|
||||
@@ -72,12 +72,12 @@ std::string compress(const std::string &raw) {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string decompress(const std::string &raw) {
|
||||
std::string decompress(const std::string &raw, int windowBits) {
|
||||
z_stream inflate_stream;
|
||||
memset(&inflate_stream, 0, sizeof(inflate_stream));
|
||||
|
||||
// TODO: reuse z_streams
|
||||
if (inflateInit(&inflate_stream) != Z_OK) {
|
||||
if (inflateInit2(&inflate_stream, windowBits) != Z_OK) {
|
||||
throw std::runtime_error("failed to initialize inflate");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user