Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use libdeflate instead of zlib #696

Open
wants to merge 42 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
17a8ace
[libdeflate] added smiple support for libdeflate | This work was spon…
Dec 20, 2018
a86e6ca
[libdeflate] added smiple support for libdeflate | This work was spon…
Dec 20, 2018
0d764c7
[libdeflate] added smiple support for libdeflate | This work was spon…
Dec 20, 2018
4a64427
[tippecanoe] Added missing dependency for libdeflate as git submodule…
Dec 21, 2018
44d5423
[tippecanoe] Added missing dependency for libdeflate as git submodule…
Dec 21, 2018
e866e2e
[tippecanoe] Added missing dependency for libdeflate as git submodule…
Dec 21, 2018
65f0a6d
[tippecanoe] Added missing dependency for libdeflate as git submodule…
Dec 21, 2018
03a21fb
[tippecanoe] Added missing dependency for libdeflate as git submodule…
Dec 21, 2018
fb197a4
[tippecanoe] Added missing dependency for libdeflate as git submodule…
Dec 21, 2018
7e54e24
[tippecanoe] Added missing dependency for libdeflate as git submodule…
Dec 21, 2018
3d5b7d6
[tippecanoe] Added missing dependency for libdeflate as git submodule…
Dec 21, 2018
7c4e638
[tippecanoe] Added missing dependency for libdeflate as git submodule…
Dec 21, 2018
1c54f51
[tippecanoe] Added missing dependency for libdeflate as git submodule…
Dec 21, 2018
31113da
[tippecanoe] Added missing dependency for libdeflate as git submodule…
Dec 21, 2018
e28d035
[tippecanoe] Added missing dependency for libdeflate as git submodule…
Dec 21, 2018
b351aca
[tippecanoe] Added missing dependency for libdeflate as git submodule…
Dec 21, 2018
52328b7
[tippecanoe] Added missing dependency for libdeflate as git submodule…
Dec 21, 2018
5f8bee6
[tippecanoe] Added missing dependency for libdeflate as git submodule…
Dec 21, 2018
fb07fbd
[tippecanoe] Added missing dependency for libdeflate as git submodule…
Dec 21, 2018
eb13d6b
[tippecanoe] Added missing dependency for libdeflate as git submodule…
Dec 21, 2018
ba3549e
[tippecanoe] Added missing dependency for libdeflate as git submodule…
Dec 21, 2018
586de1f
[tippecanoe] Added missing dependency for libdeflate as git submodule…
Dec 21, 2018
d25e79c
[tippecanoe] Fixed compression errors
Dec 22, 2018
ede4a95
[mvt.cpp] Fixed compression problems
Dec 24, 2018
edd48c4
[mvt.cpp] Fixed compression problems
Dec 24, 2018
6fc4259
[mvt.cpp] Fixed compression problems, added shared dependency to libd…
Dec 24, 2018
9c15a07
[mvt.cpp] Fixed compression problems, switched to static libdeflate l…
Dec 24, 2018
df400e4
[tippecanoe] added libdeflate into ldpath
Dec 24, 2018
0ad4753
[tippecanoe] added libdeflate into ldpath
Dec 24, 2018
acc28fa
[tippecanoe] added libdeflate into ldpath
Dec 24, 2018
b92ac21
[tippecanoe] added libdeflate into ldpath
Dec 24, 2018
f76ed56
[tippecanoe] added libdeflate into ldpath
Dec 24, 2018
99a86cf
[tippecanoe] added libdeflate into ldpath
Dec 24, 2018
b594b41
[tippecanoe] added libdeflate into ldpath
Dec 24, 2018
81d98e1
[mvt.cpp] Fixed compression problems, switched to static libdeflate l…
Dec 24, 2018
314b4a1
[tippecanoe] added libdeflate into ldpath
Dec 24, 2018
4019935
[tippecanoe] Fixed compression errors
Dec 24, 2018
ee1c9c5
[tippecanoe] Fixed compression errors
Dec 24, 2018
ca1dbe2
[tippecanoe] Fixed compression errors
Dec 24, 2018
05ac48e
[tippecanoe] Fixed compression errors
Dec 24, 2018
cdf5322
[tippecanoe] still trying to fix build errors
Dec 24, 2018
abd3e0f
[tippecanoe] Added missing dependency for libdeflate
Dec 24, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "libdeflate"]
path = libdeflate
url = https://github.com/ebiggers/libdeflate
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ RUN apt-get update \
RUN mkdir -p /tmp/tippecanoe-src
WORKDIR /tmp/tippecanoe-src
COPY . /tmp/tippecanoe-src
ENV LD_LIBRARY_PATH LD_LIBRARY_PATH:libdeflate

# Build tippecanoe
RUN make \
Expand Down
1 change: 1 addition & 0 deletions Dockerfile.centos7
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ RUN yum install -y make sqlite-devel zlib-devel bash git gcc-c++
RUN mkdir -p /tmp/tippecanoe-src
WORKDIR /tmp/tippecanoe-src
COPY . /tmp/tippecanoe-src
ENV LD_LIBRARY_PATH LD_LIBRARY_PATH:libdeflate

# Build tippecanoe
RUN make \
Expand Down
24 changes: 16 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ else
FINAL_FLAGS := -g $(WARNING_FLAGS) $(DEBUG_FLAGS)
endif

all: tippecanoe tippecanoe-enumerate tippecanoe-decode tile-join unit tippecanoe-json-tool
all: deflate tippecanoe tippecanoe-enumerate tippecanoe-decode tile-join unit tippecanoe-json-tool

docs: man/tippecanoe.1

install: tippecanoe tippecanoe-enumerate tippecanoe-decode tile-join tippecanoe-json-tool
install: deflate tippecanoe tippecanoe-enumerate tippecanoe-decode tile-join tippecanoe-json-tool
mkdir -p $(PREFIX)/bin
mkdir -p $(MANDIR)
cp tippecanoe $(PREFIX)/bin/tippecanoe
Expand All @@ -44,20 +44,21 @@ PG=
H = $(wildcard *.h) $(wildcard *.hpp)
C = $(wildcard *.c) $(wildcard *.cpp)

INCLUDES = -I/usr/local/include -I.
LIBS = -L/usr/local/lib
INCLUDES = -I/usr/local/include -I. -Ilibdeflate
LIBS = -L/usr/local/lib -L$(PWD)/libdeflate -L$(PWD)
LD_LIBRARY_PATH := /usr/local/lib:$(PWD)/libdeflate:$(PWD)

tippecanoe: geojson.o jsonpull/jsonpull.o tile.o pool.o mbtiles.o geometry.o projection.o memfile.o mvt.o serial.o main.o text.o dirtiles.o plugin.o read_json.o write_json.o geobuf.o evaluator.o geocsv.o csv.o geojson-loop.o
$(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -lpthread
$(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -lpthread libdeflate/libdeflate.a

tippecanoe-enumerate: enumerate.o
$(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lsqlite3

tippecanoe-decode: decode.o projection.o mvt.o write_json.o text.o jsonpull/jsonpull.o dirtiles.o
$(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3
$(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 libdeflate/libdeflate.a

tile-join: tile-join.o projection.o pool.o mbtiles.o mvt.o memfile.o dirtiles.o jsonpull/jsonpull.o text.o evaluator.o csv.o write_json.o
$(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -lpthread
$(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -lpthread libdeflate/libdeflate.a

tippecanoe-json-tool: jsontool.o jsonpull/jsonpull.o csv.o text.o geojson-loop.o
$(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -lpthread
Expand All @@ -73,7 +74,7 @@ unit: unit.o text.o
%.o: %.cpp
$(CXX) -MMD $(PG) $(INCLUDES) $(FINAL_FLAGS) $(CXXFLAGS) -c -o $@ $<

clean:
clean: deflate-clean
rm -f ./tippecanoe ./tippecanoe-* ./tile-join ./unit *.o *.d */*.o */*.d tests/**/*.mbtiles tests/**/*.check

indent:
Expand Down Expand Up @@ -331,6 +332,7 @@ layer-json-test:

# Use this target to regenerate the standards that the tests are compared against
# after making a change that legitimately changes their output
#

prep-test: $(TESTS)

Expand All @@ -339,3 +341,9 @@ tests/%.json: Makefile tippecanoe tippecanoe-decode
./tippecanoe-decode -x generator $@.check.mbtiles > $@
cmp $(patsubst %.check,%,$@) $@
rm $@.check.mbtiles

deflate: deflate-clean
cd libdeflate && make BUILDTYPE=$(BUILDTYPE) libdeflate.a

deflate-clean:
cd libdeflate && make realclean
1 change: 1 addition & 0 deletions libdeflate
Submodule libdeflate added at d6d50c
133 changes: 54 additions & 79 deletions mvt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
#include <string>
#include <vector>
#include <map>
#include <zlib.h>
#include <errno.h>
#include <limits.h>
#include <ctype.h>
#include <libdeflate.h>
#include "mvt.hpp"
#include "geometry.hpp"
#include "protozero/varint.hpp"
Expand All @@ -22,114 +22,89 @@ mvt_geometry::mvt_geometry(int nop, long long nx, long long ny) {

// https://github.com/mapbox/mapnik-vector-tile/blob/master/src/vector_tile_compression.hpp
bool is_compressed(std::string const &data) {
return data.size() > 2 && (((uint8_t) data[0] == 0x78 && (uint8_t) data[1] == 0x9C) || ((uint8_t) data[0] == 0x1F && (uint8_t) data[1] == 0x8B));
return data.size() > 2 && (((uint8_t) data[0] & 0x60) == 0x4 || ((uint8_t) data[0] & 0x60) == 0x20);
}

// https://github.com/mapbox/mapnik-vector-tile/blob/master/src/vector_tile_compression.hpp
int decompress(std::string const &input, std::string &output) {
z_stream inflate_s;
inflate_s.zalloc = Z_NULL;
inflate_s.zfree = Z_NULL;
inflate_s.opaque = Z_NULL;
inflate_s.avail_in = 0;
inflate_s.next_in = Z_NULL;
if (inflateInit2(&inflate_s, 32 + 15) != Z_OK) {
fprintf(stderr, "Decompression error: %s\n", inflate_s.msg);
size_t avail_in = 8192;
size_t avail_out = 8192;
long unsigned int actual_output = 0;
long unsigned int actual_input = 0;
long unsigned int actual_out = 0;
long unsigned int actual_in = 0;
output.resize(avail_out);
void *current_out = (void *) output.data();
void *current_in = (void *) input.data();

struct libdeflate_decompressor *decompressor = libdeflate_alloc_decompressor();
decompress:
int ret = libdeflate_deflate_decompress_ex(decompressor,
current_in, avail_in,
current_out, avail_out,
&actual_input,
&actual_output);
actual_in += actual_input;
actual_out += actual_output;
if (ret == LIBDEFLATE_SHORT_OUTPUT) {
output.resize(actual_out + avail_out);
current_out = (void *) ((long) output.data() + actual_out);
current_in = (void *) ((long) input.data() + actual_in);
goto decompress;
}
inflate_s.next_in = (Bytef *) input.data();
inflate_s.avail_in = input.size();
inflate_s.next_out = (Bytef *) output.data();
inflate_s.avail_out = output.size();
libdeflate_free_decompressor(decompressor);

while (true) {
size_t existing_output = inflate_s.next_out - (Bytef *) output.data();

output.resize(existing_output + 2 * inflate_s.avail_in + 100);
inflate_s.next_out = (Bytef *) output.data() + existing_output;
inflate_s.avail_out = output.size() - existing_output;

int ret = inflate(&inflate_s, 0);
if (ret < 0) {
if (ret != LIBDEFLATE_SUCCESS) {
if (ret == LIBDEFLATE_BAD_DATA) {
fprintf(stderr, "data not compressed");
} else {
fprintf(stderr, "Decompression error: ");
if (ret == Z_DATA_ERROR) {
fprintf(stderr, "data error");
}
if (ret == Z_STREAM_ERROR) {
fprintf(stderr, "stream error");
}
if (ret == Z_MEM_ERROR) {
if (ret == LIBDEFLATE_INSUFFICIENT_SPACE) {
fprintf(stderr, "out of memory");
}
if (ret == Z_BUF_ERROR) {
fprintf(stderr, "no data in buffer");
}
fprintf(stderr, "\n");
return 0;
}

if (ret == Z_STREAM_END) {
break;
}

// ret must be Z_OK or Z_NEED_DICT;
// continue decompresing
fprintf(stderr, "\n");
return -ret;
}

output.resize(inflate_s.next_out - (Bytef *) output.data());
inflateEnd(&inflate_s);
return 1;
output.resize(actual_out);
return 0;
}

// https://github.com/mapbox/mapnik-vector-tile/blob/master/src/vector_tile_compression.hpp
int compress(std::string const &input, std::string &output) {
z_stream deflate_s;
deflate_s.zalloc = Z_NULL;
deflate_s.zfree = Z_NULL;
deflate_s.opaque = Z_NULL;
deflate_s.avail_in = 0;
deflate_s.next_in = Z_NULL;
deflateInit2(&deflate_s, Z_BEST_COMPRESSION, Z_DEFLATED, 31, 8, Z_DEFAULT_STRATEGY);
deflate_s.next_in = (Bytef *) input.data();
deflate_s.avail_in = input.size();
size_t length = 0;
do {
size_t increase = input.size() / 2 + 1024;
output.resize(length + increase);
deflate_s.avail_out = increase;
deflate_s.next_out = (Bytef *) (output.data() + length);
int ret = deflate(&deflate_s, Z_FINISH);
if (ret != Z_STREAM_END && ret != Z_OK && ret != Z_BUF_ERROR) {
return -1;
}
length += (increase - deflate_s.avail_out);
} while (deflate_s.avail_out == 0);
deflateEnd(&deflate_s);
output.resize(length);
return 0;
size_t avail_in = input.size();
size_t avail_out = avail_in * 8;
output.resize(avail_out);
struct libdeflate_compressor *deflate_s = libdeflate_alloc_compressor(9);
int ret = libdeflate_deflate_compress(deflate_s,
(void *) input.data(), avail_in,
(void *) output.data(), avail_out);
libdeflate_free_compressor(deflate_s);
if (ret == 0) {
return -1;
}
output.resize(ret);
return 1;
}

bool mvt_tile::decode(std::string &message, bool &was_compressed) {
layers.clear();
std::string src;
std::string uncompressed;

if (is_compressed(message)) {
std::string uncompressed;
if (decompress(message, uncompressed) == 0) {
exit(EXIT_FAILURE);
}
was_compressed = false;
src = message;
if (decompress(message, uncompressed) == 0) {
src = uncompressed;
was_compressed = true;
} else {
src = message;
was_compressed = false;
}

protozero::pbf_reader reader(src);

while (reader.next()) {
switch (reader.tag()) {
case 3: /* layer */
{
case 3: /* layer */ {
protozero::pbf_reader layer_reader(reader.get_message());
mvt_layer layer;

Expand Down