From cae0fc272ed2c21e9ebfaefd01ed0116715b392d Mon Sep 17 00:00:00 2001 From: Nathan Gass Date: Thu, 14 Oct 2021 01:22:49 +0200 Subject: [PATCH] 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 --- include/mbgl/util/compression.hpp | 6 ++- .../src/mbgl/storage/mbtiles_file_source.cpp | 44 +------------------ .../default/src/mbgl/util/compression.cpp | 8 ++-- 3 files changed, 10 insertions(+), 48 deletions(-) diff --git a/include/mbgl/util/compression.hpp b/include/mbgl/util/compression.hpp index 93a3ddb8b..efe87ff2e 100644 --- a/include/mbgl/util/compression.hpp +++ b/include/mbgl/util/compression.hpp @@ -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 diff --git a/platform/default/src/mbgl/storage/mbtiles_file_source.cpp b/platform/default/src/mbgl/storage/mbtiles_file_source.cpp index 076a151ab..10f7ba264 100644 --- a/platform/default/src/mbgl/storage/mbtiles_file_source.cpp +++ b/platform/default/src/mbgl/storage/mbtiles_file_source.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -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(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 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(decompress_string(*response.data)); + response.data = std::make_shared(util::decompress(*response.data)); } } } diff --git a/platform/default/src/mbgl/util/compression.cpp b/platform/default/src/mbgl/util/compression.cpp index dbf2c9f2c..a71c21bcf 100644 --- a/platform/default/src/mbgl/util/compression.cpp +++ b/platform/default/src/mbgl/util/compression.cpp @@ -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"); }