Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
1e9f266
use property_mapper (#68)
artemp Jul 11, 2018
4f2d2e5
use latest vtzero API - refs #68
Jul 22, 2018
25053e5
optimize point filtering
Jul 22, 2018
c381ccd
run clang-format
Jul 22, 2018
d257c19
Remove `reserve` in the point_handler
Jul 28, 2018
02cb6b1
Merge branch 'master' into property_mapper
springmeyer Jul 28, 2018
63b212a
remove unused things
Jul 28, 2018
774f53d
fix broken code from incorrect merge
Jul 28, 2018
c563018
start porting to libdeflate - mapbox/gzip-hpp#25
Jul 28, 2018
50b1a85
build against local gzip-hpp
Jul 28, 2018
89cf870
also link libdeflate on linux
Jul 28, 2018
cb239cc
try again to get linking working on linux
Jul 28, 2018
f43f059
fix local header search
Jul 28, 2018
dfb66bc
inherit flags
Jul 28, 2018
00e6296
set CXXFLAGS so everybody sees them
Jul 28, 2018
7090aa8
releasing 0.2.0-zlib [publish binary]
millzpaugh Aug 2, 2018
6590615
upgrade libdeflate to version 1.0
artemp Oct 4, 2018
fafeb47
inherit CXXFLAGS to avoid breaking coverage build
Oct 8, 2018
d40f547
Merge branch 'master' into libdeflate
springmeyer Oct 9, 2018
70bac5f
use local libdeflate c++ wrapper [initial commit]
artemp Oct 15, 2018
55d1a96
remove unused header
artemp Oct 15, 2018
5b8c152
simplify + format
artemp Oct 15, 2018
7ef90b2
sync with master
artemp Oct 15, 2018
9282bee
Fixed usage of deprecated (node-v10.12.0) methods.
artemp Oct 18, 2018
d0ad0a7
clang-format
artemp Oct 18, 2018
1224ec6
attempting to fix .travis.yml (/home/travis/.travis/job_stages: line …
artemp Oct 18, 2018
faf52cb
Use `Nan::To<T>` converters
artemp Oct 19, 2018
c15df09
use `std::vector<std::vector<char>>` as buffer cache.
artemp Oct 19, 2018
698fa0f
Initial implementation useing `N-API` via `node-addon-api`
artemp Oct 25, 2018
f2c8360
check CallbackInfo index is valid + format/tidy
artemp Oct 25, 2018
f1765fd
attempting to fix .travis.yml (/home/travis/.travis/job_stages: line …
artemp Oct 18, 2018
7aabb89
Perhaps more generic approach to obtaining 'node-addon-api' include path
artemp Oct 25, 2018
23eeb11
Merge branch 'master' into n-api
artemp Oct 29, 2018
18e5359
remove `<uv,h>`
artemp Oct 30, 2018
4efb356
Simplify `CallbackError` signature
artemp Oct 31, 2018
8420108
Merge branch 'master' into libdeflate
artemp Nov 5, 2018
659cb99
Merge branch 'n-api' into libdeflate
artemp Nov 5, 2018
ef12486
clang-tidy
artemp Nov 5, 2018
b39a441
bump version to v0.2.0 [publish binary]
artemp Nov 9, 2018
f0016e3
refactor decompression logic to use output buffer size (not capacity)…
artemp Nov 12, 2018
3f80258
bump version to v0.2.1 [publish binary]
artemp Nov 12, 2018
ae290da
use `As<Napi::Object>` consistently
artemp Nov 19, 2018
809fb8f
Merge branch 'n-api' into libdeflate
artemp Nov 19, 2018
93806a9
remove redundant conversion
artemp Nov 19, 2018
4f50896
Minimise internal type conversions by passing `Napi::Buffer<char>` an…
artemp Nov 19, 2018
e730387
Merge branch 'n-api' into libdeflate
artemp Nov 19, 2018
86e4ab1
Merge branch 'master' into n-api
artemp Dec 3, 2018
eb92855
Merge branch 'n-api' into libdeflate
artemp Dec 3, 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
12 changes: 8 additions & 4 deletions binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
['AR', '<(module_root_dir)/mason_packages/.link/bin/llvm-ar'],
['NM', '<(module_root_dir)/mason_packages/.link/bin/llvm-nm']
],
'includes': [ 'common.gypi' ], # brings in a default set of options that are inherited from gyp
'includes': [ 'common.gypi'], # brings in a default set of options that are inherited from gyp
'variables': { # custom variables we use specific to this file
'error_on_warnings%':'true', # can be overriden by a command line variable because of the % sign using "WERROR" (defined in Makefile)
# Use this variable to silence warnings from mason dependencies and from NAN
# Use this variable to silence warnings from mason dependencies
# It's a variable to make easy to pass to
# cflags (linux) and xcode (mac)
'system_includes': [
"-isystem <(module_root_dir)/<!(node -e \"require('nan')\")",
"-isystem <!@(node -p \"require('node-addon-api').include.slice(1,-1)\")",
"-isystem <(module_root_dir)/mason_packages/.link/include/"
],
# Flags we pass to the compiler to ensure the compiler
Expand Down Expand Up @@ -77,8 +77,11 @@
'./src/module.cpp',
'./src/vtcomposite.cpp'
],
'libraries':[
'<(module_root_dir)/mason_packages/.link/lib/libdeflate.a'
],
'ldflags': [
'-Wl,-z,now',
'-Wl,-z,now'
],
'conditions': [
['error_on_warnings == "true"', {
Expand All @@ -88,6 +91,7 @@
}
}]
],
#'include_dirs' : ["<!@(node -p \"require('node-addon-api').include\")"],
'cflags_cc': [
'<@(system_includes)',
'<@(compiler_checks)'
Expand Down
4 changes: 2 additions & 2 deletions mason-versions.ini
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
[headers]
boost=1.66.0
geometry=96d3505
gzip-hpp=0.1.0
protozero=1.6.2
spatial-algorithms=0.1.0
variant=1.1.5
vtzero=2915725
[compiled]
libdeflate=1.0
clang++=5.0.1
clang-tidy=5.0.1
clang-format=5.0.1
llvm-cov=5.0.1
binutils=2.30
binutils=2.30
10 changes: 8 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@mapbox/vtcomposite",
"version": "0.1.1",
"description": "Skeleton for bindings to C++ libraries for Node.js using NAN",
"version": "0.2.1",
"description": "Compositing operations on Vector Tiles (c++ bindings using N-API)",
"url": "http://github.com/mapbox/vtcomposite",
"main": "./lib/index.js",
"repository": {
Expand All @@ -18,7 +18,7 @@
"license": "ISC",
"dependencies": {
"mason-js-sdk": "^0.1.4",
"nan": "~2.10.0",
"node-addon-api": "^1.5.0",
"node-pre-gyp": "~0.10.2"
},
"devDependencies": {
Expand Down
1 change: 0 additions & 1 deletion scripts/sanitize.sh
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,3 @@ else
LD_PRELOAD=${MASON_LLVM_RT_PRELOAD} \
npm test
fi

166 changes: 166 additions & 0 deletions src/deflate.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
#pragma once

// libdeflate
#include <libdeflate.h>
// std
#include <limits>
#include <stdexcept>
#include <memory>

namespace deflate {

inline bool is_zlib(char const* data) noexcept
{
return (static_cast<uint8_t>(data[0]) == 0x78 &&
(static_cast<uint8_t>(data[1]) == 0x9C ||
static_cast<uint8_t>(data[1]) == 0x01 ||
static_cast<uint8_t>(data[1]) == 0xDA ||
static_cast<uint8_t>(data[1]) == 0x5E));
}

inline bool is_gzip(char const* data) noexcept
{
return (static_cast<uint8_t>(data[0]) == 0x1F && static_cast<uint8_t>(data[1]) == 0x8B);
}

inline bool is_compressed(char const* data, std::size_t size) noexcept
{
return size > 2 && (is_gzip(data) || is_zlib(data));
}

class Compressor
{
struct cleanup_compressor
{
void operator()(libdeflate_compressor* ptr) const
{
if (ptr) libdeflate_free_compressor(ptr);
}
};
std::size_t max_;
int level_;
std::unique_ptr<libdeflate_compressor, cleanup_compressor> compressor_;
// make noncopyable
Compressor(Compressor const&) = delete;
Compressor& operator=(Compressor const&) = delete;

public:
Compressor(int level = 6,
std::size_t max_bytes = 2000000000) // by default refuse operation if uncompressed data is > 2GB
: max_{max_bytes},
level_{level},
compressor_{libdeflate_alloc_compressor(level_)}
{
if (!compressor_)
{
throw std::runtime_error("libdeflate_alloc_compressor failed");
}
}

template <typename OutputType>
void operator()(OutputType& output,
char const* data,
std::size_t size) const
{
if (size > max_)
{
throw std::runtime_error("size may use more memory than intended when decompressing");
}

std::size_t max_compressed_size = libdeflate_gzip_compress_bound(compressor_.get(), size);
// TODO: sanity check this before allocating
if (max_compressed_size > output.size())
{
output.resize(max_compressed_size);
}

std::size_t actual_compressed_size = libdeflate_gzip_compress(compressor_.get(),
data,
size,
const_cast<char*>(output.data()),
max_compressed_size);
if (actual_compressed_size == 0)
{
throw std::runtime_error("actual_compressed_size 0");
}
output.resize(actual_compressed_size);
}
};

class Decompressor
{
struct cleanup_decompressor
{
void operator()(libdeflate_decompressor* ptr) const
{
if (ptr) libdeflate_free_decompressor(ptr);
}
};

std::size_t const max_;
std::unique_ptr<libdeflate_decompressor, cleanup_decompressor> decompressor_;
// noncopyable
Decompressor(Decompressor const&) = delete;
Decompressor& operator=(Decompressor const&) = delete;

public:
Decompressor(std::size_t max_bytes = 2147483648u) // by default refuse operation if required uutput buffer is > 2GB
: max_{max_bytes},
decompressor_{libdeflate_alloc_decompressor(), cleanup_decompressor()}
{
if (!decompressor_)
{
throw std::runtime_error("libdeflate_alloc_decompressor failed");
}
}

template <typename OutputType>
void operator()(OutputType& output,
char const* data,
std::size_t size) const
{
if (is_gzip(data))
apply(output, libdeflate_gzip_decompress, data, size);
else if (is_zlib(data))
apply(output, libdeflate_zlib_decompress, data, size);
}

template <typename OutputType, typename Fun>
void apply(OutputType& output, Fun fun,
char const* data,
std::size_t size) const
{
std::size_t actual_size;
std::size_t uncompressed_size_guess = std::min(size * 4, max_);
output.resize(uncompressed_size_guess);
libdeflate_result result;
for (;;)
{
result = fun(decompressor_.get(),
data,
size,
const_cast<char*>(output.data()),
output.size(), &actual_size);
if (result == LIBDEFLATE_SUCCESS)
{
output.resize(actual_size);
break;
}
else if (result == LIBDEFLATE_INSUFFICIENT_SPACE)
{
if (output.size() == max_)
{
throw std::runtime_error("request to resize output buffer can't exceed maximum limit");
}
std::size_t new_size = std::min(output.size() << 1, max_);
output.resize(new_size);
}
else //LIBDEFLATE_BAD_DATA
{
throw std::runtime_error("bad data: did not succeed");
}
}
}
};

} // namespace deflate
9 changes: 5 additions & 4 deletions src/module.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#include "vtcomposite.hpp"
#include <nan.h>
#include <napi.h>

NAN_MODULE_INIT(init)
Napi::Object init(Napi::Env env, Napi::Object exports)
{
Nan::SetMethod(target, "composite", vtile::composite);
exports.Set(Napi::String::New(env, "composite"), Napi::Function::New(env, vtile::composite));
return exports;
}

NODE_MODULE(module, init) // NOLINT
NODE_API_MODULE(module, init) // NOLINT
29 changes: 7 additions & 22 deletions src/module_utils.hpp
Original file line number Diff line number Diff line change
@@ -1,28 +1,13 @@
#pragma once
#include <nan.h>
#include <napi.h>

namespace utils {

/*
* This is an internal function used to return callback error messages instead of
* throwing errors.
* Usage:
*
* v8::Local<v8::Function> callback;
* return CallbackError("error message", callback); // "return" is important to
* prevent duplicate callbacks from being fired!
*
*
* "inline" is important here as well. See for more contex:
* - https://github.com/mapbox/cpp/blob/master/glossary.md#inline-keyword
* - https://github.com/mapbox/node-cpp-skel/pull/52#discussion_r126847394 for
* context
*
*/
inline void CallbackError(std::string message, v8::Local<v8::Function> func)
inline Napi::Value CallbackError(std::string const& message, Napi::CallbackInfo const& info)
{
Nan::Callback cb(func);
v8::Local<v8::Value> argv[1] = {Nan::Error(message.c_str())};
Nan::Call(cb, 1, argv);
Napi::Object obj = Napi::Object::New(info.Env());
obj.Set("message", message);
auto func = info[info.Length() - 1].As<Napi::Function>();
return func.Call({obj});
}
} // namespace utils
} // namespace utils
Loading