summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Käfer <mail@kkaefer.com>2018-02-20 15:06:26 +0100
committerKonstantin Käfer <mail@kkaefer.com>2018-02-21 14:50:13 +0100
commit021e1ae596440cfdee5ffe75907b76069ae44307 (patch)
treeebf15ff8a72e5f14291ba37b6f297ca9a738eea4
parent06213d9145d3b20b63e235cc25678fd76dc296d0 (diff)
downloadqtlocation-mapboxgl-upstream/blob.tar.gz
[core] introduce Blob for compressed and uncompressed dataupstream/blob
- Blob is a wrapper type for a shared_ptr<const string> that has accessor functions for getting compressed and uncompressed data - Moved util::writeFile, util::readFile, util::compress, util::uncompress, decodeImage, and encodePNG to the Blob interface - Added Blob support to Request and file sources - Added Blob support to VectorTile objects - Added support for gzip decoding to util::uncompress - We're no longer compressing WebP, PNG, and JPEG data when storing in the OfflineDatabase - Android's HTTPRequest returns compressed Blobs by default One caveat is that our previous decompress function didn't support gzip, so once users upgrade to this version, their offline cache may contain both zlib-compressed data and gzip-compressed data, but older versions won't be able to decompress gzip data. On the other hand, we don't support downgrading SDKs anyway, so this shouldn't be a problem. To be on the safe side, we could bump the user_version of the SQLite DB.
-rw-r--r--benchmark/api/query.benchmark.cpp4
-rw-r--r--benchmark/api/render.benchmark.cpp8
-rw-r--r--benchmark/parse/vector_tile.benchmark.cpp2
-rw-r--r--bin/render.cpp2
-rw-r--r--cmake/core-files.cmake2
-rw-r--r--include/mbgl/storage/resource.hpp16
-rw-r--r--include/mbgl/storage/response.hpp3
-rw-r--r--include/mbgl/style/style.hpp5
-rw-r--r--include/mbgl/util/blob.hpp34
-rw-r--r--include/mbgl/util/compression.hpp7
-rw-r--r--include/mbgl/util/image.hpp6
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/UnknownContentEncodingException.java12
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java19
-rw-r--r--platform/android/src/asset_manager_file_source.cpp5
-rw-r--r--platform/android/src/http_file_source.cpp14
-rw-r--r--platform/android/src/image.cpp12
-rwxr-xr-xplatform/android/src/native_map_view.cpp4
-rw-r--r--platform/darwin/src/http_file_source.mm5
-rw-r--r--platform/darwin/src/image.mm5
-rw-r--r--platform/darwin/test/MGLOfflineStorageTests.mm4
-rw-r--r--platform/default/asset_file_source.cpp8
-rw-r--r--platform/default/default_file_source.cpp15
-rw-r--r--platform/default/http_file_source.cpp4
-rw-r--r--platform/default/image.cpp7
-rw-r--r--platform/default/local_file_source.cpp8
-rw-r--r--platform/default/mbgl/storage/offline_database.cpp73
-rw-r--r--platform/default/mbgl/storage/offline_database.hpp2
-rw-r--r--platform/default/mbgl/storage/offline_download.cpp18
-rw-r--r--platform/default/online_file_source.cpp10
-rw-r--r--platform/default/png_writer.cpp4
-rw-r--r--platform/ios/ios.xcodeproj/project.pbxproj4
-rw-r--r--platform/macos/macos.xcodeproj/project.pbxproj2
-rw-r--r--platform/node/src/node_map.cpp4
-rw-r--r--platform/node/src/node_request.cpp6
-rw-r--r--platform/qt/src/http_request.cpp4
-rw-r--r--platform/qt/src/qmapboxgl.cpp4
-rw-r--r--platform/qt/src/qt_image.cpp11
-rw-r--r--platform/qt/test/qmapboxgl.test.cpp2
-rw-r--r--src/mbgl/gl/program.hpp4
-rw-r--r--src/mbgl/programs/binary_program.cpp9
-rw-r--r--src/mbgl/programs/binary_program.hpp5
-rw-r--r--src/mbgl/sprite/sprite_loader.cpp8
-rw-r--r--src/mbgl/sprite/sprite_loader_worker.cpp5
-rw-r--r--src/mbgl/sprite/sprite_loader_worker.hpp3
-rw-r--r--src/mbgl/sprite/sprite_parser.cpp7
-rw-r--r--src/mbgl/sprite/sprite_parser.hpp2
-rw-r--r--src/mbgl/storage/resource.cpp18
-rw-r--r--src/mbgl/style/sources/geojson_source.cpp3
-rw-r--r--src/mbgl/style/sources/image_source.cpp2
-rw-r--r--src/mbgl/style/sources/raster_source.cpp2
-rw-r--r--src/mbgl/style/sources/vector_source.cpp3
-rw-r--r--src/mbgl/style/style.cpp4
-rw-r--r--src/mbgl/style/style_impl.cpp12
-rw-r--r--src/mbgl/style/style_impl.hpp8
-rw-r--r--src/mbgl/text/glyph_manager.cpp2
-rw-r--r--src/mbgl/text/glyph_pbf.cpp5
-rw-r--r--src/mbgl/text/glyph_pbf.hpp2
-rw-r--r--src/mbgl/tile/raster_dem_tile.cpp2
-rw-r--r--src/mbgl/tile/raster_dem_tile.hpp2
-rw-r--r--src/mbgl/tile/raster_dem_tile_worker.cpp4
-rw-r--r--src/mbgl/tile/raster_dem_tile_worker.hpp3
-rw-r--r--src/mbgl/tile/raster_tile.cpp2
-rw-r--r--src/mbgl/tile/raster_tile.hpp2
-rw-r--r--src/mbgl/tile/raster_tile_worker.cpp4
-rw-r--r--src/mbgl/tile/raster_tile_worker.hpp3
-rw-r--r--src/mbgl/tile/tile_loader_impl.hpp2
-rw-r--r--src/mbgl/tile/vector_tile.cpp4
-rw-r--r--src/mbgl/tile/vector_tile.hpp2
-rw-r--r--src/mbgl/tile/vector_tile_data.cpp15
-rw-r--r--src/mbgl/tile/vector_tile_data.hpp9
-rw-r--r--src/mbgl/util/blob.cpp46
-rw-r--r--src/mbgl/util/compression.cpp37
-rw-r--r--src/mbgl/util/io.cpp34
-rw-r--r--src/mbgl/util/io.hpp7
-rw-r--r--test/api/annotations.test.cpp54
-rw-r--r--test/api/custom_geometry_source.test.cpp2
-rw-r--r--test/api/custom_layer.test.cpp2
-rw-r--r--test/api/query.test.cpp4
-rw-r--r--test/api/recycle_map.cpp4
-rw-r--r--test/api/zoom_history.cpp2
-rw-r--r--test/gl/context.test.cpp2
-rw-r--r--test/map/map.test.cpp54
-rw-r--r--test/map/prefetch.test.cpp10
-rw-r--r--test/programs/binary_program.test.cpp2
-rw-r--r--test/renderer/image_manager.test.cpp4
-rw-r--r--test/sprite/sprite_loader.test.cpp6
-rw-r--r--test/sprite/sprite_parser.test.cpp38
-rw-r--r--test/src/mbgl/test/util.cpp12
-rw-r--r--test/storage/asset_file_source.test.cpp22
-rw-r--r--test/storage/default_file_source.test.cpp100
-rw-r--r--test/storage/http_file_source.test.cpp27
-rw-r--r--test/storage/local_file_source.test.cpp20
-rw-r--r--test/storage/offline_database.test.cpp62
-rw-r--r--test/storage/offline_download.test.cpp10
-rw-r--r--test/storage/online_file_source.test.cpp28
-rw-r--r--test/style/expression/expression.test.cpp6
-rw-r--r--test/style/source.test.cpp26
-rw-r--r--test/style/style.test.cpp16
-rw-r--r--test/style/style_layer.test.cpp2
-rw-r--r--test/style/style_parser.test.cpp8
-rw-r--r--test/text/glyph_manager.test.cpp8
-rw-r--r--test/text/glyph_pbf.test.cpp2
-rw-r--r--test/text/local_glyph_rasterizer.test.cpp8
-rw-r--r--test/util/image.test.cpp14
-rw-r--r--test/util/memory.test.cpp6
105 files changed, 723 insertions, 475 deletions
diff --git a/benchmark/api/query.benchmark.cpp b/benchmark/api/query.benchmark.cpp
index 7694585526..f9cbbff32b 100644
--- a/benchmark/api/query.benchmark.cpp
+++ b/benchmark/api/query.benchmark.cpp
@@ -22,10 +22,10 @@ public:
NetworkStatus::Set(NetworkStatus::Status::Offline);
fileSource.setAccessToken("foobar");
- map.getStyle().loadJSON(util::read_file("benchmark/fixtures/api/style.json"));
+ map.getStyle().loadJSON(util::readFile("benchmark/fixtures/api/style.json"));
map.setLatLngZoom({ 40.726989, -73.992857 }, 15); // Manhattan
map.getStyle().addImage(std::make_unique<style::Image>("test-icon",
- decodeImage(util::read_file("benchmark/fixtures/api/default_marker.png")), 1.0));
+ decodeImage(util::readFile("benchmark/fixtures/api/default_marker.png")), 1.0));
frontend.render(map);
}
diff --git a/benchmark/api/render.benchmark.cpp b/benchmark/api/render.benchmark.cpp
index a1b557777f..8c783c6a0e 100644
--- a/benchmark/api/render.benchmark.cpp
+++ b/benchmark/api/render.benchmark.cpp
@@ -29,11 +29,11 @@ public:
ThreadPool threadPool { 4 };
};
-static void prepare(Map& map, optional<std::string> json = {}) {
- map.getStyle().loadJSON(json ? *json : util::read_file("benchmark/fixtures/api/style.json"));
+static void prepare(Map& map, Blob json = {}) {
+ map.getStyle().loadJSON(json ? json : util::readFile("benchmark/fixtures/api/style.json"));
map.setLatLngZoom({ 40.726989, -73.992857 }, 15); // Manhattan
map.getStyle().addImage(std::make_unique<style::Image>("test-icon",
- decodeImage(util::read_file("benchmark/fixtures/api/default_marker.png")), 1.0));
+ decodeImage(util::readFile("benchmark/fixtures/api/default_marker.png")), 1.0));
}
} // end namespace
@@ -55,7 +55,7 @@ static void API_renderStill_reuse_map_switch_styles(::benchmark::State& state) {
Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), 1, bench.fileSource, bench.threadPool, MapMode::Static};
while (state.KeepRunning()) {
- prepare(map, { "{}" });
+ prepare(map, { "{}", false });
frontend.render(map);
prepare(map);
frontend.render(map);
diff --git a/benchmark/parse/vector_tile.benchmark.cpp b/benchmark/parse/vector_tile.benchmark.cpp
index 24623dbda7..fab22ae380 100644
--- a/benchmark/parse/vector_tile.benchmark.cpp
+++ b/benchmark/parse/vector_tile.benchmark.cpp
@@ -6,7 +6,7 @@
using namespace mbgl;
static void Parse_VectorTile(benchmark::State& state) {
- auto data = std::make_shared<std::string>(util::read_file("test/fixtures/api/assets/streets/10-163-395.vector.pbf"));
+ auto data = util::readFile("test/fixtures/api/assets/streets/10-163-395.vector.pbf");
while (state.KeepRunning()) {
std::size_t length = 0;
diff --git a/bin/render.cpp b/bin/render.cpp
index 6ceb32eb00..4b15ced9a9 100644
--- a/bin/render.cpp
+++ b/bin/render.cpp
@@ -101,7 +101,7 @@ int main(int argc, char *argv[]) {
try {
std::ofstream out(output, std::ios::binary);
- out << encodePNG(frontend.render(map));
+ out << *encodePNG(frontend.render(map)).uncompressedData();
out.close();
} catch(std::exception& e) {
std::cout << "Error: " << e.what() << std::endl;
diff --git a/cmake/core-files.cmake b/cmake/core-files.cmake
index f24482e301..a0523a6f42 100644
--- a/cmake/core-files.cmake
+++ b/cmake/core-files.cmake
@@ -656,6 +656,7 @@ set(MBGL_CORE_FILES
# util
include/mbgl/util/async_request.hpp
include/mbgl/util/async_task.hpp
+ include/mbgl/util/blob.hpp
include/mbgl/util/char_array_buffer.hpp
include/mbgl/util/chrono.hpp
include/mbgl/util/color.hpp
@@ -698,6 +699,7 @@ set(MBGL_CORE_FILES
include/mbgl/util/work_request.hpp
include/mbgl/util/work_task.hpp
include/mbgl/util/work_task_impl.hpp
+ src/mbgl/util/blob.cpp
src/mbgl/util/chrono.cpp
src/mbgl/util/clip_id.cpp
src/mbgl/util/clip_id.hpp
diff --git a/include/mbgl/storage/resource.hpp b/include/mbgl/storage/resource.hpp
index 318fa389f4..d9da494e4d 100644
--- a/include/mbgl/storage/resource.hpp
+++ b/include/mbgl/storage/resource.hpp
@@ -42,12 +42,23 @@ public:
All = Cache | Network,
};
+ enum class Compression : bool {
+ // The data will be an uncompressed blob, even if it was obtained in compressed form.
+ Uncompressed = false,
+
+ // The data will be returned compressed if it was already obtained in compressed form,
+ // and uncompressed otherwise.
+ PreferCompressed = true,
+ };
+
Resource(Kind kind_,
std::string url_,
optional<TileData> tileData_ = {},
- LoadingMethod loadingMethod_ = LoadingMethod::All)
+ LoadingMethod loadingMethod_ = LoadingMethod::All,
+ Compression compression_ = Compression::PreferCompressed)
: kind(kind_),
loadingMethod(loadingMethod_),
+ compression(compression_),
url(std::move(url_)),
tileData(std::move(tileData_)) {
}
@@ -72,6 +83,7 @@ public:
Kind kind;
LoadingMethod loadingMethod;
+ Compression compression;
std::string url;
// Includes auxiliary data if this is a tile request.
@@ -80,7 +92,7 @@ public:
optional<Timestamp> priorModified = {};
optional<Timestamp> priorExpires = {};
optional<std::string> priorEtag = {};
- std::shared_ptr<const std::string> priorData;
+ Blob priorData;
};
diff --git a/include/mbgl/storage/response.hpp b/include/mbgl/storage/response.hpp
index 508400141b..81a84effb7 100644
--- a/include/mbgl/storage/response.hpp
+++ b/include/mbgl/storage/response.hpp
@@ -2,6 +2,7 @@
#include <mbgl/util/chrono.hpp>
#include <mbgl/util/optional.hpp>
+#include <mbgl/util/blob.hpp>
#include <string>
#include <memory>
@@ -31,7 +32,7 @@ public:
bool mustRevalidate = false;
// The actual data of the response. Present only for non-error, non-notModified responses.
- std::shared_ptr<const std::string> data;
+ Blob data;
optional<Timestamp> modified;
optional<Timestamp> expires;
diff --git a/include/mbgl/style/style.hpp b/include/mbgl/style/style.hpp
index d6fdbd8f2c..dffdbf99ec 100644
--- a/include/mbgl/style/style.hpp
+++ b/include/mbgl/style/style.hpp
@@ -3,6 +3,7 @@
#include <mbgl/style/transition_options.hpp>
#include <mbgl/map/camera.hpp>
#include <mbgl/util/geo.hpp>
+#include <mbgl/util/blob.hpp>
#include <string>
#include <vector>
@@ -25,10 +26,10 @@ public:
Style(Scheduler&, FileSource&, float pixelRatio);
~Style();
- void loadJSON(const std::string&);
+ void loadJSON(Blob);
void loadURL(const std::string&);
- std::string getJSON() const;
+ Blob getJSON() const;
std::string getURL() const;
// Defaults
diff --git a/include/mbgl/util/blob.hpp b/include/mbgl/util/blob.hpp
new file mode 100644
index 0000000000..df8fddc773
--- /dev/null
+++ b/include/mbgl/util/blob.hpp
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <memory>
+#include <string>
+
+namespace mbgl {
+
+class Blob {
+public:
+ Blob();
+ Blob(std::shared_ptr<const std::string> bytes, bool gzip);
+ Blob(std::string&& bytes, bool compressed);
+
+ // Return uncompressed/compressed data.
+ std::shared_ptr<const std::string> uncompressedData() const;
+ std::shared_ptr<const std::string> compressedData() const;
+
+ // Transform the blob to being uncompressed.
+ void uncompress();
+
+ bool isCompressed() const {
+ return compressed;
+ }
+
+ explicit operator bool() const {
+ return (bool)bytes;
+ }
+
+private:
+ std::shared_ptr<const std::string> bytes;
+ bool compressed;
+};
+
+} // namespace mbgl
diff --git a/include/mbgl/util/compression.hpp b/include/mbgl/util/compression.hpp
index 93a3ddb8bc..cbce764683 100644
--- a/include/mbgl/util/compression.hpp
+++ b/include/mbgl/util/compression.hpp
@@ -5,8 +5,15 @@
namespace mbgl {
namespace util {
+// Compresses data with the deflate algorithm.
std::string compress(const std::string& raw);
+
+// Decompresses data that is in deflate format, optionally wrapped in a gzip container.
std::string decompress(const std::string& raw);
+// Returns true when there's a good chance that the string can be compressed.
+// In particular, it returns false when the data is an already compressed image format.
+bool isCompressible(const std::string& raw);
+
} // namespace util
} // namespace mbgl
diff --git a/include/mbgl/util/image.hpp b/include/mbgl/util/image.hpp
index 4887058f79..1cb3cca8c9 100644
--- a/include/mbgl/util/image.hpp
+++ b/include/mbgl/util/image.hpp
@@ -2,6 +2,7 @@
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/geometry.hpp>
+#include <mbgl/util/blob.hpp>
#include <mbgl/util/size.hpp>
#include <string>
@@ -170,8 +171,7 @@ using UnassociatedImage = Image<ImageAlphaMode::Unassociated>;
using PremultipliedImage = Image<ImageAlphaMode::Premultiplied>;
using AlphaImage = Image<ImageAlphaMode::Exclusive>;
-// TODO: don't use std::string for binary data.
-PremultipliedImage decodeImage(const std::string&);
-std::string encodePNG(const PremultipliedImage&);
+PremultipliedImage decodeImage(Blob);
+Blob encodePNG(const PremultipliedImage&);
} // namespace mbgl
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/UnknownContentEncodingException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/UnknownContentEncodingException.java
new file mode 100644
index 0000000000..4debc33ee4
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/UnknownContentEncodingException.java
@@ -0,0 +1,12 @@
+package com.mapbox.mapboxsdk.exceptions;
+
+/**
+ * An UnknownContentEncodingException is thrown by HTTPRequest
+ * when there aren't enough LatLng to create a bounds.
+ */
+public class UnknownContentEncodingException extends RuntimeException {
+
+ public UnknownContentEncodingException(String encoding) {
+ super("Unknown content encoding '" + encoding + "'");
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java
index caee493e6f..942b88f1fb 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java
@@ -9,6 +9,7 @@ import android.text.TextUtils;
import com.mapbox.mapboxsdk.BuildConfig;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
+import com.mapbox.mapboxsdk.exceptions.UnknownContentEncodingException;
import java.io.IOException;
import java.io.InterruptedIOException;
@@ -66,7 +67,7 @@ class HTTPRequest implements Callback {
private native void nativeOnFailure(int type, String message);
private native void nativeOnResponse(int code, String etag, String modified, String cacheControl, String expires,
- String retryAfter, String xRateLimitReset, byte[] body);
+ String retryAfter, String xRateLimitReset, byte[] body, boolean gzip);
private HTTPRequest(long nativePtr, String resourceUrl, String etag, String modified) {
mNativePtr = nativePtr;
@@ -93,6 +94,7 @@ class HTTPRequest implements Callback {
Request.Builder builder = new Request.Builder()
.url(resourceUrl)
.tag(resourceUrl.toLowerCase(MapboxConstants.MAPBOX_LOCALE))
+ .addHeader("Accept-Encoding", "gzip, deflate")
.addHeader("User-Agent", getUserAgent());
if (etag.length() > 0) {
builder = builder.addHeader("If-None-Match", etag);
@@ -149,6 +151,18 @@ class HTTPRequest implements Callback {
mLock.lock();
if (mNativePtr != 0) {
+ String encoding = response.header("Content-Encoding");
+ boolean compressed = false;
+ if (encoding != null) {
+ if (encoding.equals("gzip") || encoding.equals("deflate")) {
+ compressed = true;
+ } else if (!encoding.equals("identity")) {
+ mLock.unlock();
+ handleFailure(call, new UnknownContentEncodingException(encoding));
+ return;
+ }
+ }
+
nativeOnResponse(response.code(),
response.header("ETag"),
response.header("Last-Modified"),
@@ -156,7 +170,8 @@ class HTTPRequest implements Callback {
response.header("Expires"),
response.header("Retry-After"),
response.header("x-rate-limit-reset"),
- body);
+ body,
+ compressed);
}
mLock.unlock();
}
diff --git a/platform/android/src/asset_manager_file_source.cpp b/platform/android/src/asset_manager_file_source.cpp
index aa65e3ff48..404177ba95 100644
--- a/platform/android/src/asset_manager_file_source.cpp
+++ b/platform/android/src/asset_manager_file_source.cpp
@@ -23,8 +23,9 @@ public:
Response response;
if (AAsset* asset = AAssetManager_open(assetManager, path.c_str(), AASSET_MODE_BUFFER)) {
- response.data = std::make_shared<std::string>(
- reinterpret_cast<const char*>(AAsset_getBuffer(asset)), AAsset_getLength64(asset));
+ response.data = { { reinterpret_cast<const char*>(AAsset_getBuffer(asset)),
+ static_cast<size_t>(AAsset_getLength64(asset)) },
+ false };
AAsset_close(asset);
} else {
response.error = std::make_unique<Response::Error>(Response::Error::Reason::NotFound,
diff --git a/platform/android/src/http_file_source.cpp b/platform/android/src/http_file_source.cpp
index 8eb9416e9d..7602c1914e 100644
--- a/platform/android/src/http_file_source.cpp
+++ b/platform/android/src/http_file_source.cpp
@@ -30,7 +30,8 @@ public:
jni::String etag, jni::String modified,
jni::String cacheControl, jni::String expires,
jni::String retryAfter, jni::String xRateLimitReset,
- jni::Array<jni::jbyte> body);
+ jni::Array<jni::jbyte> body,
+ jni::jboolean compressed);
static jni::Class<HTTPRequest> javaClass;
jni::UniqueObject<HTTPRequest> javaRequest;
@@ -104,7 +105,8 @@ void HTTPRequest::onResponse(jni::JNIEnv& env, int code,
jni::String etag, jni::String modified,
jni::String cacheControl, jni::String expires,
jni::String jRetryAfter, jni::String jXRateLimitReset,
- jni::Array<jni::jbyte> body) {
+ jni::Array<jni::jbyte> body,
+ jni::jboolean compressed) {
using Error = Response::Error;
@@ -128,11 +130,11 @@ void HTTPRequest::onResponse(jni::JNIEnv& env, int code,
if (code == 200) {
if (body) {
- auto data = std::make_shared<std::string>(body.Length(env), char());
- jni::GetArrayRegion(env, *body, 0, data->size(), reinterpret_cast<jbyte*>(&(*data)[0]));
- response.data = data;
+ std::string data(static_cast<size_t>(body.Length(env)), char());
+ jni::GetArrayRegion(env, *body, 0, data.size(), reinterpret_cast<jbyte*>(&data[0]));
+ response.data = Blob{ std::move(data), static_cast<bool>(compressed) };
} else {
- response.data = std::make_shared<std::string>();
+ response.data = {};
}
} else if (code == 204 || (code == 404 && resource.kind == Resource::Kind::Tile)) {
response.noContent = true;
diff --git a/platform/android/src/image.cpp b/platform/android/src/image.cpp
index 2a33944b18..dd98a3a6c8 100644
--- a/platform/android/src/image.cpp
+++ b/platform/android/src/image.cpp
@@ -8,14 +8,16 @@
namespace mbgl {
-PremultipliedImage decodeImage(const std::string& string) {
+PremultipliedImage decodeImage(Blob blob) {
auto env{ android::AttachEnv() };
- auto array = jni::Array<jni::jbyte>::New(*env, string.size());
- jni::SetArrayRegion(*env, *array, 0, string.size(),
- reinterpret_cast<const signed char*>(string.data()));
+ const auto string = blob.uncompressedData();
- auto bitmap = android::BitmapFactory::DecodeByteArray(*env, array, 0, string.size());
+ auto array = jni::Array<jni::jbyte>::New(*env, string->size());
+ jni::SetArrayRegion(*env, *array, 0, string->size(),
+ reinterpret_cast<const signed char*>(string->data()));
+
+ auto bitmap = android::BitmapFactory::DecodeByteArray(*env, array, 0, string->size());
return android::Bitmap::GetImage(*env, bitmap);
}
diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp
index 67fc132204..c52aad6405 100755
--- a/platform/android/src/native_map_view.cpp
+++ b/platform/android/src/native_map_view.cpp
@@ -188,11 +188,11 @@ void NativeMapView::setStyleUrl(jni::JNIEnv& env, jni::String url) {
}
jni::String NativeMapView::getStyleJson(jni::JNIEnv& env) {
- return jni::Make<jni::String>(env, map->getStyle().getJSON());
+ return jni::Make<jni::String>(env, *map->getStyle().getJSON().uncompressedData());
}
void NativeMapView::setStyleJson(jni::JNIEnv& env, jni::String json) {
- map->getStyle().loadJSON(jni::Make<std::string>(env, json));
+ map->getStyle().loadJSON(Blob{ jni::Make<std::string>(env, json), false });
}
void NativeMapView::setLatLngBounds(jni::JNIEnv& env, jni::Object<mbgl::android::LatLngBounds> jBounds) {
diff --git a/platform/darwin/src/http_file_source.mm b/platform/darwin/src/http_file_source.mm
index 4a16ad82fb..6840740c44 100644
--- a/platform/darwin/src/http_file_source.mm
+++ b/platform/darwin/src/http_file_source.mm
@@ -232,8 +232,7 @@ std::unique_ptr<AsyncRequest> HTTPFileSource::request(const Resource& resource,
if (error) {
if (data) {
- response.data =
- std::make_shared<std::string>((const char*)[data bytes], [data length]);
+ response.data = Blob{ { (const char*)[data bytes], [data length] }, false };
}
switch ([error code]) {
@@ -287,7 +286,7 @@ std::unique_ptr<AsyncRequest> HTTPFileSource::request(const Resource& resource,
}
if (responseCode == 200) {
- response.data = std::make_shared<std::string>((const char *)[data bytes], [data length]);
+ response.data = { { (const char *)[data bytes], [data length] }, false };
} else if (responseCode == 204 || (responseCode == 404 && resource.kind == Resource::Kind::Tile)) {
response.noContent = true;
} else if (responseCode == 304) {
diff --git a/platform/darwin/src/image.mm b/platform/darwin/src/image.mm
index 3a5adcca0a..f08fb9a25f 100644
--- a/platform/darwin/src/image.mm
+++ b/platform/darwin/src/image.mm
@@ -71,9 +71,10 @@ mbgl::PremultipliedImage MGLPremultipliedImageFromCGImage(CGImageRef src) {
namespace mbgl {
-PremultipliedImage decodeImage(const std::string& source) {
+PremultipliedImage decodeImage(Blob blob) {
+ const auto source = blob.uncompressedData();
CFDataHandle data(CFDataCreateWithBytesNoCopy(
- kCFAllocatorDefault, reinterpret_cast<const unsigned char*>(source.data()), source.size(),
+ kCFAllocatorDefault, reinterpret_cast<const unsigned char*>(source->data()), source->size(),
kCFAllocatorNull));
if (!data) {
throw std::runtime_error("CFDataCreateWithBytesNoCopy failed");
diff --git a/platform/darwin/test/MGLOfflineStorageTests.mm b/platform/darwin/test/MGLOfflineStorageTests.mm
index 28c6633028..f0d54f81b4 100644
--- a/platform/darwin/test/MGLOfflineStorageTests.mm
+++ b/platform/darwin/test/MGLOfflineStorageTests.mm
@@ -182,8 +182,8 @@
req = fs->request(resource, [&](mbgl::Response res) {
req.reset();
XCTAssertFalse(res.error.get(), @"Request should not return an error");
- XCTAssertTrue(res.data.get(), @"Request should return data");
- XCTAssertEqual("{\"api\":\"mapbox\"}", *res.data, @"Request did not return expected data");
+ XCTAssertTrue(res.data, @"Request should return data");
+ XCTAssertEqual("{\"api\":\"mapbox\"}", *res.data.uncompressedData(), @"Request did not return expected data");
CFRunLoopStop(CFRunLoopGetCurrent());
});
diff --git a/platform/default/asset_file_source.cpp b/platform/default/asset_file_source.cpp
index 3063bf88a0..0b57a6dcef 100644
--- a/platform/default/asset_file_source.cpp
+++ b/platform/default/asset_file_source.cpp
@@ -44,12 +44,10 @@ public:
} else if (result == -1 && errno == ENOENT) {
response.error = std::make_unique<Response::Error>(Response::Error::Reason::NotFound);
} else {
- try {
- response.data = std::make_shared<std::string>(util::read_file(path));
- } catch (...) {
+ response.data = util::readFile(path);
+ if (!response.data) {
response.error = std::make_unique<Response::Error>(
- Response::Error::Reason::Other,
- util::toString(std::current_exception()));
+ Response::Error::Reason::Other, "Cannot read file " + path);
}
}
diff --git a/platform/default/default_file_source.cpp b/platform/default/default_file_source.cpp
index cb602995a4..5dcd28facd 100644
--- a/platform/default/default_file_source.cpp
+++ b/platform/default/default_file_source.cpp
@@ -151,8 +151,23 @@ public:
// Get from the online file source
if (resource.hasLoadingMethod(Resource::LoadingMethod::Network)) {
+ // Always solicit a compressed response so that we can insert it into the database
+ // while still compressed to save on CPU time.
+ const auto compression = resource.compression;
+ resource.compression = Resource::Compression::PreferCompressed;
tasks[req] = onlineFileSource.request(resource, [=] (Response onlineResponse) mutable {
this->offlineDatabase->put(resource, onlineResponse);
+ // If the original request expects an uncompressed response, uncompress before
+ // handing it back.
+ if (onlineResponse.data && onlineResponse.data.isCompressed() &&
+ compression == Resource::Compression::Uncompressed) {
+ try {
+ onlineResponse.data.uncompress();
+ } catch (std::exception& ex) {
+ onlineResponse.error = std::make_unique<Response::Error>(
+ Response::Error::Reason::Other, ex.what());
+ }
+ }
callback(onlineResponse);
});
}
diff --git a/platform/default/http_file_source.cpp b/platform/default/http_file_source.cpp
index a9c442c2de..1a0ae577b8 100644
--- a/platform/default/http_file_source.cpp
+++ b/platform/default/http_file_source.cpp
@@ -371,9 +371,9 @@ void HTTPRequest::handleResult(CURLcode code) {
if (responseCode == 200) {
if (data) {
- response->data = std::move(data);
+ response->data = Blob{ std::move(data), false };
} else {
- response->data = std::make_shared<std::string>();
+ response->data = Blob{ "", false };
}
} else if (responseCode == 204 || (responseCode == 404 && resource.kind == Resource::Kind::Tile)) {
response->noContent = true;
diff --git a/platform/default/image.cpp b/platform/default/image.cpp
index 447c6bcd66..4fde1898c6 100644
--- a/platform/default/image.cpp
+++ b/platform/default/image.cpp
@@ -11,9 +11,10 @@ PremultipliedImage decodeWebP(const uint8_t*, size_t);
PremultipliedImage decodePNG(const uint8_t*, size_t);
PremultipliedImage decodeJPEG(const uint8_t*, size_t);
-PremultipliedImage decodeImage(const std::string& string) {
- const auto* data = reinterpret_cast<const uint8_t*>(string.data());
- const size_t size = string.size();
+PremultipliedImage decodeImage(Blob blob) {
+ const auto uncompressed = blob.uncompressedData();
+ const auto* data = reinterpret_cast<const uint8_t*>(uncompressed->data());
+ const size_t size = uncompressed->size();
#if !defined(__ANDROID__) && !defined(__APPLE__)
if (size >= 12) {
diff --git a/platform/default/local_file_source.cpp b/platform/default/local_file_source.cpp
index 0635e86d80..9a8f5ae51b 100644
--- a/platform/default/local_file_source.cpp
+++ b/platform/default/local_file_source.cpp
@@ -46,12 +46,10 @@ public:
} else if (result == -1 && errno == ENOENT) {
response.error = std::make_unique<Response::Error>(Response::Error::Reason::NotFound);
} else {
- try {
- response.data = std::make_shared<std::string>(util::read_file(path));
- } catch (...) {
+ response.data = util::readFile(path);
+ if (!response.data) {
response.error = std::make_unique<Response::Error>(
- Response::Error::Reason::Other,
- util::toString(std::current_exception()));
+ Response::Error::Reason::Other, "Cannot read file " + path);
}
}
diff --git a/platform/default/mbgl/storage/offline_database.cpp b/platform/default/mbgl/storage/offline_database.cpp
index 65c2097182..d7022f1c80 100644
--- a/platform/default/mbgl/storage/offline_database.cpp
+++ b/platform/default/mbgl/storage/offline_database.cpp
@@ -1,10 +1,10 @@
#include <mbgl/storage/offline_database.hpp>
#include <mbgl/storage/response.hpp>
-#include <mbgl/util/compression.hpp>
#include <mbgl/util/io.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/util/chrono.hpp>
#include <mbgl/util/logging.hpp>
+#include <mbgl/util/compression.hpp>
#include "sqlite3.hpp"
@@ -153,7 +153,7 @@ optional<Response> OfflineDatabase::get(const Resource& resource) {
optional<std::pair<Response, uint64_t>> OfflineDatabase::getInternal(const Resource& resource) {
if (resource.kind == Resource::Kind::Tile) {
assert(resource.tileData);
- return getTile(*resource.tileData);
+ return getTile(resource);
} else {
return getResource(resource);
}
@@ -177,14 +177,31 @@ std::pair<bool, uint64_t> OfflineDatabase::putInternal(const Resource& resource,
return { false, 0 };
}
- std::string compressedData;
+ std::shared_ptr<const std::string> data;
bool compressed = false;
uint64_t size = 0;
if (response.data) {
- compressedData = util::compress(*response.data);
- compressed = compressedData.size() < response.data->size();
- size = compressed ? compressedData.size() : response.data->size();
+ if (response.data.isCompressed()) {
+ // The response is already compressed; don't try to compare it against the uncompressed size.
+ compressed = true;
+ data = response.data.compressedData();
+ } else {
+ data = response.data.uncompressedData();
+
+ // Only try to compress the data when we have a good chance that the data can actually
+ // be considerably compressed.
+ if (util::isCompressible(*data)) {
+ const auto compressedData = response.data.compressedData();
+ if (compressedData->size() < data->size()) {
+ compressed = true;
+ data = compressedData;
+ }
+ }
+ }
+ size = data->size();
+ } else {
+ data = std::make_shared<const std::string>();
}
if (evict_ && !evict(size)) {
@@ -196,13 +213,9 @@ std::pair<bool, uint64_t> OfflineDatabase::putInternal(const Resource& resource,
if (resource.kind == Resource::Kind::Tile) {
assert(resource.tileData);
- inserted = putTile(*resource.tileData, response,
- compressed ? compressedData : response.data ? *response.data : "",
- compressed);
+ inserted = putTile(*resource.tileData, response, *data, compressed);
} else {
- inserted = putResource(resource, response,
- compressed ? compressedData : response.data ? *response.data : "",
- compressed);
+ inserted = putResource(resource, response, *data, compressed);
}
return { inserted, size };
@@ -243,12 +256,20 @@ optional<std::pair<Response, uint64_t>> OfflineDatabase::getResource(const Resou
optional<std::string> data = stmt->get<optional<std::string>>(4);
if (!data) {
response.noContent = true;
- } else if (stmt->get<bool>(5)) {
- response.data = std::make_shared<std::string>(util::decompress(*data));
- size = data->length();
} else {
- response.data = std::make_shared<std::string>(*data);
+ response.data = { std::move(*data), stmt->get<bool>(5) };
size = data->length();
+
+ // Make sure the data is decompressed when the user explicitly requested uncompressed data.
+ if (response.data.isCompressed() &&
+ resource.compression == Resource::Compression::Uncompressed) {
+ try {
+ response.data.uncompress();
+ } catch (std::exception& ex) {
+ response.error =
+ std::make_unique<Response::Error>(Response::Error::Reason::Other, ex.what());
+ }
+ }
}
return std::make_pair(response, size);
@@ -359,7 +380,9 @@ bool OfflineDatabase::putResource(const Resource& resource,
return true;
}
-optional<std::pair<Response, uint64_t>> OfflineDatabase::getTile(const Resource::TileData& tile) {
+optional<std::pair<Response, uint64_t>> OfflineDatabase::getTile(const Resource& resource) {
+ const auto& tile = *resource.tileData;
+
// clang-format off
Statement accessedStmt = getStatement(
"UPDATE tiles "
@@ -412,12 +435,20 @@ optional<std::pair<Response, uint64_t>> OfflineDatabase::getTile(const Resource:
optional<std::string> data = stmt->get<optional<std::string>>(4);
if (!data) {
response.noContent = true;
- } else if (stmt->get<bool>(5)) {
- response.data = std::make_shared<std::string>(util::decompress(*data));
- size = data->length();
} else {
- response.data = std::make_shared<std::string>(*data);
+ response.data = { std::move(*data), stmt->get<bool>(5) };
size = data->length();
+
+ // Make sure the data is decompressed when the user explicitly requested uncompressed data.
+ if (response.data.isCompressed() &&
+ resource.compression == Resource::Compression::Uncompressed) {
+ try {
+ response.data.uncompress();
+ } catch (std::exception& ex) {
+ response.error =
+ std::make_unique<Response::Error>(Response::Error::Reason::Other, ex.what());
+ }
+ }
}
return std::make_pair(response, size);
diff --git a/platform/default/mbgl/storage/offline_database.hpp b/platform/default/mbgl/storage/offline_database.hpp
index 91b544a9e0..fba1a3c230 100644
--- a/platform/default/mbgl/storage/offline_database.hpp
+++ b/platform/default/mbgl/storage/offline_database.hpp
@@ -81,7 +81,7 @@ private:
Statement getStatement(const char *);
- optional<std::pair<Response, uint64_t>> getTile(const Resource::TileData&);
+ optional<std::pair<Response, uint64_t>> getTile(const Resource&);
optional<int64_t> hasTile(const Resource::TileData&);
bool putTile(const Resource::TileData&, const Response&,
const std::string&, bool compressed);
diff --git a/platform/default/mbgl/storage/offline_download.cpp b/platform/default/mbgl/storage/offline_download.cpp
index ba504c1f9b..d8fe8c646b 100644
--- a/platform/default/mbgl/storage/offline_download.cpp
+++ b/platform/default/mbgl/storage/offline_download.cpp
@@ -71,7 +71,7 @@ OfflineRegionStatus OfflineDownload::getStatus() const {
}
style::Parser parser;
- parser.parse(*styleResponse->data);
+ parser.parse(*styleResponse->data.uncompressedData());
result.requiredResourceCountIsPrecise = true;
@@ -88,7 +88,8 @@ OfflineRegionStatus OfflineDownload::getStatus() const {
optional<Response> sourceResponse = offlineDatabase.get(Resource::source(url));
if (sourceResponse) {
style::conversion::Error error;
- optional<Tileset> tileset = style::conversion::convertJSON<Tileset>(*sourceResponse->data, error);
+ optional<Tileset> tileset = style::conversion::convertJSON<Tileset>(
+ *sourceResponse->data.uncompressedData(), error);
if (tileset) {
result.requiredResourceCount +=
definition.tileCount(type, tileSize, (*tileset).zoomRange);
@@ -160,7 +161,7 @@ void OfflineDownload::activateDownload() {
status.requiredResourceCountIsPrecise = true;
style::Parser parser;
- parser.parse(*styleResponse.data);
+ parser.parse(*styleResponse.data.uncompressedData());
for (const auto& source : parser.sources) {
SourceType type = source->getType();
@@ -176,7 +177,8 @@ void OfflineDownload::activateDownload() {
ensureResource(Resource::source(url), [=](Response sourceResponse) {
style::conversion::Error error;
- optional<Tileset> tileset = style::conversion::convertJSON<Tileset>(*sourceResponse.data, error);
+ optional<Tileset> tileset = style::conversion::convertJSON<Tileset>(
+ *sourceResponse.data.uncompressedData(), error);
if (tileset) {
util::mapbox::canonicalizeTileset(*tileset, url, type, tileSize);
queueTiles(type, tileSize, *tileset);
@@ -236,14 +238,18 @@ void OfflineDownload::activateDownload() {
if (!parser.glyphURL.empty()) {
for (const auto& fontStack : parser.fontStacks()) {
for (char16_t i = 0; i < GLYPH_RANGES_PER_FONT_STACK; i++) {
- queueResource(Resource::glyphs(parser.glyphURL, fontStack, getGlyphRange(i * GLYPHS_PER_GLYPH_RANGE)));
+ auto resource = Resource::glyphs(parser.glyphURL, fontStack, getGlyphRange(i * GLYPHS_PER_GLYPH_RANGE));
+ resource.compression = Resource::Compression::PreferCompressed;
+ queueResource(resource);
}
}
}
if (!parser.spriteURL.empty()) {
queueResource(Resource::spriteImage(parser.spriteURL, definition.pixelRatio));
- queueResource(Resource::spriteJSON(parser.spriteURL, definition.pixelRatio));
+ auto spriteJSON = Resource::spriteJSON(parser.spriteURL, definition.pixelRatio);
+ spriteJSON.compression = Resource::Compression::PreferCompressed;
+ queueResource(spriteJSON);
}
continueDownload();
diff --git a/platform/default/online_file_source.cpp b/platform/default/online_file_source.cpp
index d685109b95..fe77df8c02 100644
--- a/platform/default/online_file_source.cpp
+++ b/platform/default/online_file_source.cpp
@@ -374,6 +374,16 @@ void OnlineFileRequest::completed(Response response) {
failedRequestReason = Response::Error::Reason::Success;
}
+ // Make sure the data is decompressed when the user explicitly requested uncompressed data.
+ if (response.data && response.data.isCompressed() &&
+ resource.compression == Resource::Compression::Uncompressed) {
+ try {
+ response.data.uncompress();
+ } catch (std::exception& ex) {
+ response.error = std::make_unique<Response::Error>(Response::Error::Reason::Other, ex.what());
+ }
+ }
+
schedule(response.expires);
// Calling the callback may result in `this` being deleted. It needs to be done last,
diff --git a/platform/default/png_writer.cpp b/platform/default/png_writer.cpp
index 9ef9052158..d3297b8ebf 100644
--- a/platform/default/png_writer.cpp
+++ b/platform/default/png_writer.cpp
@@ -38,7 +38,7 @@ void addChunk(std::string& png, const char* type, const char* data = "", const u
namespace mbgl {
// Encode PNGs without libpng.
-std::string encodePNG(const PremultipliedImage& pre) {
+Blob encodePNG(const PremultipliedImage& pre) {
// Make copy of the image so that we can unpremultiply it.
const auto src = util::unpremultiply(pre.clone());
@@ -74,7 +74,7 @@ std::string encodePNG(const PremultipliedImage& pre) {
addChunk(png, "IHDR", ihdr, 13);
addChunk(png, "IDAT", idat.data(), static_cast<uint32_t>(idat.size()));
addChunk(png, "IEND");
- return png;
+ return { std::move(png), false };
}
} // namespace mbgl
diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj
index 07fae5945c..c29c2ec89f 100644
--- a/platform/ios/ios.xcodeproj/project.pbxproj
+++ b/platform/ios/ios.xcodeproj/project.pbxproj
@@ -211,6 +211,7 @@
40F887701D7A1E58008ECB67 /* MGLShapeSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 40F8876F1D7A1DB8008ECB67 /* MGLShapeSource_Private.h */; };
40F887711D7A1E59008ECB67 /* MGLShapeSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 40F8876F1D7A1DB8008ECB67 /* MGLShapeSource_Private.h */; };
40FDA76B1CCAAA6800442548 /* MBXAnnotationView.m in Sources */ = {isa = PBXBuildFile; fileRef = 40FDA76A1CCAAA6800442548 /* MBXAnnotationView.m */; };
+ 55434256203C7530002624EB /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 55434255203C7530002624EB /* libz.tbd */; };
5549A0381EF1D86B00073113 /* libmbgl-core.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5549A0371EF1D86B00073113 /* libmbgl-core.a */; };
5549A0391EF2877100073113 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 554180411D2E97DE00012372 /* OpenGLES.framework */; };
5549A03A1EF2877500073113 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 554180411D2E97DE00012372 /* OpenGLES.framework */; };
@@ -794,6 +795,7 @@
40FDA7691CCAAA6800442548 /* MBXAnnotationView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MBXAnnotationView.h; sourceTree = "<group>"; };
40FDA76A1CCAAA6800442548 /* MBXAnnotationView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MBXAnnotationView.m; sourceTree = "<group>"; };
554180411D2E97DE00012372 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; };
+ 55434255203C7530002624EB /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
5549A0371EF1D86B00073113 /* libmbgl-core.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libmbgl-core.a"; path = "../../build/ios/Debug-iphonesimulator/libmbgl-core.a"; sourceTree = "<group>"; };
556660C91E1BF3A900E2C41B /* MGLFoundation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLFoundation.h; sourceTree = "<group>"; };
556660D71E1D085500E2C41B /* MGLVersionNumber.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = MGLVersionNumber.m; path = ../../darwin/test/MGLVersionNumber.m; sourceTree = "<group>"; };
@@ -1145,6 +1147,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ 55434256203C7530002624EB /* libz.tbd in Frameworks */,
5549A0381EF1D86B00073113 /* libmbgl-core.a in Frameworks */,
DA2E88561CC036F400F24E7B /* Mapbox.framework in Frameworks */,
);
@@ -1477,6 +1480,7 @@
DA1DC9921CB6DF24006E619F /* Frameworks */ = {
isa = PBXGroup;
children = (
+ 55434255203C7530002624EB /* libz.tbd */,
55D120AD1F791018004B6D81 /* libmbgl-loop-darwin.a */,
55D120AB1F791015004B6D81 /* libmbgl-filesource.a */,
55D120A91F79100C004B6D81 /* libmbgl-filesource.a */,
diff --git a/platform/macos/macos.xcodeproj/project.pbxproj b/platform/macos/macos.xcodeproj/project.pbxproj
index 4327670911..58f29ed2a3 100644
--- a/platform/macos/macos.xcodeproj/project.pbxproj
+++ b/platform/macos/macos.xcodeproj/project.pbxproj
@@ -80,6 +80,7 @@
52B5D17F1E5E26DF00BBCB48 /* libmbgl-loop-darwin.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5548BE7B1D0ACBBD005DDE81 /* libmbgl-loop-darwin.a */; };
52B5D1801E5E26DF00BBCB48 /* libmbgl-loop-darwin.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5548BE7B1D0ACBBD005DDE81 /* libmbgl-loop-darwin.a */; };
5548BE781D09E718005DDE81 /* libmbgl-core.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAE6C3451CC31D1200DB3429 /* libmbgl-core.a */; };
+ 555CF3EC203DA46F004C828F /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 55D9B4B01D005D3900C1CCE2 /* libz.tbd */; };
556660C61E1BEA0100E2C41B /* MGLFoundation.h in Headers */ = {isa = PBXBuildFile; fileRef = 556660C51E1BEA0100E2C41B /* MGLFoundation.h */; settings = {ATTRIBUTES = (Public, ); }; };
556660D61E1D07E400E2C41B /* MGLVersionNumber.m in Sources */ = {isa = PBXBuildFile; fileRef = 556660D51E1D07E400E2C41B /* MGLVersionNumber.m */; };
558DE7A61E56161C00C7916D /* MGLFoundation_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 558DE7A41E56161C00C7916D /* MGLFoundation_Private.h */; };
@@ -659,6 +660,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ 555CF3EC203DA46F004C828F /* libz.tbd in Frameworks */,
DAE0DD7A1D5F015A005A6BB1 /* libmbgl-core.a in Frameworks */,
55D120A51F790A0C004B6D81 /* libmbgl-filesource.a in Frameworks */,
DAE6C3321CC30DB200DB3429 /* Mapbox.framework in Frameworks */,
diff --git a/platform/node/src/node_map.cpp b/platform/node/src/node_map.cpp
index ac14df0228..a4f6f6a9de 100644
--- a/platform/node/src/node_map.cpp
+++ b/platform/node/src/node_map.cpp
@@ -214,8 +214,8 @@ void NodeMap::Load(const Nan::FunctionCallbackInfo<v8::Value>& info) {
}
try {
- nodeMap->map->getStyle().loadJSON(style);
- } catch (const std::exception &ex) {
+ nodeMap->map->getStyle().loadJSON(mbgl::Blob{ std::move(style), false });
+ } catch (const std::exception& ex) {
return Nan::ThrowError(ex.what());
}
diff --git a/platform/node/src/node_request.cpp b/platform/node/src/node_request.cpp
index de16710f78..7b2b57fd1f 100644
--- a/platform/node/src/node_request.cpp
+++ b/platform/node/src/node_request.cpp
@@ -99,10 +99,8 @@ void NodeRequest::HandleCallback(const Nan::FunctionCallbackInfo<v8::Value>& inf
if (Nan::Has(res, Nan::New("data").ToLocalChecked()).FromJust()) {
auto data = Nan::Get(res, Nan::New("data").ToLocalChecked()).ToLocalChecked();
if (node::Buffer::HasInstance(data)) {
- response.data = std::make_shared<std::string>(
- node::Buffer::Data(data),
- node::Buffer::Length(data)
- );
+ response.data = { std::string{ node::Buffer::Data(data), node::Buffer::Length(data), },
+ false };
} else {
return Nan::ThrowTypeError("Response data must be a Buffer");
}
diff --git a/platform/qt/src/http_request.cpp b/platform/qt/src/http_request.cpp
index ea3f388bd5..4e2143ba8e 100644
--- a/platform/qt/src/http_request.cpp
+++ b/platform/qt/src/http_request.cpp
@@ -99,9 +99,9 @@ void HTTPRequest::handleNetworkReply(QNetworkReply *reply, const QByteArray& dat
switch(responseCode) {
case 200: {
if (data.isEmpty()) {
- response.data = std::make_shared<std::string>();
+ response.data = Blob{ "", false };
} else {
- response.data = std::make_shared<std::string>(data.constData(), data.size());
+ response.data = Blob{ std::string{ data.constData(), static_cast<size_t>(data.size()) }, false };
}
break;
}
diff --git a/platform/qt/src/qmapboxgl.cpp b/platform/qt/src/qmapboxgl.cpp
index 414b65255c..e054d88489 100644
--- a/platform/qt/src/qmapboxgl.cpp
+++ b/platform/qt/src/qmapboxgl.cpp
@@ -585,12 +585,12 @@ void QMapboxGL::cycleDebugOptions()
*/
QString QMapboxGL::styleJson() const
{
- return QString::fromStdString(d_ptr->mapObj->getStyle().getJSON());
+ return QString::fromStdString(*d_ptr->mapObj->getStyle().getJSON().uncompressedData());
}
void QMapboxGL::setStyleJson(const QString &style)
{
- d_ptr->mapObj->getStyle().loadJSON(style.toStdString());
+ d_ptr->mapObj->getStyle().loadJSON(mbgl::Blob{ style.toStdString(), false });
}
/*!
diff --git a/platform/qt/src/qt_image.cpp b/platform/qt/src/qt_image.cpp
index a5c92514c1..ff45b02ef1 100644
--- a/platform/qt/src/qt_image.cpp
+++ b/platform/qt/src/qt_image.cpp
@@ -6,7 +6,7 @@
namespace mbgl {
-std::string encodePNG(const PremultipliedImage& pre) {
+Blob encodePNG(const PremultipliedImage& pre) {
QImage image(pre.data.get(), pre.size.width, pre.size.height,
QImage::Format_ARGB32_Premultiplied);
@@ -16,7 +16,7 @@ std::string encodePNG(const PremultipliedImage& pre) {
buffer.open(QIODevice::WriteOnly);
image.rgbSwapped().save(&buffer, "PNG");
- return std::string(array.constData(), array.size());
+ return { std::string(array.constData(), array.size()), false };
}
#if !defined(QT_IMAGE_DECODERS)
@@ -24,9 +24,10 @@ PremultipliedImage decodeJPEG(const uint8_t*, size_t);
PremultipliedImage decodeWebP(const uint8_t*, size_t);
#endif
-PremultipliedImage decodeImage(const std::string& string) {
- const uint8_t* data = reinterpret_cast<const uint8_t*>(string.data());
- const size_t size = string.size();
+PremultipliedImage decodeImage(Blob blob) {
+ const auto uncompressed = blob.uncompressedData();
+ const uint8_t* data = reinterpret_cast<const uint8_t*>(uncompressed->data());
+ const size_t size = uncompressed->size();
#if !defined(QT_IMAGE_DECODERS)
if (size >= 12) {
diff --git a/platform/qt/test/qmapboxgl.test.cpp b/platform/qt/test/qmapboxgl.test.cpp
index 2a56b346a3..607cdd6ba9 100644
--- a/platform/qt/test/qmapboxgl.test.cpp
+++ b/platform/qt/test/qmapboxgl.test.cpp
@@ -47,7 +47,7 @@ void QMapboxGLTest::onNeedsRendering() {
TEST_F(QMapboxGLTest, TEST_DISABLED_ON_CI(styleJson)) {
QString json = QString::fromStdString(
- mbgl::util::read_file("test/fixtures/resources/style_vector.json"));
+ *mbgl::util::readFile("test/fixtures/resources/style_vector.json").uncompressedData());
map.setStyleJson(json);
ASSERT_EQ(map.styleJson(), json);
diff --git a/src/mbgl/gl/program.hpp b/src/mbgl/gl/program.hpp
index 3b54ec194a..64e3a355d6 100644
--- a/src/mbgl/gl/program.hpp
+++ b/src/mbgl/gl/program.hpp
@@ -62,7 +62,7 @@ public:
try {
if (auto cachedBinaryProgram = util::readFile(*cachePath)) {
- const BinaryProgram binaryProgram(std::move(*cachedBinaryProgram));
+ const BinaryProgram binaryProgram(cachedBinaryProgram);
if (binaryProgram.identifier() == identifier) {
return Program { context, binaryProgram };
} else {
@@ -82,7 +82,7 @@ public:
try {
if (const auto binaryProgram =
result.template get<BinaryProgram>(context, identifier)) {
- util::write_file(*cachePath, binaryProgram->serialize());
+ util::writeFile(*cachePath, binaryProgram->serialize());
Log::Warning(Event::OpenGL, "Caching program in: %s", (*cachePath).c_str());
}
} catch (std::runtime_error& error) {
diff --git a/src/mbgl/programs/binary_program.cpp b/src/mbgl/programs/binary_program.cpp
index da629194b4..e5943bb5db 100644
--- a/src/mbgl/programs/binary_program.cpp
+++ b/src/mbgl/programs/binary_program.cpp
@@ -32,9 +32,10 @@ static std::pair<const std::string, Binding> parseBinding(protozero::pbf_reader&
namespace mbgl {
-BinaryProgram::BinaryProgram(std::string&& data) {
+BinaryProgram::BinaryProgram(Blob blob) {
+ const auto data = blob.uncompressedData();
bool hasFormat = false, hasCode = false;
- protozero::pbf_reader pbf(data);
+ protozero::pbf_reader pbf(*data);
while (pbf.next()) {
switch (pbf.tag()) {
case 1: // format
@@ -76,7 +77,7 @@ BinaryProgram::BinaryProgram(
uniforms(std::move(uniforms_)) {
}
-std::string BinaryProgram::serialize() const {
+Blob BinaryProgram::serialize() const {
std::string data;
data.reserve(32 + binaryCode.size() + uniforms.size() * 32 + attributes.size() * 32);
protozero::pbf_writer pbf(data);
@@ -95,7 +96,7 @@ std::string BinaryProgram::serialize() const {
if (!binaryIdentifier.empty()) {
pbf.add_string(5 /* identifier */, binaryIdentifier);
}
- return data;
+ return { std::move(data), false };
}
optional<gl::AttributeLocation> BinaryProgram::attributeLocation(const std::string& name) const {
diff --git a/src/mbgl/programs/binary_program.hpp b/src/mbgl/programs/binary_program.hpp
index 8690f3fd6f..2d3ea45aa6 100644
--- a/src/mbgl/programs/binary_program.hpp
+++ b/src/mbgl/programs/binary_program.hpp
@@ -1,6 +1,7 @@
#pragma once
#include <mbgl/gl/types.hpp>
+#include <mbgl/util/blob.hpp>
#include <mbgl/util/optional.hpp>
#include <string>
@@ -11,7 +12,7 @@ namespace mbgl {
class BinaryProgram {
public:
// Initialize a BinaryProgram object from a serialized represenation.
- BinaryProgram(std::string&& data);
+ BinaryProgram(Blob data);
BinaryProgram(gl::BinaryProgramFormat,
std::string&& binaryCode,
@@ -19,7 +20,7 @@ public:
std::vector<std::pair<const std::string, gl::AttributeLocation>>&&,
std::vector<std::pair<const std::string, gl::UniformLocation>>&&);
- std::string serialize() const;
+ Blob serialize() const;
gl::BinaryProgramFormat format() const {
return binaryFormat;
diff --git a/src/mbgl/sprite/sprite_loader.cpp b/src/mbgl/sprite/sprite_loader.cpp
index 93d6dfd9ae..3bc8add160 100644
--- a/src/mbgl/sprite/sprite_loader.cpp
+++ b/src/mbgl/sprite/sprite_loader.cpp
@@ -25,8 +25,8 @@ struct SpriteLoader::Loader {
worker(scheduler, ActorRef<SpriteLoader>(imageManager, mailbox)) {
}
- std::shared_ptr<const std::string> image;
- std::shared_ptr<const std::string> json;
+ Blob image;
+ Blob json;
std::unique_ptr<AsyncRequest> jsonRequest;
std::unique_ptr<AsyncRequest> spriteRequest;
std::shared_ptr<Mailbox> mailbox;
@@ -55,7 +55,7 @@ void SpriteLoader::load(const std::string& url, Scheduler& scheduler, FileSource
} else if (res.notModified) {
return;
} else if (res.noContent) {
- loader->json = std::make_shared<const std::string>();
+ loader->json = {};
emitSpriteLoadedIfComplete();
} else {
// Only trigger a sprite loaded event we got new data.
@@ -70,7 +70,7 @@ void SpriteLoader::load(const std::string& url, Scheduler& scheduler, FileSource
} else if (res.notModified) {
return;
} else if (res.noContent) {
- loader->image = std::make_shared<const std::string>();
+ loader->image = {};
emitSpriteLoadedIfComplete();
} else {
loader->image = res.data;
diff --git a/src/mbgl/sprite/sprite_loader_worker.cpp b/src/mbgl/sprite/sprite_loader_worker.cpp
index 4bded33d53..a2e3f331e9 100644
--- a/src/mbgl/sprite/sprite_loader_worker.cpp
+++ b/src/mbgl/sprite/sprite_loader_worker.cpp
@@ -8,8 +8,7 @@ SpriteLoaderWorker::SpriteLoaderWorker(ActorRef<SpriteLoaderWorker>, ActorRef<Sp
: parent(std::move(parent_)) {
}
-void SpriteLoaderWorker::parse(std::shared_ptr<const std::string> image,
- std::shared_ptr<const std::string> json) {
+void SpriteLoaderWorker::parse(Blob image, Blob json) {
try {
if (!image) {
// This shouldn't happen, since we always invoke it with a non-empty pointer.
@@ -20,7 +19,7 @@ void SpriteLoaderWorker::parse(std::shared_ptr<const std::string> image,
throw std::runtime_error("missing sprite metadata");
}
- parent.invoke(&SpriteLoader::onParsed, parseSprite(*image, *json));
+ parent.invoke(&SpriteLoader::onParsed, parseSprite(std::move(image), std::move(json)));
} catch (...) {
parent.invoke(&SpriteLoader::onError, std::current_exception());
}
diff --git a/src/mbgl/sprite/sprite_loader_worker.hpp b/src/mbgl/sprite/sprite_loader_worker.hpp
index d61e07d14f..4f2e38be29 100644
--- a/src/mbgl/sprite/sprite_loader_worker.hpp
+++ b/src/mbgl/sprite/sprite_loader_worker.hpp
@@ -2,6 +2,7 @@
#include <mbgl/actor/actor_ref.hpp>
#include <mbgl/sprite/sprite_parser.hpp>
+#include <mbgl/storage/response.hpp>
#include <memory>
#include <string>
@@ -14,7 +15,7 @@ class SpriteLoaderWorker {
public:
SpriteLoaderWorker(ActorRef<SpriteLoaderWorker>, ActorRef<SpriteLoader>);
- void parse(std::shared_ptr<const std::string> image, std::shared_ptr<const std::string> json);
+ void parse(Blob image, Blob json);
private:
ActorRef<SpriteLoader> parent;
diff --git a/src/mbgl/sprite/sprite_parser.cpp b/src/mbgl/sprite/sprite_parser.cpp
index 1a36e3e990..c93d97ba78 100644
--- a/src/mbgl/sprite/sprite_parser.cpp
+++ b/src/mbgl/sprite/sprite_parser.cpp
@@ -85,11 +85,12 @@ bool getBoolean(const JSValue& value, const char* name, const bool def = false)
} // namespace
-std::vector<std::unique_ptr<style::Image>> parseSprite(const std::string& encodedImage, const std::string& json) {
- const PremultipliedImage raster = decodeImage(encodedImage);
+std::vector<std::unique_ptr<style::Image>> parseSprite(Blob imageBlob, Blob jsonBlob) {
+ const PremultipliedImage raster = decodeImage(imageBlob);
+ const auto json = jsonBlob.uncompressedData();
JSDocument doc;
- doc.Parse<0>(json.c_str());
+ doc.Parse<0>(json->c_str());
if (doc.HasParseError()) {
std::stringstream message;
message << "Failed to parse JSON: " << rapidjson::GetParseError_En(doc.GetParseError()) << " at offset " << doc.GetErrorOffset();
diff --git a/src/mbgl/sprite/sprite_parser.hpp b/src/mbgl/sprite/sprite_parser.hpp
index f602818d3b..b17f4cc458 100644
--- a/src/mbgl/sprite/sprite_parser.hpp
+++ b/src/mbgl/sprite/sprite_parser.hpp
@@ -23,6 +23,6 @@ std::unique_ptr<style::Image> createStyleImage(const std::string& id,
bool sdf);
// Parses an image and an associated JSON file and returns the sprite objects.
-std::vector<std::unique_ptr<style::Image>> parseSprite(const std::string& image, const std::string& json);
+std::vector<std::unique_ptr<style::Image>> parseSprite(Blob image, Blob json);
} // namespace mbgl
diff --git a/src/mbgl/storage/resource.cpp b/src/mbgl/storage/resource.cpp
index 207dd2ee69..9bc8495d53 100644
--- a/src/mbgl/storage/resource.cpp
+++ b/src/mbgl/storage/resource.cpp
@@ -42,14 +42,20 @@ static std::string getTileBBox(int32_t x, int32_t y, int8_t z) {
Resource Resource::style(const std::string& url) {
return Resource {
Resource::Kind::Style,
- url
+ url,
+ {},
+ LoadingMethod::All,
+ Compression::Uncompressed
};
}
Resource Resource::source(const std::string& url) {
return Resource {
Resource::Kind::Source,
- url
+ url,
+ {},
+ LoadingMethod::All,
+ Compression::Uncompressed
};
}
@@ -87,7 +93,10 @@ Resource Resource::glyphs(const std::string& urlTemplate, const FontStack& fontS
} else {
return std::string();
}
- })
+ }),
+ {},
+ LoadingMethod::All,
+ Compression::Uncompressed
};
}
@@ -133,7 +142,8 @@ Resource Resource::tile(const std::string& urlTemplate,
y,
z
},
- loadingMethod
+ loadingMethod,
+ Compression::PreferCompressed
};
}
diff --git a/src/mbgl/style/sources/geojson_source.cpp b/src/mbgl/style/sources/geojson_source.cpp
index 4e3478322d..48308ccbc3 100644
--- a/src/mbgl/style/sources/geojson_source.cpp
+++ b/src/mbgl/style/sources/geojson_source.cpp
@@ -61,7 +61,8 @@ void GeoJSONSource::loadDescription(FileSource& fileSource) {
*this, std::make_exception_ptr(std::runtime_error("unexpectedly empty GeoJSON")));
} else {
conversion::Error error;
- optional<GeoJSON> geoJSON = conversion::convertJSON<GeoJSON>(*res.data, error);
+ optional<GeoJSON> geoJSON =
+ conversion::convertJSON<GeoJSON>(*res.data.uncompressedData(), error);
if (!geoJSON) {
Log::Error(Event::ParseStyle, "Failed to parse GeoJSON data: %s",
error.message.c_str());
diff --git a/src/mbgl/style/sources/image_source.cpp b/src/mbgl/style/sources/image_source.cpp
index fa268da0ef..5be1b54410 100644
--- a/src/mbgl/style/sources/image_source.cpp
+++ b/src/mbgl/style/sources/image_source.cpp
@@ -70,7 +70,7 @@ void ImageSource::loadDescription(FileSource& fileSource) {
observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error("unexpectedly empty image url")));
} else {
try {
- baseImpl = makeMutable<Impl>(impl(), decodeImage(*res.data));
+ baseImpl = makeMutable<Impl>(impl(), decodeImage(res.data));
} catch (...) {
observer->onSourceError(*this, std::current_exception());
}
diff --git a/src/mbgl/style/sources/raster_source.cpp b/src/mbgl/style/sources/raster_source.cpp
index 53f29d660b..c3c47567aa 100644
--- a/src/mbgl/style/sources/raster_source.cpp
+++ b/src/mbgl/style/sources/raster_source.cpp
@@ -57,7 +57,7 @@ void RasterSource::loadDescription(FileSource& fileSource) {
observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error("unexpectedly empty TileJSON")));
} else {
conversion::Error error;
- optional<Tileset> tileset = conversion::convertJSON<Tileset>(*res.data, error);
+ optional<Tileset> tileset = conversion::convertJSON<Tileset>(*res.data.uncompressedData(), error);
if (!tileset) {
observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error(error.message)));
return;
diff --git a/src/mbgl/style/sources/vector_source.cpp b/src/mbgl/style/sources/vector_source.cpp
index ccdd453c75..d88622f1b8 100644
--- a/src/mbgl/style/sources/vector_source.cpp
+++ b/src/mbgl/style/sources/vector_source.cpp
@@ -54,7 +54,8 @@ void VectorSource::loadDescription(FileSource& fileSource) {
observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error("unexpectedly empty TileJSON")));
} else {
conversion::Error error;
- optional<Tileset> tileset = conversion::convertJSON<Tileset>(*res.data, error);
+ optional<Tileset> tileset =
+ conversion::convertJSON<Tileset>(*res.data.uncompressedData(), error);
if (!tileset) {
observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error(error.message)));
return;
diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp
index bd8631fc52..82f421ecdf 100644
--- a/src/mbgl/style/style.cpp
+++ b/src/mbgl/style/style.cpp
@@ -14,7 +14,7 @@ Style::Style(Scheduler& scheduler, FileSource& fileSource, float pixelRatio)
Style::~Style() = default;
-void Style::loadJSON(const std::string& json) {
+void Style::loadJSON(Blob json) {
impl->loadJSON(json);
}
@@ -22,7 +22,7 @@ void Style::loadURL(const std::string& url) {
impl->loadURL(url);
}
-std::string Style::getJSON() const {
+Blob Style::getJSON() const {
return impl->getJSON();
}
diff --git a/src/mbgl/style/style_impl.cpp b/src/mbgl/style/style_impl.cpp
index d330b3120a..a952ccb8c2 100644
--- a/src/mbgl/style/style_impl.cpp
+++ b/src/mbgl/style/style_impl.cpp
@@ -39,7 +39,7 @@ Style::Impl::Impl(Scheduler& scheduler_, FileSource& fileSource_, float pixelRat
Style::Impl::~Impl() = default;
-void Style::Impl::loadJSON(const std::string& json_) {
+void Style::Impl::loadJSON(Blob json_) {
lastError = nullptr;
observer->onStyleLoading();
@@ -73,15 +73,17 @@ void Style::Impl::loadURL(const std::string& url_) {
} else if (res.notModified || res.noContent) {
return;
} else {
- parse(*res.data);
+ parse(res.data);
}
});
}
-void Style::Impl::parse(const std::string& json_) {
+void Style::Impl::parse(Blob json_) {
Parser parser;
- if (auto error = parser.parse(json_)) {
+ const auto data = json_.uncompressedData();
+
+ if (auto error = parser.parse(*data)) {
std::string message = "Failed to parse style: " + util::toString(error);
Log::Error(Event::ParseStyle, message.c_str());
observer->onStyleError(std::make_exception_ptr(util::StyleParseException(message)));
@@ -124,7 +126,7 @@ void Style::Impl::parse(const std::string& json_) {
observer->onStyleLoaded();
}
-std::string Style::Impl::getJSON() const {
+Blob Style::Impl::getJSON() const {
return json;
}
diff --git a/src/mbgl/style/style_impl.hpp b/src/mbgl/style/style_impl.hpp
index 3dc222bfad..9dc2704391 100644
--- a/src/mbgl/style/style_impl.hpp
+++ b/src/mbgl/style/style_impl.hpp
@@ -41,10 +41,10 @@ public:
Impl(Scheduler&, FileSource&, float pixelRatio);
~Impl() override;
- void loadJSON(const std::string&);
+ void loadJSON(Blob);
void loadURL(const std::string&);
- std::string getJSON() const;
+ Blob getJSON() const;
std::string getURL() const;
void setObserver(Observer*);
@@ -96,13 +96,13 @@ public:
bool spriteLoaded = false;
private:
- void parse(const std::string&);
+ void parse(Blob);
Scheduler& scheduler;
FileSource& fileSource;
std::string url;
- std::string json;
+ Blob json;
std::unique_ptr<AsyncRequest> styleRequest;
std::unique_ptr<SpriteLoader> spriteLoader;
diff --git a/src/mbgl/text/glyph_manager.cpp b/src/mbgl/text/glyph_manager.cpp
index 3130418908..37574eff15 100644
--- a/src/mbgl/text/glyph_manager.cpp
+++ b/src/mbgl/text/glyph_manager.cpp
@@ -91,7 +91,7 @@ void GlyphManager::processResponse(const Response& res, const FontStack& fontSta
std::vector<Glyph> glyphs;
try {
- glyphs = parseGlyphPBF(range, *res.data);
+ glyphs = parseGlyphPBF(range, res.data);
} catch (...) {
observer->onGlyphsError(fontStack, range, std::current_exception());
return;
diff --git a/src/mbgl/text/glyph_pbf.cpp b/src/mbgl/text/glyph_pbf.cpp
index cfaf803f75..77ea5ec2cb 100644
--- a/src/mbgl/text/glyph_pbf.cpp
+++ b/src/mbgl/text/glyph_pbf.cpp
@@ -4,11 +4,12 @@
namespace mbgl {
-std::vector<Glyph> parseGlyphPBF(const GlyphRange& glyphRange, const std::string& data) {
+std::vector<Glyph> parseGlyphPBF(const GlyphRange& glyphRange, Blob blob) {
+ const auto data = blob.uncompressedData();
std::vector<Glyph> result;
result.reserve(256);
- protozero::pbf_reader glyphs_pbf(data);
+ protozero::pbf_reader glyphs_pbf(*data);
while (glyphs_pbf.next(1)) {
auto fontstack_pbf = glyphs_pbf.get_message();
diff --git a/src/mbgl/text/glyph_pbf.hpp b/src/mbgl/text/glyph_pbf.hpp
index 28a28b4114..0c82343ce5 100644
--- a/src/mbgl/text/glyph_pbf.hpp
+++ b/src/mbgl/text/glyph_pbf.hpp
@@ -8,6 +8,6 @@
namespace mbgl {
-std::vector<Glyph> parseGlyphPBF(const GlyphRange&, const std::string& data);
+std::vector<Glyph> parseGlyphPBF(const GlyphRange&, Blob blob);
} // namespace mbgl
diff --git a/src/mbgl/tile/raster_dem_tile.cpp b/src/mbgl/tile/raster_dem_tile.cpp
index 5db298cf4c..10f22e378b 100644
--- a/src/mbgl/tile/raster_dem_tile.cpp
+++ b/src/mbgl/tile/raster_dem_tile.cpp
@@ -45,7 +45,7 @@ void RasterDEMTile::setMetadata(optional<Timestamp> modified_, optional<Timestam
expires = expires_;
}
-void RasterDEMTile::setData(std::shared_ptr<const std::string> data) {
+void RasterDEMTile::setData(Blob data) {
pending = true;
++correlationID;
worker.invoke(&RasterDEMTileWorker::parse, data, correlationID, encoding);
diff --git a/src/mbgl/tile/raster_dem_tile.hpp b/src/mbgl/tile/raster_dem_tile.hpp
index 0c8dd75961..0c5b3e7bf2 100644
--- a/src/mbgl/tile/raster_dem_tile.hpp
+++ b/src/mbgl/tile/raster_dem_tile.hpp
@@ -70,7 +70,7 @@ public:
void setError(std::exception_ptr);
void setMetadata(optional<Timestamp> modified, optional<Timestamp> expires);
- void setData(std::shared_ptr<const std::string> data);
+ void setData(Blob data);
void upload(gl::Context&) override;
Bucket* getBucket(const style::Layer::Impl&) const override;
diff --git a/src/mbgl/tile/raster_dem_tile_worker.cpp b/src/mbgl/tile/raster_dem_tile_worker.cpp
index 7338e578c7..ec5aba380a 100644
--- a/src/mbgl/tile/raster_dem_tile_worker.cpp
+++ b/src/mbgl/tile/raster_dem_tile_worker.cpp
@@ -10,14 +10,14 @@ RasterDEMTileWorker::RasterDEMTileWorker(ActorRef<RasterDEMTileWorker>, ActorRef
: parent(std::move(parent_)) {
}
-void RasterDEMTileWorker::parse(std::shared_ptr<const std::string> data, uint64_t correlationID, Tileset::DEMEncoding encoding) {
+void RasterDEMTileWorker::parse(Blob data, uint64_t correlationID, Tileset::DEMEncoding encoding) {
if (!data) {
parent.invoke(&RasterDEMTile::onParsed, nullptr, correlationID); // No data; empty tile.
return;
}
try {
- auto bucket = std::make_unique<HillshadeBucket>(decodeImage(*data), encoding);
+ auto bucket = std::make_unique<HillshadeBucket>(decodeImage(data), encoding);
parent.invoke(&RasterDEMTile::onParsed, std::move(bucket), correlationID);
} catch (...) {
parent.invoke(&RasterDEMTile::onError, std::current_exception(), correlationID);
diff --git a/src/mbgl/tile/raster_dem_tile_worker.hpp b/src/mbgl/tile/raster_dem_tile_worker.hpp
index 5a8222bc2d..5b9bce1a19 100644
--- a/src/mbgl/tile/raster_dem_tile_worker.hpp
+++ b/src/mbgl/tile/raster_dem_tile_worker.hpp
@@ -2,6 +2,7 @@
#include <mbgl/actor/actor_ref.hpp>
#include <mbgl/util/tileset.hpp>
+#include <mbgl/util/blob.hpp>
#include <memory>
#include <string>
@@ -14,7 +15,7 @@ class RasterDEMTileWorker {
public:
RasterDEMTileWorker(ActorRef<RasterDEMTileWorker>, ActorRef<RasterDEMTile>);
- void parse(std::shared_ptr<const std::string> data, uint64_t correlationID, Tileset::DEMEncoding encoding);
+ void parse(Blob data, uint64_t correlationID, Tileset::DEMEncoding encoding);
private:
ActorRef<RasterDEMTile> parent;
diff --git a/src/mbgl/tile/raster_tile.cpp b/src/mbgl/tile/raster_tile.cpp
index ff23d4493e..4bc9830fda 100644
--- a/src/mbgl/tile/raster_tile.cpp
+++ b/src/mbgl/tile/raster_tile.cpp
@@ -34,7 +34,7 @@ void RasterTile::setMetadata(optional<Timestamp> modified_, optional<Timestamp>
expires = expires_;
}
-void RasterTile::setData(std::shared_ptr<const std::string> data) {
+void RasterTile::setData(Blob data) {
pending = true;
++correlationID;
worker.invoke(&RasterTileWorker::parse, data, correlationID);
diff --git a/src/mbgl/tile/raster_tile.hpp b/src/mbgl/tile/raster_tile.hpp
index e25329119a..c1fa6caa99 100644
--- a/src/mbgl/tile/raster_tile.hpp
+++ b/src/mbgl/tile/raster_tile.hpp
@@ -26,7 +26,7 @@ public:
void setError(std::exception_ptr);
void setMetadata(optional<Timestamp> modified, optional<Timestamp> expires);
- void setData(std::shared_ptr<const std::string> data);
+ void setData(Blob data);
void upload(gl::Context&) override;
Bucket* getBucket(const style::Layer::Impl&) const override;
diff --git a/src/mbgl/tile/raster_tile_worker.cpp b/src/mbgl/tile/raster_tile_worker.cpp
index 4afa876429..d0dd8918a2 100644
--- a/src/mbgl/tile/raster_tile_worker.cpp
+++ b/src/mbgl/tile/raster_tile_worker.cpp
@@ -10,14 +10,14 @@ RasterTileWorker::RasterTileWorker(ActorRef<RasterTileWorker>, ActorRef<RasterTi
: parent(std::move(parent_)) {
}
-void RasterTileWorker::parse(std::shared_ptr<const std::string> data, uint64_t correlationID) {
+void RasterTileWorker::parse(Blob data, uint64_t correlationID) {
if (!data) {
parent.invoke(&RasterTile::onParsed, nullptr, correlationID); // No data; empty tile.
return;
}
try {
- auto bucket = std::make_unique<RasterBucket>(decodeImage(*data));
+ auto bucket = std::make_unique<RasterBucket>(decodeImage(data));
parent.invoke(&RasterTile::onParsed, std::move(bucket), correlationID);
} catch (...) {
parent.invoke(&RasterTile::onError, std::current_exception(), correlationID);
diff --git a/src/mbgl/tile/raster_tile_worker.hpp b/src/mbgl/tile/raster_tile_worker.hpp
index 520973c3c3..c56da82d0a 100644
--- a/src/mbgl/tile/raster_tile_worker.hpp
+++ b/src/mbgl/tile/raster_tile_worker.hpp
@@ -1,6 +1,7 @@
#pragma once
#include <mbgl/actor/actor_ref.hpp>
+#include <mbgl/util/blob.hpp>
#include <memory>
#include <string>
@@ -13,7 +14,7 @@ class RasterTileWorker {
public:
RasterTileWorker(ActorRef<RasterTileWorker>, ActorRef<RasterTile>);
- void parse(std::shared_ptr<const std::string> data, uint64_t correlationID);
+ void parse(Blob data, uint64_t correlationID);
private:
ActorRef<RasterTile> parent;
diff --git a/src/mbgl/tile/tile_loader_impl.hpp b/src/mbgl/tile/tile_loader_impl.hpp
index 1b29638269..48b3b7c87b 100644
--- a/src/mbgl/tile/tile_loader_impl.hpp
+++ b/src/mbgl/tile/tile_loader_impl.hpp
@@ -106,7 +106,7 @@ void TileLoader<T>::loadedData(const Response& res) {
resource.priorExpires = res.expires;
resource.priorEtag = res.etag;
tile.setMetadata(res.modified, res.expires);
- tile.setData(res.noContent ? nullptr : res.data);
+ tile.setData(res.noContent ? Blob{} : res.data);
}
}
diff --git a/src/mbgl/tile/vector_tile.cpp b/src/mbgl/tile/vector_tile.cpp
index 0756d3e526..a815f31e41 100644
--- a/src/mbgl/tile/vector_tile.cpp
+++ b/src/mbgl/tile/vector_tile.cpp
@@ -21,8 +21,8 @@ void VectorTile::setMetadata(optional<Timestamp> modified_, optional<Timestamp>
expires = expires_;
}
-void VectorTile::setData(std::shared_ptr<const std::string> data_) {
- GeometryTile::setData(data_ ? std::make_unique<VectorTileData>(data_) : nullptr);
+void VectorTile::setData(Blob data_) {
+ GeometryTile::setData(data_ ? std::make_unique<VectorTileData>(std::move(data_)) : nullptr);
}
} // namespace mbgl
diff --git a/src/mbgl/tile/vector_tile.hpp b/src/mbgl/tile/vector_tile.hpp
index 7dae414fef..87abf2f598 100644
--- a/src/mbgl/tile/vector_tile.hpp
+++ b/src/mbgl/tile/vector_tile.hpp
@@ -17,7 +17,7 @@ public:
void setNecessity(TileNecessity) final;
void setMetadata(optional<Timestamp> modified, optional<Timestamp> expires);
- void setData(std::shared_ptr<const std::string> data);
+ void setData(Blob data);
private:
TileLoader<VectorTile> loader;
diff --git a/src/mbgl/tile/vector_tile_data.cpp b/src/mbgl/tile/vector_tile_data.cpp
index 2d4a01bda3..eaa91dc9cf 100644
--- a/src/mbgl/tile/vector_tile_data.cpp
+++ b/src/mbgl/tile/vector_tile_data.cpp
@@ -60,19 +60,24 @@ std::string VectorTileLayer::getName() const {
return layer.getName();
}
-VectorTileData::VectorTileData(std::shared_ptr<const std::string> data_) : data(std::move(data_)) {
+VectorTileData::VectorTileData(Blob blob_) : blob(std::move(blob_)) {
}
std::unique_ptr<GeometryTileData> VectorTileData::clone() const {
- return std::make_unique<VectorTileData>(data);
+ // Always pass on data that is uncompressed, if we have it.
+ return std::make_unique<VectorTileData>(data ? Blob{ data, false } : blob);
}
std::unique_ptr<GeometryTileLayer> VectorTileData::getLayer(const std::string& name) const {
- if (!parsed) {
+ if (!blob) {
+ return nullptr;
+ }
+
+ if (!data) {
// We're parsing this lazily so that we can construct VectorTileData objects on the main
- // thread without incurring the overhead of parsing immediately.
+ // thread without incurring the overhead of parsing and decompressing immediately.
+ data = blob.uncompressedData();
layers = mapbox::vector_tile::buffer(*data).getLayers();
- parsed = true;
}
auto it = layers.find(name);
diff --git a/src/mbgl/tile/vector_tile_data.hpp b/src/mbgl/tile/vector_tile_data.hpp
index 48beaf9d07..ce120e97c0 100644
--- a/src/mbgl/tile/vector_tile_data.hpp
+++ b/src/mbgl/tile/vector_tile_data.hpp
@@ -1,5 +1,7 @@
#include <mbgl/tile/geometry_tile_data.hpp>
+#include <mbgl/util/blob.hpp>
+
#include <mapbox/vector_tile.hpp>
#include <protozero/pbf_reader.hpp>
@@ -38,7 +40,8 @@ private:
class VectorTileData : public GeometryTileData {
public:
- VectorTileData(std::shared_ptr<const std::string> data);
+ VectorTileData(const VectorTileData&);
+ VectorTileData(Blob blob);
std::unique_ptr<GeometryTileData> clone() const override;
std::unique_ptr<GeometryTileLayer> getLayer(const std::string& name) const override;
@@ -46,8 +49,8 @@ public:
std::vector<std::string> layerNames() const;
private:
- std::shared_ptr<const std::string> data;
- mutable bool parsed = false;
+ Blob blob;
+ mutable std::shared_ptr<const std::string> data;
mutable std::map<std::string, const protozero::data_view> layers;
};
diff --git a/src/mbgl/util/blob.cpp b/src/mbgl/util/blob.cpp
new file mode 100644
index 0000000000..53d7644002
--- /dev/null
+++ b/src/mbgl/util/blob.cpp
@@ -0,0 +1,46 @@
+#include <mbgl/util/blob.hpp>
+#include <mbgl/util/compression.hpp>
+
+namespace mbgl {
+
+Blob::Blob() = default;
+
+Blob::Blob(std::shared_ptr<const std::string> bytes_, bool compressed_)
+ : bytes(std::move(bytes_)), compressed(compressed_) {
+}
+
+Blob::Blob(std::string&& bytes_, bool compressed_)
+ : bytes(std::make_shared<const std::string>(std::move(bytes_))), compressed(compressed_) {
+}
+
+std::shared_ptr<const std::string> Blob::uncompressedData() const {
+ if (!bytes) {
+ throw std::runtime_error("invalid blob");
+ }
+ if (compressed) {
+ return std::make_shared<const std::string>(util::decompress(*bytes));
+ } else {
+ return bytes;
+ }
+}
+
+std::shared_ptr<const std::string> Blob::compressedData() const {
+ if (!bytes) {
+ throw std::runtime_error("invalid blob");
+ }
+ if (compressed) {
+ return bytes;
+ } else {
+ return std::make_shared<const std::string>(util::compress(*bytes));
+ }
+}
+
+void Blob::uncompress() {
+ if (compressed) {
+ bytes = uncompressedData();
+ compressed = false;
+ }
+}
+
+
+} // namespace mbgl
diff --git a/src/mbgl/util/compression.cpp b/src/mbgl/util/compression.cpp
index 30e813cbb8..4d4e094f06 100644
--- a/src/mbgl/util/compression.cpp
+++ b/src/mbgl/util/compression.cpp
@@ -71,7 +71,8 @@ std::string decompress(const std::string &raw) {
memset(&inflate_stream, 0, sizeof(inflate_stream));
// TODO: reuse z_streams
- if (inflateInit(&inflate_stream) != Z_OK) {
+ // MAX_WBITS + allows decoding gzip in addition to zlib
+ if (inflateInit2(&inflate_stream, MAX_WBITS + 32) != Z_OK) {
throw std::runtime_error("failed to initialize inflate");
}
@@ -100,5 +101,39 @@ std::string decompress(const std::string &raw) {
return result;
}
+
+bool isCompressible(const std::string& raw) {
+ // WebP
+ if (raw.size() >= 12 && static_cast<uint8_t>(raw[0]) == 'R' &&
+ static_cast<uint8_t>(raw[1]) == 'I' && static_cast<uint8_t>(raw[2]) == 'F' &&
+ static_cast<uint8_t>(raw[3]) == 'F' && static_cast<uint8_t>(raw[8]) == 'W' &&
+ static_cast<uint8_t>(raw[9]) == 'E' && static_cast<uint8_t>(raw[10]) == 'B' &&
+ static_cast<uint8_t>(raw[11]) == 'P') {
+ // Note: the WebP container format allows uncompressed data as well, but we just assume that
+ // all WebP files are already compressed.
+ return false;
+ }
+
+ // PNG
+ if (raw.size() >= 8 && static_cast<uint8_t>(raw[0]) == 0x89 &&
+ static_cast<uint8_t>(raw[1]) == 'P' && static_cast<uint8_t>(raw[2]) == 'N' &&
+ static_cast<uint8_t>(raw[3]) == 'G' && static_cast<uint8_t>(raw[4]) == '\r' &&
+ static_cast<uint8_t>(raw[5]) == '\n' && static_cast<uint8_t>(raw[6]) == 0x1a &&
+ static_cast<uint8_t>(raw[7]) == '\n') {
+ // Note: this assumes the PNG file itself is compressed. However, it is possible to create
+ // PNG files with uncompressed data in it (zlib compression 0), but they are exceedingly
+ // rare, so we don't care about them.
+ return false;
+ }
+
+ // JPEG
+ if (raw.size() >= 3 && static_cast<uint8_t>(raw[0]) == 0xff &&
+ static_cast<uint8_t>(raw[1]) == 0xd8 && static_cast<uint8_t>(raw[2]) == 0xff) {
+ return false;
+ }
+
+ return true;
+}
+
} // namespace util
} // namespace mbgl
diff --git a/src/mbgl/util/io.cpp b/src/mbgl/util/io.cpp
index 6a6ed7b250..2dc6cabf0f 100644
--- a/src/mbgl/util/io.cpp
+++ b/src/mbgl/util/io.cpp
@@ -1,43 +1,29 @@
#include <mbgl/util/io.hpp>
-#include <cstdio>
#include <cerrno>
#include <iostream>
-#include <sstream>
#include <fstream>
namespace mbgl {
namespace util {
-void write_file(const std::string &filename, const std::string &data) {
- FILE *fd = fopen(filename.c_str(), "wb");
- if (fd) {
- fwrite(data.data(), sizeof(std::string::value_type), data.size(), fd);
- fclose(fd);
- } else {
- throw std::runtime_error(std::string("Failed to open file ") + filename);
- }
-}
-
-std::string read_file(const std::string &filename) {
- std::ifstream file(filename);
+void writeFile(const std::string &filename, Blob blob) {
+ std::ofstream file(filename, std::ios::binary);
if (file.good()) {
- std::stringstream data;
- data << file.rdbuf();
- return data.str();
+ file << *blob.uncompressedData();
} else {
- throw std::runtime_error(std::string("Cannot read file ") + filename);
+ throw IOException(errno, "failed to write file");
}
}
-optional<std::string> readFile(const std::string &filename) {
- std::ifstream file(filename);
+Blob readFile(const std::string &filename) {
+ std::ifstream file(filename, std::ios::binary);
if (file.good()) {
- std::stringstream data;
- data << file.rdbuf();
- return data.str();
+ return { { std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>() },
+ false };
+ } else {
+ return {};
}
- return {};
}
void deleteFile(const std::string& filename) {
diff --git a/src/mbgl/util/io.hpp b/src/mbgl/util/io.hpp
index 847271acf0..b74f89485b 100644
--- a/src/mbgl/util/io.hpp
+++ b/src/mbgl/util/io.hpp
@@ -1,6 +1,7 @@
#pragma once
#include <mbgl/util/optional.hpp>
+#include <mbgl/util/blob.hpp>
#include <string>
#include <stdexcept>
@@ -14,10 +15,8 @@ struct IOException : std::runtime_error {
const int code = 0;
};
-void write_file(const std::string &filename, const std::string &data);
-std::string read_file(const std::string &filename);
-
-optional<std::string> readFile(const std::string &filename);
+void writeFile(const std::string &filename, Blob blob);
+Blob readFile(const std::string &filename);
void deleteFile(const std::string& filename);
} // namespace util
diff --git a/test/api/annotations.test.cpp b/test/api/annotations.test.cpp
index 07257851ac..8b25fa482d 100644
--- a/test/api/annotations.test.cpp
+++ b/test/api/annotations.test.cpp
@@ -17,7 +17,7 @@ using namespace mbgl;
namespace {
PremultipliedImage namedImage(const std::string& name) {
- return decodeImage(util::read_file("test/fixtures/sprites/" + name + ".png"));
+ return decodeImage(util::readFile("test/fixtures/sprites/" + name + ".png"));
}
std::unique_ptr<style::Image> namedMarker(const std::string& name) {
@@ -45,7 +45,7 @@ public:
TEST(Annotations, SymbolAnnotation) {
AnnotationTest test;
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
test.map.addAnnotationImage(namedMarker("default_marker"));
test.map.addAnnotation(SymbolAnnotation { Point<double>(0, 0), "default_marker" });
test.checkRendering("point_annotation");
@@ -67,7 +67,7 @@ TEST(Annotations, LineAnnotation) {
annotation.color = Color::red();
annotation.width = { 5 };
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
test.map.addAnnotation(annotation);
test.checkRendering("line_annotation");
@@ -82,7 +82,7 @@ TEST(Annotations, FillAnnotation) {
FillAnnotation annotation { polygon };
annotation.color = Color::red();
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
test.map.addAnnotation(annotation);
test.checkRendering("fill_annotation");
@@ -95,7 +95,7 @@ TEST(Annotations, AntimeridianAnnotationSmall) {
double antimeridian = 180;
test.map.setLatLngZoom(mbgl::LatLng(0, antimeridian), 0);
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
LineString<double> line = {{ { antimeridian, 20 }, { antimeridian, -20 } }};
LineAnnotation lineAnnotation { line };
@@ -116,7 +116,7 @@ TEST(Annotations, AntimeridianAnnotationLarge) {
double antimeridian = 180;
test.map.setLatLngZoom(mbgl::LatLng(0, antimeridian), 0);
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
LineString<double> line = {{ { antimeridian, 20 }, { antimeridian, -20 } }};
LineAnnotation lineAnnotation { line };
@@ -141,7 +141,7 @@ TEST(Annotations, OverlappingFillAnnotation) {
FillAnnotation overlaidAnnotation { polygon };
overlaidAnnotation.color = Color::red();
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
test.map.addAnnotation(underlaidAnnotation);
test.map.addAnnotation(overlaidAnnotation);
test.checkRendering("overlapping_fill_annotation");
@@ -150,7 +150,7 @@ TEST(Annotations, OverlappingFillAnnotation) {
TEST(Annotations, AddMultiple) {
AnnotationTest test;
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
test.map.addAnnotationImage(namedMarker("default_marker"));
test.map.addAnnotation(SymbolAnnotation { Point<double> { -10, 0 }, "default_marker" });
@@ -163,7 +163,7 @@ TEST(Annotations, AddMultiple) {
TEST(Annotations, NonImmediateAdd) {
AnnotationTest test;
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
test.frontend.render(test.map);
Polygon<double> polygon = { {{ { 0, 0 }, { 0, 45 }, { 45, 45 }, { 45, 0 } }} };
@@ -177,7 +177,7 @@ TEST(Annotations, NonImmediateAdd) {
TEST(Annotations, UpdateSymbolAnnotationGeometry) {
AnnotationTest test;
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
test.map.addAnnotationImage(namedMarker("default_marker"));
test.map.addAnnotationImage(namedMarker("flipped_marker"));
AnnotationID point = test.map.addAnnotation(SymbolAnnotation { Point<double> { 0, 0 }, "default_marker" });
@@ -191,7 +191,7 @@ TEST(Annotations, UpdateSymbolAnnotationGeometry) {
TEST(Annotations, UpdateSymbolAnnotationIcon) {
AnnotationTest test;
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
test.map.addAnnotationImage(namedMarker("default_marker"));
test.map.addAnnotationImage(namedMarker("flipped_marker"));
AnnotationID point = test.map.addAnnotation(SymbolAnnotation { Point<double> { 0, 0 }, "default_marker" });
@@ -209,7 +209,7 @@ TEST(Annotations, UpdateLineAnnotationGeometry) {
annotation.color = Color::red();
annotation.width = { 5 };
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
AnnotationID line = test.map.addAnnotation(annotation);
test.frontend.render(test.map);
@@ -226,7 +226,7 @@ TEST(Annotations, UpdateLineAnnotationStyle) {
annotation.color = Color::red();
annotation.width = { 5 };
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
AnnotationID line = test.map.addAnnotation(annotation);
test.frontend.render(test.map);
@@ -243,7 +243,7 @@ TEST(Annotations, UpdateFillAnnotationGeometry) {
FillAnnotation annotation { Polygon<double> { {{ { 0, 0 }, { 0, 45 }, { 45, 45 }, { 45, 0 } }} } };
annotation.color = Color::red();
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
AnnotationID fill = test.map.addAnnotation(annotation);
test.frontend.render(test.map);
@@ -260,7 +260,7 @@ TEST(Annotations, UpdateFillAnnotationStyle) {
FillAnnotation annotation { polygon };
annotation.color = Color::red();
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
AnnotationID fill = test.map.addAnnotation(annotation);
test.frontend.render(test.map);
@@ -273,7 +273,7 @@ TEST(Annotations, UpdateFillAnnotationStyle) {
TEST(Annotations, RemovePoint) {
AnnotationTest test;
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
test.map.addAnnotationImage(namedMarker("default_marker"));
AnnotationID point = test.map.addAnnotation(SymbolAnnotation { Point<double> { 0, 0 }, "default_marker" });
@@ -291,7 +291,7 @@ TEST(Annotations, RemoveShape) {
annotation.color = Color::red();
annotation.width = { 5 };
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
AnnotationID shape = test.map.addAnnotation(annotation);
test.frontend.render(test.map);
@@ -304,7 +304,7 @@ TEST(Annotations, ImmediateRemoveShape) {
AnnotationTest test;
test.map.removeAnnotation(test.map.addAnnotation(LineAnnotation { LineString<double>() }));
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
test.frontend.render(test.map);
}
@@ -312,20 +312,20 @@ TEST(Annotations, ImmediateRemoveShape) {
TEST(Annotations, SwitchStyle) {
AnnotationTest test;
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
test.map.addAnnotationImage(namedMarker("default_marker"));
test.map.addAnnotation(SymbolAnnotation { Point<double> { 0, 0 }, "default_marker" });
test.frontend.render(test.map);
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
test.checkRendering("switch_style");
}
TEST(Annotations, ReaddImage) {
AnnotationTest test;
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
test.map.addAnnotationImage(namedMarker("default_marker"));
test.map.addAnnotation(SymbolAnnotation { Point<double> { 0, 0 }, "default_marker" });
@@ -338,7 +338,7 @@ TEST(Annotations, ReaddImage) {
TEST(Annotations, QueryRenderedFeatures) {
AnnotationTest test;
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
test.map.addAnnotationImage(namedMarker("default_marker"));
test.map.addAnnotation(SymbolAnnotation { Point<double> { 0, 0 }, "default_marker" });
test.map.addAnnotation(SymbolAnnotation { Point<double> { 0, 50 }, "default_marker" });
@@ -362,7 +362,7 @@ TEST(Annotations, QueryFractionalZoomLevels) {
auto viewSize = test.frontend.getSize();
auto box = ScreenBox { {}, { double(viewSize.width), double(viewSize.height) } };
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
test.map.addAnnotationImage(namedMarker("default_marker"));
std::vector<mbgl::AnnotationID> ids;
@@ -394,7 +394,7 @@ TEST(Annotations, VisibleFeatures) {
auto viewSize = test.frontend.getSize();
auto box = ScreenBox { {}, { double(viewSize.width), double(viewSize.height) } };
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
test.map.addAnnotationImage(namedMarker("default_marker"));
test.map.setLatLngZoom({ 5, 5 }, 3);
@@ -438,7 +438,7 @@ TEST(Annotations, DebugEmpty) {
// should not render them.
AnnotationTest test;
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
test.map.setDebug(MapDebugOptions::TileBorders);
test.map.setZoom(1);
@@ -451,7 +451,7 @@ TEST(Annotations, DebugSparse) {
// tiles because they're all empty.
AnnotationTest test;
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
test.map.setDebug(MapDebugOptions::TileBorders);
test.map.setZoom(1);
test.map.addAnnotationImage(namedMarker("default_marker"));
@@ -469,7 +469,7 @@ TEST(Annotations, ChangeMaxZoom) {
annotation.width = { 5 };
test.map.setMaxZoom(6);
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
test.map.addAnnotation(annotation);
test.map.setMaxZoom(14);
test.map.setZoom(test.map.getMaxZoom());
diff --git a/test/api/custom_geometry_source.test.cpp b/test/api/custom_geometry_source.test.cpp
index 83d1543a0a..3397bef9ef 100644
--- a/test/api/custom_geometry_source.test.cpp
+++ b/test/api/custom_geometry_source.test.cpp
@@ -26,7 +26,7 @@ TEST(CustomGeometrySource, Grid) {
HeadlessFrontend frontend { pixelRatio, fileSource, *threadPool };
Map map(frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio, fileSource,
*threadPool, MapMode::Static);
- map.getStyle().loadJSON(util::read_file("test/fixtures/api/water.json"));
+ map.getStyle().loadJSON(util::readFile("test/fixtures/api/water.json"));
map.setLatLngZoom({ 37.8, -122.5 }, 10);
CustomGeometrySource::Options options;
diff --git a/test/api/custom_layer.test.cpp b/test/api/custom_layer.test.cpp
index eb1d7e0d3a..5eaa73a37a 100644
--- a/test/api/custom_layer.test.cpp
+++ b/test/api/custom_layer.test.cpp
@@ -91,7 +91,7 @@ TEST(CustomLayer, Basic) {
HeadlessFrontend frontend { pixelRatio, fileSource, threadPool };
Map map(frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio, fileSource,
threadPool, MapMode::Static);
- map.getStyle().loadJSON(util::read_file("test/fixtures/api/water.json"));
+ map.getStyle().loadJSON(util::readFile("test/fixtures/api/water.json"));
map.setLatLngZoom({ 37.8, -122.5 }, 10);
map.getStyle().addLayer(std::make_unique<CustomLayer>(
"custom",
diff --git a/test/api/query.test.cpp b/test/api/query.test.cpp
index c67ff9064c..43067dd57a 100644
--- a/test/api/query.test.cpp
+++ b/test/api/query.test.cpp
@@ -19,9 +19,9 @@ namespace {
class QueryTest {
public:
QueryTest() {
- map.getStyle().loadJSON(util::read_file("test/fixtures/api/query_style.json"));
+ map.getStyle().loadJSON(util::readFile("test/fixtures/api/query_style.json"));
map.getStyle().addImage(std::make_unique<style::Image>("test-icon",
- decodeImage(util::read_file("test/fixtures/sprites/default_marker.png")), 1.0));
+ decodeImage(util::readFile("test/fixtures/sprites/default_marker.png")), 1.0));
frontend.render(map);
}
diff --git a/test/api/recycle_map.cpp b/test/api/recycle_map.cpp
index ca6abac8c1..1055eda5a9 100644
--- a/test/api/recycle_map.cpp
+++ b/test/api/recycle_map.cpp
@@ -40,10 +40,10 @@ TEST(API, RecycleMapUpdateImages) {
auto layer = std::make_unique<SymbolLayer>("geometry", "geometry");
layer->setIconImage({ markerName });
- map->getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ map->getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
map->getStyle().addSource(std::move(source));
map->getStyle().addLayer(std::move(layer));
- map->getStyle().addImage(std::make_unique<style::Image>(markerName, decodeImage(util::read_file(markerPath)), 1.0));
+ map->getStyle().addImage(std::make_unique<style::Image>(markerName, decodeImage(util::readFile(markerPath)), 1.0));
};
// default marker
diff --git a/test/api/zoom_history.cpp b/test/api/zoom_history.cpp
index df9b6ff2a3..a16d5322d7 100644
--- a/test/api/zoom_history.cpp
+++ b/test/api/zoom_history.cpp
@@ -34,7 +34,7 @@ TEST(API, ZoomHistory) {
EXPECT_TRUE(map);
- map->getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ map->getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
auto source = std::make_unique<GeoJSONSource>("source");
source->setGeoJSON({ LineString<double> { { 45, -45 }, { -45, 45 } } });
diff --git a/test/gl/context.test.cpp b/test/gl/context.test.cpp
index 179ce5de53..157732d723 100644
--- a/test/gl/context.test.cpp
+++ b/test/gl/context.test.cpp
@@ -90,7 +90,7 @@ TEST(GLContextMode, Shared) {
HeadlessFrontend frontend { pixelRatio, fileSource, threadPool, {}, GLContextMode::Shared };
Map map(frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio, fileSource, threadPool, MapMode::Static);
- map.getStyle().loadJSON(util::read_file("test/fixtures/api/water.json"));
+ map.getStyle().loadJSON(util::readFile("test/fixtures/api/water.json"));
map.setLatLngZoom({ 37.8, -122.5 }, 10);
// Set transparent background layer.
diff --git a/test/map/map.test.cpp b/test/map/map.test.cpp
index 9b34ea89b0..bb0ff2a201 100644
--- a/test/map/map.test.cpp
+++ b/test/map/map.test.cpp
@@ -21,7 +21,6 @@
using namespace mbgl;
using namespace mbgl::style;
-using namespace std::literals::string_literals;
class StubMapObserver : public MapObserver {
public:
@@ -162,7 +161,7 @@ TEST(Map, Offline) {
auto expiredItem = [] (const std::string& path) {
Response response;
- response.data = std::make_shared<std::string>(util::read_file("test/fixtures/map/offline/"s + path));
+ response.data = util::readFile("test/fixtures/map/offline/" + path);
response.expires = Timestamp{ Seconds(0) };
return response;
};
@@ -188,13 +187,13 @@ TEST(Map, Offline) {
TEST(Map, SetStyleDefaultCamera) {
MapTest<> test;
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
EXPECT_DOUBLE_EQ(test.map.getZoom(), 0.0);
EXPECT_DOUBLE_EQ(test.map.getPitch(), 0.0);
EXPECT_DOUBLE_EQ(test.map.getBearing(), 0.0);
EXPECT_EQ(test.map.getLatLng(), LatLng {});
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty-zoomed.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty-zoomed.json"));
EXPECT_DOUBLE_EQ(test.map.getZoom(), 0.0);
test.map.jumpTo(test.map.getStyle().getDefaultCamera());
@@ -211,7 +210,7 @@ TEST(Map, SetStyleInvalidJSON) {
test.observer.didFailLoadingMapCallback = [&]() {
fail = true;
};
- test.map.getStyle().loadJSON("invalid");
+ test.map.getStyle().loadJSON(Blob{ "invalid", false });
}
EXPECT_TRUE(fail);
@@ -247,8 +246,8 @@ TEST(Map, SetStyleInvalidURL) {
TEST(Map, DoubleStyleLoad) {
MapTest<> test;
- test.map.getStyle().loadJSON("");
- test.map.getStyle().loadJSON("");
+ test.map.getStyle().loadJSON(Blob{ "", false });
+ test.map.getStyle().loadJSON(Blob{ "", false });
}
TEST(Map, StyleFresh) {
@@ -260,7 +259,7 @@ TEST(Map, StyleFresh) {
EXPECT_EQ(1u, test.fileSource.requests.size());
Response response;
- response.data = std::make_shared<std::string>(util::read_file("test/fixtures/api/empty.json"));
+ response.data = util::readFile("test/fixtures/api/empty.json");
response.expires = Timestamp::max();
test.fileSource.respond(Resource::Style, response);
@@ -278,7 +277,7 @@ TEST(Map, StyleExpired) {
EXPECT_EQ(1u, test.fileSource.requests.size());
Response response;
- response.data = std::make_shared<std::string>(util::read_file("test/fixtures/api/empty.json"));
+ response.data = util::readFile("test/fixtures/api/empty.json");
response.expires = util::now() - 1h;
test.fileSource.respond(Resource::Style, response);
@@ -303,7 +302,7 @@ TEST(Map, StyleExpiredWithAnnotations) {
EXPECT_EQ(1u, test.fileSource.requests.size());
Response response;
- response.data = std::make_shared<std::string>(util::read_file("test/fixtures/api/empty.json"));
+ response.data = util::readFile("test/fixtures/api/empty.json");
response.expires = util::now() - 1h;
test.fileSource.respond(Resource::Style, response);
@@ -327,7 +326,7 @@ TEST(Map, StyleExpiredWithRender) {
EXPECT_EQ(1u, test.fileSource.requests.size());
Response response;
- response.data = std::make_shared<std::string>(util::read_file("test/fixtures/api/empty.json"));
+ response.data = util::readFile("test/fixtures/api/empty.json");
response.expires = util::now() - 1h;
test.fileSource.respond(Resource::Style, response);
@@ -349,7 +348,7 @@ TEST(Map, StyleEarlyMutation) {
test.map.getStyle().addLayer(std::make_unique<style::BackgroundLayer>("bg"));
Response response;
- response.data = std::make_shared<std::string>(util::read_file("test/fixtures/api/water.json"));
+ response.data = util::readFile("test/fixtures/api/water.json");
test.fileSource.respond(Resource::Style, response);
EXPECT_EQ(0u, test.fileSource.requests.size());
@@ -363,7 +362,7 @@ TEST(Map, MapLoadingSignal) {
test.observer.onWillStartLoadingMapCallback = [&]() {
emitted = true;
};
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
EXPECT_TRUE(emitted);
}
@@ -374,7 +373,7 @@ TEST(Map, MapLoadedSignal) {
test.runLoop.stop();
};
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
test.runLoop.run();
}
@@ -386,12 +385,12 @@ TEST(Map, StyleLoadedSignal) {
test.observer.didFinishLoadingStyleCallback = [&]() {
emitted = true;
};
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
EXPECT_TRUE(emitted);
// But not when the style couldn't be parsed
emitted = false;
- test.map.getStyle().loadJSON("invalid");
+ test.map.getStyle().loadJSON(Blob{ "invalid", false });
EXPECT_FALSE(emitted);
}
@@ -437,7 +436,7 @@ TEST(Map, TEST_REQUIRES_SERVER(StyleNotFound)) {
TEST(Map, AddLayer) {
MapTest<> test;
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
auto layer = std::make_unique<BackgroundLayer>("background");
layer->setBackgroundColor({ { 1, 0, 0, 1 } });
@@ -452,7 +451,7 @@ TEST(Map, WithoutVAOExtension) {
BackendScope scope { *test.frontend.getBackend() };
test.frontend.getBackend()->getContext().disableVAOExtension = true;
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/water.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/water.json"));
test::checkImage("test/fixtures/map/no_vao", test.frontend.render(test.map), 0.002);
}
@@ -460,7 +459,7 @@ TEST(Map, WithoutVAOExtension) {
TEST(Map, RemoveLayer) {
MapTest<> test;
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/api/empty.json"));
auto layer = std::make_unique<BackgroundLayer>("background");
layer->setBackgroundColor({{ 1, 0, 0, 1 }});
@@ -477,8 +476,7 @@ TEST(Map, DisabledSources) {
test.fileSource.response = [] (const Resource& res) -> optional<Response> {
if (res.url == "asset://tile.png") {
Response response;
- response.data = std::make_shared<std::string>(
- util::read_file("test/fixtures/map/disabled_layers/tile.png"));
+ response.data = util::readFile("test/fixtures/map/disabled_layers/tile.png");
return {std::move(response)};
}
return {};
@@ -491,7 +489,7 @@ TEST(Map, DisabledSources) {
// to an opacity of 0.5). Then, we are zooming back out to a zoom level of 0.5 and rerender.
// The "raster1" layer should not be visible anymore since it has minzoom 1, while "raster2"
// should still be there. Both layers have a distinct color through "raster-hue-rotate".
- test.map.getStyle().loadJSON(R"STYLE(
+ test.map.getStyle().loadJSON(Blob{ R"STYLE(
{
"version": 8,
"name": "Test",
@@ -523,7 +521,7 @@ TEST(Map, DisabledSources) {
}
}]
}
-)STYLE");
+)STYLE", false });
test::checkImage("test/fixtures/map/disabled_layers/first", test.frontend.render(test.map));
test.map.setZoom(0.5);
@@ -533,7 +531,7 @@ TEST(Map, DisabledSources) {
TEST(Map, DontLoadUnneededTiles) {
MapTest<> test;
- test.map.getStyle().loadJSON(R"STYLE({
+ test.map.getStyle().loadJSON(Blob{ R"STYLE({
"sources": {
"a": { "type": "vector", "tiles": [ "a/{z}/{x}/{y}" ] }
},
@@ -545,7 +543,7 @@ TEST(Map, DontLoadUnneededTiles) {
"minzoom": 0.3,
"maxzoom": 1.6
}]
-})STYLE");
+})STYLE", false });
using Tiles = std::unordered_set<std::string>;
Tiles tiles;
@@ -606,7 +604,7 @@ TEST(Map, TEST_DISABLED_ON_CI(ContinuousRendering)) {
};
Map map(frontend, observer, frontend.getSize(), pixelRatio, fileSource, threadPool, MapMode::Continuous);
- map.getStyle().loadJSON(util::read_file("test/fixtures/api/water.json"));
+ map.getStyle().loadJSON(util::readFile("test/fixtures/api/water.json"));
runLoop.run();
}
@@ -624,7 +622,7 @@ TEST(Map, NoContentTiles) {
Tileset::Scheme::XYZ),
response);
- test.map.getStyle().loadJSON(R"STYLE({
+ test.map.getStyle().loadJSON(Blob{ R"STYLE({
"version": 8,
"name": "Water",
"sources": {
@@ -645,7 +643,7 @@ TEST(Map, NoContentTiles) {
"source": "mapbox",
"source-layer": "water"
}]
- })STYLE");
+ })STYLE", false });
test::checkImage("test/fixtures/map/nocontent",
test.frontend.render(test.map),
diff --git a/test/map/prefetch.test.cpp b/test/map/prefetch.test.cpp
index 4c82b2c965..7cb8ea1545 100644
--- a/test/map/prefetch.test.cpp
+++ b/test/map/prefetch.test.cpp
@@ -37,11 +37,9 @@ TEST(Map, PrefetchTiles) {
// The end rendering result should be all green because the map is only
// considered fully rendered when only ideal tiles are shown.
if (zoom == int(map.getZoom()) + 1) {
- response.data = std::make_shared<std::string>(
- util::read_file("test/fixtures/map/prefetch/tile_green.png"));
+ response.data = util::readFile("test/fixtures/map/prefetch/tile_green.png");
} else {
- response.data = std::make_shared<std::string>(
- util::read_file("test/fixtures/map/prefetch/tile_red.png"));
+ response.data = util::readFile("test/fixtures/map/prefetch/tile_red.png");
}
return { std::move(response) };
@@ -51,8 +49,8 @@ TEST(Map, PrefetchTiles) {
tiles.clear();
// Force tile reloading.
- map.getStyle().loadJSON(util::read_file("test/fixtures/map/prefetch/empty.json"));
- map.getStyle().loadJSON(util::read_file("test/fixtures/map/prefetch/style.json"));
+ map.getStyle().loadJSON(util::readFile("test/fixtures/map/prefetch/empty.json"));
+ map.getStyle().loadJSON(util::readFile("test/fixtures/map/prefetch/style.json"));
map.setLatLngZoom({ 40.726989, -73.992857 }, zoom); // Manhattan
diff --git a/test/programs/binary_program.test.cpp b/test/programs/binary_program.test.cpp
index a5cf7b6e39..7fc2acbf77 100644
--- a/test/programs/binary_program.test.cpp
+++ b/test/programs/binary_program.test.cpp
@@ -35,5 +35,5 @@ TEST(BinaryProgram, ObtainValues) {
EXPECT_EQ(3, binaryProgram2.uniformLocation("u_ratio"));
EXPECT_EQ(-1, binaryProgram2.uniformLocation("a_data"));
- EXPECT_THROW(BinaryProgram(""), std::runtime_error);
+ EXPECT_THROW(BinaryProgram(Blob{ "", false }), std::runtime_error);
}
diff --git a/test/renderer/image_manager.test.cpp b/test/renderer/image_manager.test.cpp
index ebe1bcd72f..e1d9030d4c 100644
--- a/test/renderer/image_manager.test.cpp
+++ b/test/renderer/image_manager.test.cpp
@@ -25,8 +25,8 @@ TEST(ImageManager, Basic) {
FixtureLog log;
ImageManager imageManager;
- auto images = parseSprite(util::read_file("test/fixtures/annotations/emerald.png"),
- util::read_file("test/fixtures/annotations/emerald.json"));
+ auto images = parseSprite(util::readFile("test/fixtures/annotations/emerald.png"),
+ util::readFile("test/fixtures/annotations/emerald.json"));
for (auto& image : images) {
imageManager.addImage(image->baseImpl);
}
diff --git a/test/sprite/sprite_loader.test.cpp b/test/sprite/sprite_loader.test.cpp
index 3691572265..d773afd539 100644
--- a/test/sprite/sprite_loader.test.cpp
+++ b/test/sprite/sprite_loader.test.cpp
@@ -58,14 +58,14 @@ public:
Response successfulSpriteImageResponse(const Resource& resource) {
EXPECT_EQ("test/fixtures/resources/sprite.png", resource.url);
Response response;
- response.data = std::make_unique<std::string>(util::read_file(resource.url));
+ response.data = util::readFile(resource.url);
return response;
}
Response successfulSpriteJSONResponse(const Resource& resource) {
EXPECT_EQ("test/fixtures/resources/sprite.json", resource.url);
Response response;
- response.data = std::make_unique<std::string>(util::read_file(resource.url));
+ response.data = util::readFile(resource.url);
return response;
}
@@ -79,7 +79,7 @@ Response failedSpriteResponse(const Resource&) {
Response corruptSpriteResponse(const Resource&) {
Response response;
- response.data = std::make_unique<std::string>("CORRUPT");
+ response.data = Blob{ "CORRUPT", false };
return response;
}
diff --git a/test/sprite/sprite_parser.test.cpp b/test/sprite/sprite_parser.test.cpp
index 529e4c75e8..14d5f65860 100644
--- a/test/sprite/sprite_parser.test.cpp
+++ b/test/sprite/sprite_parser.test.cpp
@@ -14,7 +14,7 @@ using namespace mbgl;
namespace {
auto readImage(const std::string& name) {
- return decodeImage(util::read_file(name));
+ return decodeImage(util::readFile(name));
}
} // namespace
@@ -22,7 +22,7 @@ auto readImage(const std::string& name) {
TEST(Sprite, SpriteImageCreationInvalid) {
FixtureLog log;
- const PremultipliedImage image_1x = decodeImage(util::read_file("test/fixtures/annotations/emerald.png"));
+ const PremultipliedImage image_1x = decodeImage(util::readFile("test/fixtures/annotations/emerald.png"));
ASSERT_EQ(200u, image_1x.size.width);
ASSERT_EQ(299u, image_1x.size.height);
@@ -135,7 +135,7 @@ TEST(Sprite, SpriteImageCreationInvalid) {
}
TEST(Sprite, SpriteImageCreation1x) {
- const PremultipliedImage image_1x = decodeImage(util::read_file("test/fixtures/annotations/emerald.png"));
+ const PremultipliedImage image_1x = decodeImage(util::readFile("test/fixtures/annotations/emerald.png"));
ASSERT_EQ(200u, image_1x.size.width);
ASSERT_EQ(299u, image_1x.size.height);
@@ -152,7 +152,7 @@ TEST(Sprite, SpriteImageCreation1x) {
}
TEST(Sprite, SpriteImageCreation2x) {
- const PremultipliedImage image_2x = decodeImage(util::read_file("test/fixtures/annotations/emerald@2x.png"));
+ const PremultipliedImage image_2x = decodeImage(util::readFile("test/fixtures/annotations/emerald@2x.png"));
// "museum_icon":{"x":354,"y":374,"width":36,"height":36,"pixelRatio":2,"sdf":false}
const auto sprite = createStyleImage("test", image_2x, 354, 374, 36, 36, 2, false);
@@ -165,7 +165,7 @@ TEST(Sprite, SpriteImageCreation2x) {
}
TEST(Sprite, SpriteImageCreation1_5x) {
- const PremultipliedImage image_2x = decodeImage(util::read_file("test/fixtures/annotations/emerald@2x.png"));
+ const PremultipliedImage image_2x = decodeImage(util::readFile("test/fixtures/annotations/emerald@2x.png"));
// "museum_icon":{"x":354,"y":374,"width":36,"height":36,"pixelRatio":2,"sdf":false}
const auto sprite = createStyleImage("test", image_2x, 354, 374, 36, 36, 1.5, false);
@@ -187,8 +187,8 @@ TEST(Sprite, SpriteImageCreation1_5x) {
}
TEST(Sprite, SpriteParsing) {
- const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png");
- const auto json_1x = util::read_file("test/fixtures/annotations/emerald.json");
+ const auto image_1x = util::readFile("test/fixtures/annotations/emerald.png");
+ const auto json_1x = util::readFile("test/fixtures/annotations/emerald.json");
const auto images = parseSprite(image_1x, json_1x);
@@ -281,8 +281,8 @@ TEST(Sprite, SpriteParsing) {
}
TEST(Sprite, SpriteParsingInvalidJSON) {
- const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png");
- const auto json_1x = R"JSON({ "image": " })JSON";
+ const auto image_1x = util::readFile("test/fixtures/annotations/emerald.png");
+ const auto json_1x = Blob{ R"JSON({ "image": " })JSON", false };
try {
parseSprite(image_1x, json_1x);
@@ -297,8 +297,8 @@ TEST(Sprite, SpriteParsingInvalidJSON) {
TEST(Sprite, SpriteParsingEmptyImage) {
FixtureLog log;
- const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png");
- const auto json_1x = R"JSON({ "image": {} })JSON";
+ const auto image_1x = util::readFile("test/fixtures/annotations/emerald.png");
+ const auto json_1x = Blob{ R"JSON({ "image": {} })JSON", false };
const auto images = parseSprite(image_1x, json_1x);
EXPECT_EQ(0u, images.size());
@@ -314,8 +314,8 @@ TEST(Sprite, SpriteParsingEmptyImage) {
TEST(Sprite, SpriteParsingSimpleWidthHeight) {
FixtureLog log;
- const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png");
- const auto json_1x = R"JSON({ "image": { "width": 32, "height": 32 } })JSON";
+ const auto image_1x = util::readFile("test/fixtures/annotations/emerald.png");
+ const auto json_1x = Blob{ R"JSON({ "image": { "width": 32, "height": 32 } })JSON", false };
const auto images = parseSprite(image_1x, json_1x);
EXPECT_EQ(1u, images.size());
@@ -324,8 +324,8 @@ TEST(Sprite, SpriteParsingSimpleWidthHeight) {
TEST(Sprite, SpriteParsingWidthTooBig) {
FixtureLog log;
- const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png");
- const auto json_1x = R"JSON({ "image": { "width": 65536, "height": 32 } })JSON";
+ const auto image_1x = util::readFile("test/fixtures/annotations/emerald.png");
+ const auto json_1x = Blob{ R"JSON({ "image": { "width": 65536, "height": 32 } })JSON", false };
const auto images = parseSprite(image_1x, json_1x);
EXPECT_EQ(0u, images.size());
@@ -347,8 +347,8 @@ TEST(Sprite, SpriteParsingWidthTooBig) {
TEST(Sprite, SpriteParsingNegativeWidth) {
FixtureLog log;
- const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png");
- const auto json_1x = R"JSON({ "image": { "width": -1, "height": 32 } })JSON";
+ const auto image_1x = util::readFile("test/fixtures/annotations/emerald.png");
+ const auto json_1x = Blob{ R"JSON({ "image": { "width": -1, "height": 32 } })JSON", false };
const auto images = parseSprite(image_1x, json_1x);
EXPECT_EQ(0u, images.size());
@@ -370,8 +370,8 @@ TEST(Sprite, SpriteParsingNegativeWidth) {
TEST(Sprite, SpriteParsingNullRatio) {
FixtureLog log;
- const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png");
- const auto json_1x = R"JSON({ "image": { "width": 32, "height": 32, "pixelRatio": 0 } })JSON";
+ const auto image_1x = util::readFile("test/fixtures/annotations/emerald.png");
+ const auto json_1x = Blob{ R"JSON({ "image": { "width": 32, "height": 32, "pixelRatio": 0 } })JSON", false };
const auto images = parseSprite(image_1x, json_1x);
EXPECT_EQ(0u, images.size());
diff --git a/test/src/mbgl/test/util.cpp b/test/src/mbgl/test/util.cpp
index 028a0a9d51..82d2af6cd9 100644
--- a/test/src/mbgl/test/util.cpp
+++ b/test/src/mbgl/test/util.cpp
@@ -100,26 +100,26 @@ void checkImage(const std::string& base,
double pixelThreshold) {
#if !TEST_READ_ONLY
if (getenv("UPDATE")) {
- util::write_file(base + "/expected.png", encodePNG(actual));
+ util::writeFile(base + "/expected.png", encodePNG(actual));
return;
}
#endif
- std::string expected_image;
+ Blob expectedImage;
try {
- expected_image = util::read_file(base + "/expected.png");
+ expectedImage = util::readFile(base + "/expected.png");
} catch (std::exception& ex) {
Log::Error(Event::Setup, "Failed to load expected image %s: %s",
(base + "/expected.png").c_str(), ex.what());
throw;
}
- PremultipliedImage expected = decodeImage(expected_image);
+ PremultipliedImage expected = decodeImage(expectedImage);
PremultipliedImage diff { expected.size };
#if !TEST_READ_ONLY
- util::write_file(base + "/actual.png", encodePNG(actual));
+ util::writeFile(base + "/actual.png", encodePNG(actual));
#endif
ASSERT_EQ(expected.size, actual.size);
@@ -134,7 +134,7 @@ void checkImage(const std::string& base,
EXPECT_LE(pixels / (expected.size.width * expected.size.height), imageThreshold);
#if !TEST_READ_ONLY
- util::write_file(base + "/diff.png", encodePNG(diff));
+ util::writeFile(base + "/diff.png", encodePNG(diff));
#endif
}
diff --git a/test/storage/asset_file_source.test.cpp b/test/storage/asset_file_source.test.cpp
index 978a41a306..694d56be6d 100644
--- a/test/storage/asset_file_source.test.cpp
+++ b/test/storage/asset_file_source.test.cpp
@@ -33,8 +33,8 @@ TEST(AssetFileSource, Load) {
requestCallback = [this, asset, endCallback](mbgl::Response res) {
EXPECT_EQ(nullptr, res.error);
- ASSERT_TRUE(res.data.get());
- EXPECT_EQ("content is here\n", *res.data);
+ ASSERT_TRUE(res.data);
+ EXPECT_EQ("content is here\n", *res.data.uncompressedData());
if (!--numRequests) {
endCallback();
@@ -86,8 +86,8 @@ TEST(AssetFileSource, EmptyFile) {
std::unique_ptr<AsyncRequest> req = fs.request({ Resource::Unknown, "asset://empty" }, [&](Response res) {
req.reset();
EXPECT_EQ(nullptr, res.error);
- ASSERT_TRUE(res.data.get());
- EXPECT_EQ("", *res.data);
+ ASSERT_TRUE(res.data);
+ EXPECT_EQ("", *res.data.uncompressedData());
loop.stop();
});
@@ -102,8 +102,8 @@ TEST(AssetFileSource, NonEmptyFile) {
std::unique_ptr<AsyncRequest> req = fs.request({ Resource::Unknown, "asset://nonempty" }, [&](Response res) {
req.reset();
EXPECT_EQ(nullptr, res.error);
- ASSERT_TRUE(res.data.get());
- EXPECT_EQ("content is here\n", *res.data);
+ ASSERT_TRUE(res.data);
+ EXPECT_EQ("content is here\n", *res.data.uncompressedData());
loop.stop();
});
@@ -119,7 +119,7 @@ TEST(AssetFileSource, NonExistentFile) {
req.reset();
ASSERT_NE(nullptr, res.error);
EXPECT_EQ(Response::Error::Reason::NotFound, res.error->reason);
- ASSERT_FALSE(res.data.get());
+ ASSERT_FALSE(res.data);
// Do not assert on platform-specific error message.
loop.stop();
});
@@ -137,7 +137,7 @@ TEST(AssetFileSource, InvalidURL) {
ASSERT_NE(nullptr, res.error);
EXPECT_EQ(Response::Error::Reason::Other, res.error->reason);
EXPECT_EQ("Invalid asset URL", res.error->message);
- ASSERT_FALSE(res.data.get());
+ ASSERT_FALSE(res.data);
loop.stop();
});
@@ -153,7 +153,7 @@ TEST(AssetFileSource, ReadDirectory) {
req.reset();
ASSERT_NE(nullptr, res.error);
EXPECT_EQ(Response::Error::Reason::NotFound, res.error->reason);
- ASSERT_FALSE(res.data.get());
+ ASSERT_FALSE(res.data);
// Do not assert on platform-specific error message.
loop.stop();
});
@@ -169,8 +169,8 @@ TEST(AssetFileSource, URLEncoding) {
std::unique_ptr<AsyncRequest> req = fs.request({ Resource::Unknown, "asset://%6eonempty" }, [&](Response res) {
req.reset();
EXPECT_EQ(nullptr, res.error);
- ASSERT_TRUE(res.data.get());
- EXPECT_EQ("content is here\n", *res.data);
+ ASSERT_TRUE(res.data);
+ EXPECT_EQ("content is here\n", *res.data.uncompressedData());
loop.stop();
});
diff --git a/test/storage/default_file_source.test.cpp b/test/storage/default_file_source.test.cpp
index c11d442270..f74a515d86 100644
--- a/test/storage/default_file_source.test.cpp
+++ b/test/storage/default_file_source.test.cpp
@@ -19,8 +19,8 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(CacheResponse)) {
req1 = fs.request(resource, [&](Response res) {
req1.reset();
EXPECT_EQ(nullptr, res.error);
- ASSERT_TRUE(res.data.get());
- EXPECT_EQ("Response 1", *res.data);
+ ASSERT_TRUE(res.data);
+ EXPECT_EQ("Response 1", *res.data.uncompressedData());
EXPECT_TRUE(bool(res.expires));
EXPECT_FALSE(res.mustRevalidate);
EXPECT_FALSE(bool(res.modified));
@@ -32,8 +32,8 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(CacheResponse)) {
req2 = fs.request(resource, [&](Response res2) {
req2.reset();
EXPECT_EQ(response.error, res2.error);
- ASSERT_TRUE(res2.data.get());
- EXPECT_EQ(*response.data, *res2.data);
+ ASSERT_TRUE(res2.data);
+ EXPECT_EQ(*response.data.uncompressedData(), *res2.data.uncompressedData());
EXPECT_EQ(response.expires, res2.expires);
EXPECT_EQ(response.mustRevalidate, res2.mustRevalidate);
EXPECT_EQ(response.modified, res2.modified);
@@ -61,8 +61,8 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(CacheRevalidateSame)) {
EXPECT_EQ(nullptr, res.error);
EXPECT_FALSE(res.notModified);
- ASSERT_TRUE(res.data.get());
- EXPECT_EQ("Response", *res.data);
+ ASSERT_TRUE(res.data);
+ EXPECT_EQ("Response", *res.data.uncompressedData());
EXPECT_FALSE(bool(res.expires));
EXPECT_TRUE(res.mustRevalidate);
EXPECT_FALSE(bool(res.modified));
@@ -81,8 +81,8 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(CacheRevalidateSame)) {
gotResponse = true;
EXPECT_EQ(nullptr, res2.error);
EXPECT_FALSE(res2.notModified);
- ASSERT_TRUE(res2.data.get());
- EXPECT_EQ("Response", *res2.data);
+ ASSERT_TRUE(res2.data);
+ EXPECT_EQ("Response", *res2.data.uncompressedData());
EXPECT_TRUE(bool(res2.expires));
EXPECT_TRUE(res2.mustRevalidate);
EXPECT_FALSE(bool(res2.modified));
@@ -95,7 +95,7 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(CacheRevalidateSame)) {
req2.reset();
EXPECT_EQ(nullptr, res2.error);
EXPECT_TRUE(res2.notModified);
- EXPECT_FALSE(res2.data.get());
+ EXPECT_FALSE(res2.data);
EXPECT_TRUE(bool(res2.expires));
EXPECT_TRUE(res2.mustRevalidate);
EXPECT_FALSE(bool(res2.modified));
@@ -124,8 +124,8 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(CacheRevalidateModified)) {
EXPECT_EQ(nullptr, res.error);
EXPECT_FALSE(res.notModified);
- ASSERT_TRUE(res.data.get());
- EXPECT_EQ("Response", *res.data);
+ ASSERT_TRUE(res.data);
+ EXPECT_EQ("Response", *res.data.uncompressedData());
EXPECT_FALSE(bool(res.expires));
EXPECT_TRUE(res.mustRevalidate);
EXPECT_EQ(Timestamp{ Seconds(1420070400) }, *res.modified);
@@ -144,8 +144,8 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(CacheRevalidateModified)) {
gotResponse = true;
EXPECT_EQ(nullptr, res2.error);
EXPECT_FALSE(res2.notModified);
- ASSERT_TRUE(res2.data.get());
- EXPECT_EQ("Response", *res2.data);
+ ASSERT_TRUE(res2.data);
+ EXPECT_EQ("Response", *res2.data.uncompressedData());
EXPECT_TRUE(bool(res2.expires));
EXPECT_TRUE(res2.mustRevalidate);
EXPECT_EQ(Timestamp{ Seconds(1420070400) }, *res2.modified);
@@ -158,7 +158,7 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(CacheRevalidateModified)) {
req2.reset();
EXPECT_EQ(nullptr, res2.error);
EXPECT_TRUE(res2.notModified);
- EXPECT_FALSE(res2.data.get());
+ EXPECT_FALSE(res2.data);
EXPECT_TRUE(bool(res2.expires));
EXPECT_TRUE(res2.mustRevalidate);
EXPECT_EQ(Timestamp{ Seconds(1420070400) }, *res2.modified);
@@ -184,8 +184,8 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(CacheRevalidateEtag)) {
req1.reset();
EXPECT_EQ(nullptr, res.error);
- ASSERT_TRUE(res.data.get());
- EXPECT_EQ("Response 1", *res.data);
+ ASSERT_TRUE(res.data);
+ EXPECT_EQ("Response 1", *res.data.uncompressedData());
EXPECT_FALSE(bool(res.expires));
EXPECT_TRUE(res.mustRevalidate);
EXPECT_FALSE(bool(res.modified));
@@ -196,9 +196,9 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(CacheRevalidateEtag)) {
req2.reset();
EXPECT_EQ(nullptr, res2.error);
- ASSERT_TRUE(res2.data.get());
- EXPECT_NE(res.data, res2.data);
- EXPECT_EQ("Response 2", *res2.data);
+ ASSERT_TRUE(res2.data);
+ EXPECT_FALSE(*res.data.uncompressedData() == *res2.data.uncompressedData());
+ EXPECT_EQ("Response 2", *res2.data.uncompressedData());
EXPECT_FALSE(bool(res2.expires));
EXPECT_TRUE(res2.mustRevalidate);
EXPECT_FALSE(bool(res2.modified));
@@ -235,8 +235,8 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(HTTPIssue1369)) {
req = fs.request(resource, [&](Response res) {
req.reset();
EXPECT_EQ(nullptr, res.error);
- ASSERT_TRUE(res.data.get());
- EXPECT_EQ("Hello World!", *res.data);
+ ASSERT_TRUE(res.data);
+ EXPECT_EQ("Hello World!", *res.data.uncompressedData());
EXPECT_FALSE(bool(res.expires));
EXPECT_FALSE(res.mustRevalidate);
EXPECT_FALSE(bool(res.modified));
@@ -256,7 +256,7 @@ TEST(DefaultFileSource, OptionalNonExpired) {
using namespace std::chrono_literals;
Response response;
- response.data = std::make_shared<std::string>("Cached value");
+ response.data = Blob{ "Cached value", false };
response.expires = util::now() + 1h;
fs.put(optionalResource, response);
@@ -264,8 +264,8 @@ TEST(DefaultFileSource, OptionalNonExpired) {
req = fs.request(optionalResource, [&](Response res) {
req.reset();
EXPECT_EQ(nullptr, res.error);
- ASSERT_TRUE(res.data.get());
- EXPECT_EQ("Cached value", *res.data);
+ ASSERT_TRUE(res.data);
+ EXPECT_EQ("Cached value", *res.data.uncompressedData());
ASSERT_TRUE(bool(res.expires));
EXPECT_EQ(*response.expires, *res.expires);
EXPECT_FALSE(res.mustRevalidate);
@@ -286,7 +286,7 @@ TEST(DefaultFileSource, OptionalExpired) {
using namespace std::chrono_literals;
Response response;
- response.data = std::make_shared<std::string>("Cached value");
+ response.data = Blob{ "Cached value", false };
response.expires = util::now() - 1h;
fs.put(optionalResource, response);
@@ -294,8 +294,8 @@ TEST(DefaultFileSource, OptionalExpired) {
req = fs.request(optionalResource, [&](Response res) {
req.reset();
EXPECT_EQ(nullptr, res.error);
- ASSERT_TRUE(res.data.get());
- EXPECT_EQ("Cached value", *res.data);
+ ASSERT_TRUE(res.data);
+ EXPECT_EQ("Cached value", *res.data.uncompressedData());
ASSERT_TRUE(bool(res.expires));
EXPECT_EQ(*response.expires, *res.expires);
EXPECT_FALSE(res.mustRevalidate);
@@ -361,7 +361,7 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(NoCacheRefreshEtagNotModified)) {
// Put a fake value into the cache to make sure we're not retrieving anything from the cache.
Response response;
- response.data = std::make_shared<std::string>("Cached value");
+ response.data = Blob{ "Cached value", false };
response.expires = util::now() + 1h;
fs.put(resource, response);
@@ -370,7 +370,7 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(NoCacheRefreshEtagNotModified)) {
req.reset();
EXPECT_EQ(nullptr, res.error);
EXPECT_TRUE(res.notModified);
- EXPECT_FALSE(res.data.get());
+ EXPECT_FALSE(res.data);
ASSERT_TRUE(bool(res.expires));
EXPECT_LT(util::now(), *res.expires);
EXPECT_TRUE(res.mustRevalidate);
@@ -396,7 +396,7 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(NoCacheRefreshEtagModified)) {
// Put a fake value into the cache to make sure we're not retrieving anything from the cache.
Response response;
- response.data = std::make_shared<std::string>("Cached value");
+ response.data = Blob{ "Cached value", false };
response.expires = util::now() + 1h;
fs.put(resource, response);
@@ -405,8 +405,8 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(NoCacheRefreshEtagModified)) {
req.reset();
EXPECT_EQ(nullptr, res.error);
EXPECT_FALSE(res.notModified);
- ASSERT_TRUE(res.data.get());
- EXPECT_EQ("Response", *res.data);
+ ASSERT_TRUE(res.data);
+ EXPECT_EQ("Response", *res.data.uncompressedData());
EXPECT_FALSE(bool(res.expires));
EXPECT_TRUE(res.mustRevalidate);
EXPECT_FALSE(bool(res.modified));
@@ -430,7 +430,7 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(NoCacheFull)) {
// Put a fake value into the cache to make sure we're not retrieving anything from the cache.
Response response;
- response.data = std::make_shared<std::string>("Cached value");
+ response.data = Blob{ "Cached value", false };
response.expires = util::now() + 1h;
fs.put(resource, response);
@@ -439,8 +439,8 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(NoCacheFull)) {
req.reset();
EXPECT_EQ(nullptr, res.error);
EXPECT_FALSE(res.notModified);
- ASSERT_TRUE(res.data.get());
- EXPECT_EQ("Response", *res.data);
+ ASSERT_TRUE(res.data);
+ EXPECT_EQ("Response", *res.data.uncompressedData());
EXPECT_FALSE(bool(res.expires));
EXPECT_TRUE(res.mustRevalidate);
EXPECT_FALSE(bool(res.modified));
@@ -466,7 +466,7 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(NoCacheRefreshModifiedNotModified))
// Put a fake value into the cache to make sure we're not retrieving anything from the cache.
Response response;
- response.data = std::make_shared<std::string>("Cached value");
+ response.data = Blob{ "Cached value", false };
response.expires = util::now() + 1h;
fs.put(resource, response);
@@ -475,7 +475,7 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(NoCacheRefreshModifiedNotModified))
req.reset();
EXPECT_EQ(nullptr, res.error);
EXPECT_TRUE(res.notModified);
- EXPECT_FALSE(res.data.get());
+ EXPECT_FALSE(res.data);
ASSERT_TRUE(bool(res.expires));
EXPECT_LT(util::now(), *res.expires);
EXPECT_TRUE(res.mustRevalidate);
@@ -502,7 +502,7 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(NoCacheRefreshModifiedModified)) {
// Put a fake value into the cache to make sure we're not retrieving anything from the cache.
Response response;
- response.data = std::make_shared<std::string>("Cached value");
+ response.data = Blob{ "Cached value", false };
response.expires = util::now() + 1h;
fs.put(resource, response);
@@ -511,8 +511,8 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(NoCacheRefreshModifiedModified)) {
req.reset();
EXPECT_EQ(nullptr, res.error);
EXPECT_FALSE(res.notModified);
- ASSERT_TRUE(res.data.get());
- EXPECT_EQ("Response", *res.data);
+ ASSERT_TRUE(res.data);
+ EXPECT_EQ("Response", *res.data.uncompressedData());
EXPECT_FALSE(bool(res.expires));
EXPECT_TRUE(res.mustRevalidate);
EXPECT_EQ(Timestamp{ Seconds(1420070400) }, *res.modified);
@@ -543,8 +543,8 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(SetResourceTransform)) {
req = fs.request(resource1, [&](Response res) {
req.reset();
EXPECT_EQ(nullptr, res.error);
- ASSERT_TRUE(res.data.get());
- EXPECT_EQ("Hello World!", *res.data);
+ ASSERT_TRUE(res.data);
+ EXPECT_EQ("Hello World!", *res.data.uncompressedData());
EXPECT_FALSE(bool(res.expires));
EXPECT_FALSE(res.mustRevalidate);
EXPECT_FALSE(bool(res.modified));
@@ -560,8 +560,8 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(SetResourceTransform)) {
req = fs.request(resource2, [&](Response res) {
req.reset();
EXPECT_EQ(nullptr, res.error);
- ASSERT_TRUE(res.data.get());
- EXPECT_EQ("Hello World!", *res.data);
+ ASSERT_TRUE(res.data);
+ EXPECT_EQ("Hello World!", *res.data.uncompressedData());
EXPECT_FALSE(bool(res.expires));
EXPECT_FALSE(res.mustRevalidate);
EXPECT_FALSE(bool(res.modified));
@@ -584,7 +584,7 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(RespondToStaleMustRevalidate)) {
// Put an existing value in the cache that has expired, and has must-revalidate set.
Response response;
- response.data = std::make_shared<std::string>("Cached value");
+ response.data = Blob{ "Cached value", false };
response.modified = Timestamp(Seconds(1417392000)); // December 1, 2014
response.expires = Timestamp(Seconds(1417392000));
response.mustRevalidate = true;
@@ -598,8 +598,8 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(RespondToStaleMustRevalidate)) {
EXPECT_EQ(Response::Error::Reason::NotFound, res.error->reason);
EXPECT_EQ("Cached resource is unusable", res.error->message);
EXPECT_FALSE(res.notModified);
- ASSERT_TRUE(res.data.get());
- EXPECT_EQ("Cached value", *res.data);
+ ASSERT_TRUE(res.data);
+ EXPECT_EQ("Cached value", *res.data.uncompressedData());
ASSERT_TRUE(res.expires);
EXPECT_EQ(Timestamp{ Seconds(1417392000) }, *res.expires);
EXPECT_TRUE(res.mustRevalidate);
@@ -622,7 +622,7 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(RespondToStaleMustRevalidate)) {
// request. We're replacing the data so that we can check that the DefaultFileSource doesn't
// attempt another database access if we already have the value.
resource.loadingMethod = Resource::LoadingMethod::NetworkOnly;
- resource.priorData = std::make_shared<std::string>("Prior value");
+ resource.priorData = Blob{ "Prior value", false };
req = fs.request(resource, [&](Response res) {
req.reset();
@@ -632,11 +632,11 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(RespondToStaleMustRevalidate)) {
// OnlineFileSource to ensure that requestors know that this is the first time they're
// seeing this data.
EXPECT_FALSE(res.notModified);
- ASSERT_TRUE(res.data.get());
+ ASSERT_TRUE(res.data);
// Ensure that it's the value that we manually inserted into the cache rather than the value
// the server returns, since we should be executing a revalidation request which doesn't
// return new data, only a 304 Not Modified response.
- EXPECT_EQ("Prior value", *res.data);
+ EXPECT_EQ("Prior value", *res.data.uncompressedData());
ASSERT_TRUE(res.expires);
EXPECT_LE(util::now(), *res.expires);
EXPECT_TRUE(res.mustRevalidate);
diff --git a/test/storage/http_file_source.test.cpp b/test/storage/http_file_source.test.cpp
index 006b7a0fb3..093a5c1ced 100644
--- a/test/storage/http_file_source.test.cpp
+++ b/test/storage/http_file_source.test.cpp
@@ -23,8 +23,8 @@ TEST(HTTPFileSource, TEST_REQUIRES_SERVER(HTTP200)) {
auto req = fs.request({ Resource::Unknown, "http://127.0.0.1:3000/test" }, [&](Response res) {
EXPECT_EQ(nullptr, res.error);
- ASSERT_TRUE(res.data.get());
- EXPECT_EQ("Hello World!", *res.data);
+ ASSERT_TRUE(res.data);
+ EXPECT_EQ("Hello World!", *res.data.uncompressedData());
EXPECT_FALSE(bool(res.expires));
EXPECT_FALSE(res.mustRevalidate);
EXPECT_FALSE(bool(res.modified));
@@ -43,7 +43,7 @@ TEST(HTTPFileSource, TEST_REQUIRES_SERVER(HTTP404)) {
ASSERT_NE(nullptr, res.error);
EXPECT_EQ(Response::Error::Reason::NotFound, res.error->reason);
EXPECT_EQ("HTTP status code 404", res.error->message);
- EXPECT_FALSE(bool(res.data));
+ EXPECT_FALSE(res.data);
EXPECT_FALSE(bool(res.expires));
EXPECT_FALSE(res.mustRevalidate);
EXPECT_FALSE(bool(res.modified));
@@ -61,7 +61,7 @@ TEST(HTTPFileSource, TEST_REQUIRES_SERVER(HTTPTile404)) {
auto req = fs.request({ Resource::Tile, "http://127.0.0.1:3000/doesnotexist" }, [&](Response res) {
EXPECT_TRUE(res.noContent);
EXPECT_FALSE(bool(res.error));
- EXPECT_FALSE(bool(res.data));
+ EXPECT_FALSE(res.data);
EXPECT_FALSE(bool(res.expires));
EXPECT_FALSE(res.mustRevalidate);
EXPECT_FALSE(bool(res.modified));
@@ -79,7 +79,8 @@ TEST(HTTPFileSource, TEST_REQUIRES_SERVER(HTTP200EmptyData)) {
auto req = fs.request({ Resource::Unknown, "http://127.0.0.1:3000/empty-data" }, [&](Response res) {
EXPECT_FALSE(res.noContent);
EXPECT_FALSE(bool(res.error));
- EXPECT_EQ(*res.data, std::string());
+ ASSERT_TRUE(res.data);
+ EXPECT_EQ(0u, res.data.uncompressedData()->size());
EXPECT_FALSE(bool(res.expires));
EXPECT_FALSE(res.mustRevalidate);
EXPECT_FALSE(bool(res.modified));
@@ -97,7 +98,7 @@ TEST(HTTPFileSource, TEST_REQUIRES_SERVER(HTTP204)) {
auto req = fs.request({ Resource::Unknown, "http://127.0.0.1:3000/no-content" }, [&](Response res) {
EXPECT_TRUE(res.noContent);
EXPECT_FALSE(bool(res.error));
- EXPECT_FALSE(bool(res.data));
+ EXPECT_FALSE(res.data);
EXPECT_FALSE(bool(res.expires));
EXPECT_FALSE(res.mustRevalidate);
EXPECT_FALSE(bool(res.modified));
@@ -116,7 +117,7 @@ TEST(HTTPFileSource, TEST_REQUIRES_SERVER(HTTP500)) {
ASSERT_NE(nullptr, res.error);
EXPECT_EQ(Response::Error::Reason::Server, res.error->reason);
EXPECT_EQ("HTTP status code 500", res.error->message);
- EXPECT_FALSE(bool(res.data));
+ EXPECT_FALSE(res.data);
EXPECT_FALSE(bool(res.expires));
EXPECT_FALSE(res.mustRevalidate);
EXPECT_FALSE(bool(res.modified));
@@ -134,8 +135,8 @@ TEST(HTTPFileSource, TEST_REQUIRES_SERVER(ExpiresParsing)) {
auto req = fs.request({ Resource::Unknown,
"http://127.0.0.1:3000/test?modified=1420794326&expires=1420797926&etag=foo" }, [&](Response res) {
EXPECT_EQ(nullptr, res.error);
- ASSERT_TRUE(res.data.get());
- EXPECT_EQ("Hello World!", *res.data);
+ ASSERT_TRUE(res.data);
+ EXPECT_EQ("Hello World!", *res.data.uncompressedData());
EXPECT_EQ(Timestamp{ Seconds(1420797926) }, res.expires);
EXPECT_FALSE(res.mustRevalidate);
EXPECT_EQ(Timestamp{ Seconds(1420794326) }, res.modified);
@@ -152,8 +153,8 @@ TEST(HTTPFileSource, TEST_REQUIRES_SERVER(CacheControlParsing)) {
auto req = fs.request({ Resource::Unknown, "http://127.0.0.1:3000/test?cachecontrol=max-age=120" }, [&](Response res) {
EXPECT_EQ(nullptr, res.error);
- ASSERT_TRUE(res.data.get());
- EXPECT_EQ("Hello World!", *res.data);
+ ASSERT_TRUE(res.data);
+ EXPECT_EQ("Hello World!", *res.data.uncompressedData());
EXPECT_GT(Seconds(2), util::abs(*res.expires - util::now() - Seconds(120))) << "Expiration date isn't about 120 seconds in the future";
EXPECT_FALSE(res.mustRevalidate);
EXPECT_FALSE(bool(res.modified));
@@ -181,8 +182,8 @@ TEST(HTTPFileSource, TEST_REQUIRES_SERVER(Load)) {
[&, i, current](Response res) {
reqs[i].reset();
EXPECT_EQ(nullptr, res.error);
- ASSERT_TRUE(res.data.get());
- EXPECT_EQ(std::string("Request ") + std::to_string(current), *res.data);
+ ASSERT_TRUE(res.data);
+ EXPECT_EQ(std::string("Request ") + std::to_string(current), *res.data.uncompressedData());
EXPECT_FALSE(bool(res.expires));
EXPECT_FALSE(res.mustRevalidate);
EXPECT_FALSE(bool(res.modified));
diff --git a/test/storage/local_file_source.test.cpp b/test/storage/local_file_source.test.cpp
index e1756f8e7d..76848f6682 100644
--- a/test/storage/local_file_source.test.cpp
+++ b/test/storage/local_file_source.test.cpp
@@ -37,8 +37,8 @@ TEST(LocalFileSource, EmptyFile) {
std::unique_ptr<AsyncRequest> req = fs.request({ Resource::Unknown, toAbsoluteURL("empty") }, [&](Response res) {
req.reset();
EXPECT_EQ(nullptr, res.error);
- ASSERT_TRUE(res.data.get());
- EXPECT_EQ("", *res.data);
+ ASSERT_TRUE(res.data);
+ EXPECT_EQ("", *res.data.uncompressedData());
loop.stop();
});
@@ -53,8 +53,8 @@ TEST(LocalFileSource, NonEmptyFile) {
std::unique_ptr<AsyncRequest> req = fs.request({ Resource::Unknown, toAbsoluteURL("nonempty") }, [&](Response res) {
req.reset();
EXPECT_EQ(nullptr, res.error);
- ASSERT_TRUE(res.data.get());
- EXPECT_EQ("content is here\n", *res.data);
+ ASSERT_TRUE(res.data);
+ EXPECT_EQ("content is here\n", *res.data.uncompressedData());
loop.stop();
});
@@ -70,7 +70,7 @@ TEST(LocalFileSource, NonExistentFile) {
req.reset();
ASSERT_NE(nullptr, res.error);
EXPECT_EQ(Response::Error::Reason::NotFound, res.error->reason);
- ASSERT_FALSE(res.data.get());
+ ASSERT_FALSE(res.data);
// Do not assert on platform-specific error message.
loop.stop();
});
@@ -88,7 +88,7 @@ TEST(LocalFileSource, InvalidURL) {
ASSERT_NE(nullptr, res.error);
EXPECT_EQ(Response::Error::Reason::Other, res.error->reason);
EXPECT_EQ("Invalid file URL", res.error->message);
- ASSERT_FALSE(res.data.get());
+ ASSERT_FALSE(res.data);
loop.stop();
});
@@ -104,7 +104,7 @@ TEST(LocalFileSource, ReadDirectory) {
req.reset();
ASSERT_NE(nullptr, res.error);
EXPECT_EQ(Response::Error::Reason::NotFound, res.error->reason);
- ASSERT_FALSE(res.data.get());
+ ASSERT_FALSE(res.data);
// Do not assert on platform-specific error message.
loop.stop();
});
@@ -120,8 +120,8 @@ TEST(LocalFileSource, URLEncoding) {
std::unique_ptr<AsyncRequest> req = fs.request({ Resource::Unknown, toAbsoluteURL("%6eonempty") }, [&](Response res) {
req.reset();
EXPECT_EQ(nullptr, res.error);
- ASSERT_TRUE(res.data.get());
- EXPECT_EQ("content is here\n", *res.data);
+ ASSERT_TRUE(res.data);
+ EXPECT_EQ("content is here\n", *res.data.uncompressedData());
loop.stop();
});
@@ -142,7 +142,7 @@ TEST(LocalFileSource, URLLimit) {
req.reset();
ASSERT_NE(nullptr, res.error);
EXPECT_EQ(Response::Error::Reason::Other, res.error->reason);
- ASSERT_FALSE(res.data.get());
+ ASSERT_FALSE(res.data);
loop.stop();
});
diff --git a/test/storage/offline_database.test.cpp b/test/storage/offline_database.test.cpp
index 94daf59c02..23e70448b0 100644
--- a/test/storage/offline_database.test.cpp
+++ b/test/storage/offline_database.test.cpp
@@ -34,8 +34,8 @@ void deleteFile(const char* name) {
}
}
-void writeFile(const char* name, const std::string& data) {
- mbgl::util::write_file(name, data);
+void writeFile(const char* name, mbgl::Blob&& data) {
+ mbgl::util::writeFile(name, data);
}
} // namespace
@@ -79,7 +79,7 @@ TEST(OfflineDatabase, TEST_REQUIRES_WRITE(Invalid)) {
createDir("test/fixtures/offline_database");
deleteFile("test/fixtures/offline_database/invalid.db");
- writeFile("test/fixtures/offline_database/invalid.db", "this is an invalid file");
+ writeFile("test/fixtures/offline_database/invalid.db", Blob{ "this is an invalid file", false });
Log::setObserver(std::make_unique<FixtureLogObserver>());
@@ -124,23 +124,23 @@ TEST(OfflineDatabase, PutResource) {
Resource resource { Resource::Style, "http://example.com/" };
Response response;
- response.data = std::make_shared<std::string>("first");
+ response.data = Blob{ "first", false };
auto insertPutResult = db.put(resource, response);
EXPECT_TRUE(insertPutResult.first);
EXPECT_EQ(5u, insertPutResult.second);
auto insertGetResult = db.get(resource);
EXPECT_EQ(nullptr, insertGetResult->error.get());
- EXPECT_EQ("first", *insertGetResult->data);
+ EXPECT_EQ("first", *insertGetResult->data.uncompressedData());
- response.data = std::make_shared<std::string>("second");
+ response.data = Blob{ "second", false };
auto updatePutResult = db.put(resource, response);
EXPECT_FALSE(updatePutResult.first);
EXPECT_EQ(6u, updatePutResult.second);
auto updateGetResult = db.get(resource);
EXPECT_EQ(nullptr, updateGetResult->error.get());
- EXPECT_EQ("second", *updateGetResult->data);
+ EXPECT_EQ("second", *updateGetResult->data.uncompressedData());
}
TEST(OfflineDatabase, PutTile) {
@@ -158,23 +158,23 @@ TEST(OfflineDatabase, PutTile) {
};
Response response;
- response.data = std::make_shared<std::string>("first");
+ response.data = Blob{ "first", false };
auto insertPutResult = db.put(resource, response);
EXPECT_TRUE(insertPutResult.first);
EXPECT_EQ(5u, insertPutResult.second);
auto insertGetResult = db.get(resource);
EXPECT_EQ(nullptr, insertGetResult->error.get());
- EXPECT_EQ("first", *insertGetResult->data);
+ EXPECT_EQ("first", *insertGetResult->data.uncompressedData());
- response.data = std::make_shared<std::string>("second");
+ response.data = Blob{ "second", false };
auto updatePutResult = db.put(resource, response);
EXPECT_FALSE(updatePutResult.first);
EXPECT_EQ(6u, updatePutResult.second);
auto updateGetResult = db.get(resource);
EXPECT_EQ(nullptr, updateGetResult->error.get());
- EXPECT_EQ("second", *updateGetResult->data);
+ EXPECT_EQ("second", *updateGetResult->data.uncompressedData());
}
TEST(OfflineDatabase, PutResourceNoContent) {
@@ -190,7 +190,7 @@ TEST(OfflineDatabase, PutResourceNoContent) {
auto res = db.get(resource);
EXPECT_EQ(nullptr, res->error);
EXPECT_TRUE(res->noContent);
- EXPECT_FALSE(res->data.get());
+ EXPECT_FALSE(res->data);
}
TEST(OfflineDatabase, PutTileNotFound) {
@@ -213,7 +213,7 @@ TEST(OfflineDatabase, PutTileNotFound) {
auto res = db.get(resource);
EXPECT_EQ(nullptr, res->error);
EXPECT_TRUE(res->noContent);
- EXPECT_FALSE(res->data.get());
+ EXPECT_FALSE(res->data);
}
TEST(OfflineDatabase, CreateRegion) {
@@ -344,15 +344,15 @@ TEST(OfflineDatabase, TEST_REQUIRES_WRITE(ConcurrentUse)) {
thread2.join();
}
-static std::shared_ptr<std::string> randomString(size_t size) {
- auto result = std::make_shared<std::string>(size, 0);
+static mbgl::Blob randomBlob(size_t size) {
+ auto result = std::string(size, char());
std::mt19937 random;
for (size_t i = 0; i < size; i++) {
- (*result)[i] = random();
+ result[i] = random();
}
- return result;
+ return { std::move(result), false };
}
TEST(OfflineDatabase, PutReturnsSize) {
@@ -361,11 +361,11 @@ TEST(OfflineDatabase, PutReturnsSize) {
OfflineDatabase db(":memory:");
Response compressible;
- compressible.data = std::make_shared<std::string>(1024, 0);
+ compressible.data = Blob{ std::string(1024, char()), false };
EXPECT_EQ(17u, db.put(Resource::style("http://example.com/compressible"), compressible).second);
Response incompressible;
- incompressible.data = randomString(1024);
+ incompressible.data = randomBlob(1024);
EXPECT_EQ(1024u, db.put(Resource::style("http://example.com/incompressible"), incompressible).second);
Response noContent;
@@ -379,7 +379,7 @@ TEST(OfflineDatabase, PutEvictsLeastRecentlyUsedResources) {
OfflineDatabase db(":memory:", 1024 * 100);
Response response;
- response.data = randomString(1024);
+ response.data = randomBlob(1024);
for (uint32_t i = 1; i <= 100; i++) {
Resource resource = Resource::style("http://example.com/"s + util::toString(i));
@@ -398,7 +398,7 @@ TEST(OfflineDatabase, PutRegionResourceDoesNotEvict) {
OfflineRegion region = db.createRegion(definition, OfflineRegionMetadata());
Response response;
- response.data = randomString(1024);
+ response.data = randomBlob(1024);
for (uint32_t i = 1; i <= 100; i++) {
db.putRegionResource(region.getID(), Resource::style("http://example.com/"s + util::toString(i)), response);
@@ -414,7 +414,7 @@ TEST(OfflineDatabase, PutFailsWhenEvictionInsuffices) {
OfflineDatabase db(":memory:", 1024 * 100);
Response big;
- big.data = randomString(1024 * 100);
+ big.data = randomBlob(1024 * 100);
EXPECT_FALSE(db.put(Resource::style("http://example.com/big"), big).first);
EXPECT_FALSE(bool(db.get(Resource::style("http://example.com/big"))));
@@ -435,7 +435,7 @@ TEST(OfflineDatabase, GetRegionCompletedStatus) {
EXPECT_EQ(0u, status1.completedTileSize);
Response response;
- response.data = std::make_shared<std::string>("data");
+ response.data = Blob{ "data", false };
uint64_t styleSize = db.putRegionResource(region.getID(), Resource::style("http://example.com/"), response);
@@ -465,7 +465,7 @@ TEST(OfflineDatabase, HasRegionResource) {
EXPECT_FALSE(bool(db.hasRegionResource(region.getID(), Resource::style("http://example.com/20"))));
Response response;
- response.data = randomString(1024);
+ response.data = randomBlob(1024);
for (uint32_t i = 1; i <= 100; i++) {
db.putRegionResource(region.getID(), Resource::style("http://example.com/"s + util::toString(i)), response);
@@ -493,7 +493,7 @@ TEST(OfflineDatabase, HasRegionResourceTile) {
};
Response response;
- response.data = std::make_shared<std::string>("first");
+ response.data = Blob{ "first", false };
EXPECT_FALSE(bool(db.hasRegionResource(region.getID(), resource)));
db.putRegionResource(region.getID(), resource, response);
@@ -522,7 +522,7 @@ TEST(OfflineDatabase, OfflineMapboxTileCount) {
Resource mapboxTile2 = Resource::tile("mapbox://tiles/2", 1.0, 0, 0, 1, Tileset::Scheme::XYZ);
Response response;
- response.data = std::make_shared<std::string>("data");
+ response.data = Blob{ "data", false };
// Count is initially zero.
EXPECT_EQ(0u, db.getOfflineMapboxTileCount());
@@ -609,7 +609,7 @@ TEST(OfflineDatabase, MigrateFromV2Schema) {
// v2.db is a v2 database containing a single offline region with a small number of resources.
deleteFile("test/fixtures/offline_database/migrated.db");
- writeFile("test/fixtures/offline_database/migrated.db", util::read_file("test/fixtures/offline_database/v2.db"));
+ writeFile("test/fixtures/offline_database/migrated.db", util::readFile("test/fixtures/offline_database/v2.db"));
{
OfflineDatabase db("test/fixtures/offline_database/migrated.db", 0);
@@ -630,7 +630,7 @@ TEST(OfflineDatabase, MigrateFromV3Schema) {
// v3.db is a v3 database, migrated from v2.
deleteFile("test/fixtures/offline_database/migrated.db");
- writeFile("test/fixtures/offline_database/migrated.db", util::read_file("test/fixtures/offline_database/v3.db"));
+ writeFile("test/fixtures/offline_database/migrated.db", util::readFile("test/fixtures/offline_database/v3.db"));
{
OfflineDatabase db("test/fixtures/offline_database/migrated.db", 0);
@@ -649,7 +649,7 @@ TEST(OfflineDatabase, MigrateFromV4Schema) {
// v4.db is a v4 database, migrated from v2 & v3. This database used `journal_mode = WAL` and `synchronous = NORMAL`.
deleteFile("test/fixtures/offline_database/migrated.db");
- writeFile("test/fixtures/offline_database/migrated.db", util::read_file("test/fixtures/offline_database/v4.db"));
+ writeFile("test/fixtures/offline_database/migrated.db", util::readFile("test/fixtures/offline_database/v4.db"));
{
OfflineDatabase db("test/fixtures/offline_database/migrated.db", 0);
@@ -675,7 +675,7 @@ TEST(OfflineDatabase, MigrateFromV5Schema) {
// v5.db is a v5 database, migrated from v2, v3 & v4.
deleteFile("test/fixtures/offline_database/migrated.db");
- writeFile("test/fixtures/offline_database/migrated.db", util::read_file("test/fixtures/offline_database/v5.db"));
+ writeFile("test/fixtures/offline_database/migrated.db", util::readFile("test/fixtures/offline_database/v5.db"));
{
OfflineDatabase db("test/fixtures/offline_database/migrated.db", 0);
@@ -703,7 +703,7 @@ TEST(OfflineDatabase, DowngradeSchema) {
// and recreated with the current schema.
deleteFile("test/fixtures/offline_database/migrated.db");
- writeFile("test/fixtures/offline_database/migrated.db", util::read_file("test/fixtures/offline_database/v999.db"));
+ writeFile("test/fixtures/offline_database/migrated.db", util::readFile("test/fixtures/offline_database/v999.db"));
{
OfflineDatabase db("test/fixtures/offline_database/migrated.db", 0);
diff --git a/test/storage/offline_download.test.cpp b/test/storage/offline_download.test.cpp
index 57780eba40..f7528fb024 100644
--- a/test/storage/offline_download.test.cpp
+++ b/test/storage/offline_download.test.cpp
@@ -14,7 +14,6 @@
#include <iostream>
using namespace mbgl;
-using namespace std::literals::string_literals;
class MockObserver : public OfflineRegionObserver {
public:
@@ -50,10 +49,11 @@ public:
Response response(const std::string& path) {
Response result;
- result.data = std::make_shared<std::string>(util::read_file("test/fixtures/offline_download/"s + path));
- size_t uncompressed = result.data->size();
- size_t compressed = util::compress(*result.data).size();
- size += std::min(uncompressed, compressed);
+ result.data = util::readFile("test/fixtures/offline_download/" + path);
+ const auto data = util::isCompressible(*result.data.uncompressedData())
+ ? result.data.compressedData()
+ : result.data.uncompressedData();
+ size += data->size();
return result;
}
};
diff --git a/test/storage/online_file_source.test.cpp b/test/storage/online_file_source.test.cpp
index 70bfe3ac95..9744c0a02e 100644
--- a/test/storage/online_file_source.test.cpp
+++ b/test/storage/online_file_source.test.cpp
@@ -33,8 +33,8 @@ TEST(OnlineFileSource, TEST_REQUIRES_SERVER(CancelMultiple)) {
std::unique_ptr<AsyncRequest> req = fs.request(resource, [&](Response res) {
req.reset();
EXPECT_EQ(nullptr, res.error);
- ASSERT_TRUE(res.data.get());
- EXPECT_EQ("Hello World!", *res.data);
+ ASSERT_TRUE(res.data);
+ EXPECT_EQ("Hello World!", *res.data.uncompressedData());
EXPECT_FALSE(bool(res.expires));
EXPECT_FALSE(res.mustRevalidate);
EXPECT_FALSE(bool(res.modified));
@@ -61,7 +61,7 @@ TEST(OnlineFileSource, TEST_REQUIRES_SERVER(TemporaryError)) {
ASSERT_NE(nullptr, res.error);
EXPECT_EQ(Response::Error::Reason::Server, res.error->reason);
EXPECT_EQ("HTTP status code 500", res.error->message);
- ASSERT_FALSE(bool(res.data));
+ ASSERT_FALSE(res.data);
EXPECT_FALSE(bool(res.expires));
EXPECT_FALSE(res.mustRevalidate);
EXPECT_FALSE(bool(res.modified));
@@ -72,8 +72,8 @@ TEST(OnlineFileSource, TEST_REQUIRES_SERVER(TemporaryError)) {
EXPECT_LT(0.99, duration) << "Backoff timer didn't wait 1 second";
EXPECT_GT(1.2, duration) << "Backoff timer fired too late";
EXPECT_EQ(nullptr, res.error);
- ASSERT_TRUE(res.data.get());
- EXPECT_EQ("Hello World!", *res.data);
+ ASSERT_TRUE(res.data);
+ EXPECT_EQ("Hello World!", *res.data.uncompressedData());
EXPECT_FALSE(bool(res.expires));
EXPECT_FALSE(res.mustRevalidate);
EXPECT_FALSE(bool(res.modified));
@@ -100,7 +100,7 @@ TEST(OnlineFileSource, TEST_REQUIRES_SERVER(ConnectionError)) {
EXPECT_GT(wait + 0.2, duration) << "Backoff timer fired too late";
ASSERT_NE(nullptr, res.error);
EXPECT_EQ(Response::Error::Reason::Connection, res.error->reason);
- ASSERT_FALSE(res.data.get());
+ ASSERT_FALSE(res.data);
EXPECT_FALSE(bool(res.expires));
EXPECT_FALSE(res.mustRevalidate);
EXPECT_FALSE(bool(res.modified));
@@ -127,8 +127,8 @@ TEST(OnlineFileSource, TEST_REQUIRES_SERVER(Timeout)) {
std::unique_ptr<AsyncRequest> req = fs.request(resource, [&](Response res) {
counter++;
EXPECT_EQ(nullptr, res.error);
- ASSERT_TRUE(res.data.get());
- EXPECT_EQ("Hello World!", *res.data);
+ ASSERT_TRUE(res.data);
+ EXPECT_EQ("Hello World!", *res.data.uncompressedData());
EXPECT_TRUE(bool(res.expires));
EXPECT_FALSE(res.mustRevalidate);
EXPECT_FALSE(bool(res.modified));
@@ -244,8 +244,8 @@ TEST(OnlineFileSource, TEST_REQUIRES_SERVER(Load)) {
[&, i, current](Response res) {
reqs[i].reset();
EXPECT_EQ(nullptr, res.error);
- ASSERT_TRUE(res.data.get());
- EXPECT_EQ(std::string("Request ") + std::to_string(current), *res.data);
+ ASSERT_TRUE(res.data);
+ EXPECT_EQ(std::string("Request ") + std::to_string(current), *res.data.uncompressedData());
EXPECT_FALSE(bool(res.expires));
EXPECT_FALSE(res.mustRevalidate);
EXPECT_FALSE(bool(res.modified));
@@ -282,8 +282,8 @@ TEST(OnlineFileSource, TEST_REQUIRES_SERVER(NetworkStatusChange)) {
std::unique_ptr<AsyncRequest> req = fs.request(resource, [&](Response res) {
req.reset();
EXPECT_EQ(nullptr, res.error);
- ASSERT_TRUE(res.data.get());
- EXPECT_EQ("Response", *res.data);
+ ASSERT_TRUE(res.data);
+ EXPECT_EQ("Response", *res.data.uncompressedData());
EXPECT_FALSE(bool(res.expires));
EXPECT_FALSE(res.mustRevalidate);
EXPECT_FALSE(bool(res.modified));
@@ -322,7 +322,7 @@ TEST(OnlineFileSource, TEST_REQUIRES_SERVER(NetworkStatusChangePreempt)) {
}
ASSERT_NE(nullptr, res.error);
EXPECT_EQ(Response::Error::Reason::Connection, res.error->reason);
- ASSERT_FALSE(res.data.get());
+ ASSERT_FALSE(res.data);
EXPECT_FALSE(bool(res.expires));
EXPECT_FALSE(res.mustRevalidate);
EXPECT_FALSE(bool(res.modified));
@@ -361,7 +361,7 @@ TEST(OnlineFileSource, TEST_REQUIRES_SERVER(NetworkStatusOnlineOffline)) {
req.reset();
EXPECT_EQ(nullptr, res.error);
- ASSERT_TRUE(res.data.get());
+ ASSERT_TRUE(res.data);
EXPECT_EQ(NetworkStatus::Get(), NetworkStatus::Status::Online) << "Triggered before set back to Online";
diff --git a/test/style/expression/expression.test.cpp b/test/style/expression/expression.test.cpp
index 694569695c..c40f3fb863 100644
--- a/test/style/expression/expression.test.cpp
+++ b/test/style/expression/expression.test.cpp
@@ -16,8 +16,9 @@ using namespace mbgl;
using namespace mbgl::style;
TEST(Expression, IsExpression) {
+ const auto file = util::readFile("mapbox-gl-js/src/style-spec/reference/v8.json").uncompressedData();
rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> spec;
- spec.Parse<0>(util::read_file("mapbox-gl-js/src/style-spec/reference/v8.json").c_str());
+ spec.Parse<0>(file->c_str());
ASSERT_FALSE(spec.HasParseError());
ASSERT_TRUE(spec.IsObject() &&
spec.HasMember("expression_name") &&
@@ -44,8 +45,9 @@ TEST_P(ExpressionEqualityTest, ExpressionEquality) {
std::string error;
auto parse = [&](std::string filename, std::string& error_) -> std::unique_ptr<expression::Expression> {
+ const auto file = util::readFile(filename).uncompressedData();
rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> document;
- document.Parse<0>(util::read_file(filename).c_str());
+ document.Parse<0>(file->c_str());
assert(!document.HasParseError());
const JSValue* expression = &document;
expression::ParsingContext ctx;
diff --git a/test/style/source.test.cpp b/test/style/source.test.cpp
index 6cb01146f6..94eb66a789 100644
--- a/test/style/source.test.cpp
+++ b/test/style/source.test.cpp
@@ -121,7 +121,7 @@ TEST(Source, LoadingCorrupt) {
test.fileSource.sourceResponse = [&] (const Resource& resource) {
EXPECT_EQ("url", resource.url);
Response response;
- response.data = std::make_unique<std::string>("CORRUPTED");
+ response.data = Blob{ "CORRUPTED", false };
return response;
};
@@ -375,7 +375,7 @@ TEST(Source, RasterTileCorrupt) {
test.fileSource.tileResponse = [&] (const Resource&) {
Response response;
- response.data = std::make_unique<std::string>("CORRUPTED");
+ response.data = Blob{ "CORRUPTED", false };
return response;
};
@@ -412,7 +412,7 @@ TEST(Source, RasterDEMTileCorrupt) {
test.fileSource.tileResponse = [&] (const Resource&) {
Response response;
- response.data = std::make_unique<std::string>("CORRUPTED");
+ response.data = Blob{ "CORRUPTED", false };
return response;
};
@@ -449,7 +449,7 @@ TEST(Source, VectorTileCorrupt) {
test.fileSource.tileResponse = [&] (const Resource&) {
Response response;
- response.data = std::make_unique<std::string>("CORRUPTED");
+ response.data = Blob{ "CORRUPTED", false };
return response;
};
@@ -610,9 +610,10 @@ TEST(Source, RasterTileAttribution) {
test.fileSource.sourceResponse = [&] (const Resource& resource) {
EXPECT_EQ("url", resource.url);
Response response;
- response.data = std::make_unique<std::string>(R"TILEJSON({ "tilejson": "2.1.0", "attribution": ")TILEJSON" +
- mapboxOSM +
- R"TILEJSON(", "tiles": [ "tiles" ] })TILEJSON");
+ response.data =
+ Blob{ R"TILEJSON({ "tilejson": "2.1.0", "attribution": ")TILEJSON" + mapboxOSM +
+ R"TILEJSON(", "tiles": [ "tiles" ] })TILEJSON",
+ false };
return response;
};
@@ -653,9 +654,10 @@ TEST(Source, RasterDEMTileAttribution) {
test.fileSource.sourceResponse = [&] (const Resource& resource) {
EXPECT_EQ("url", resource.url);
Response response;
- response.data = std::make_unique<std::string>(R"TILEJSON({ "tilejson": "2.1.0", "attribution": ")TILEJSON" +
- mapbox +
- R"TILEJSON(", "tiles": [ "tiles" ] })TILEJSON");
+ response.data =
+ Blob{ R"TILEJSON({ "tilejson": "2.1.0", "attribution": ")TILEJSON" + mapbox +
+ R"TILEJSON(", "tiles": [ "tiles" ] })TILEJSON",
+ false };
return response;
};
@@ -684,7 +686,7 @@ TEST(Source, GeoJSonSourceUrlUpdate) {
test.fileSource.sourceResponse = [&] (const Resource& resource) {
EXPECT_EQ("url", resource.url);
Response response;
- response.data = std::make_unique<std::string>(R"({"geometry": {"type": "Point", "coordinates": [1.1, 1.1]}, "type": "Feature", "properties": {}})");
+ response.data = Blob{ R"({"geometry": {"type": "Point", "coordinates": [1.1, 1.1]}, "type": "Feature", "properties": {}})", false };
return response;
};
@@ -714,7 +716,7 @@ TEST(Source, ImageSourceImageUpdate) {
test.fileSource.response = [&] (const Resource& resource) {
EXPECT_EQ("http://url", resource.url);
Response response;
- response.data = std::make_unique<std::string>(util::read_file("test/fixtures/image/no_profile.png"));
+ response.data = util::readFile("test/fixtures/image/no_profile.png");
return response;
};
test.styleObserver.sourceChanged = [&] (Source&) {
diff --git a/test/style/style.test.cpp b/test/style/style.test.cpp
index 9bdab37ac6..91ecbe8d22 100644
--- a/test/style/style.test.cpp
+++ b/test/style/style.test.cpp
@@ -23,27 +23,27 @@ TEST(Style, Properties) {
StubFileSource fileSource;
Style::Impl style { threadPool, fileSource, 1.0 };
- style.loadJSON(R"STYLE({"name": "Test"})STYLE");
+ style.loadJSON(Blob{ R"STYLE({"name": "Test"})STYLE", false });
ASSERT_EQ("Test", style.getName());
- style.loadJSON(R"STYLE({"center": [10, 20]})STYLE");
+ style.loadJSON(Blob{ R"STYLE({"center": [10, 20]})STYLE", false });
ASSERT_EQ("", style.getName());
ASSERT_EQ((LatLng{20, 10}), *style.getDefaultCamera().center);
- style.loadJSON(R"STYLE({"bearing": 24})STYLE");
+ style.loadJSON(Blob{ R"STYLE({"bearing": 24})STYLE", false });
ASSERT_EQ("", style.getName());
ASSERT_EQ(LatLng {}, *style.getDefaultCamera().center);
ASSERT_EQ(24, *style.getDefaultCamera().angle);
- style.loadJSON(R"STYLE({"zoom": 13.3})STYLE");
+ style.loadJSON(Blob{ R"STYLE({"zoom": 13.3})STYLE", false });
ASSERT_EQ("", style.getName());
ASSERT_EQ(13.3, *style.getDefaultCamera().zoom);
- style.loadJSON(R"STYLE({"pitch": 60})STYLE");
+ style.loadJSON(Blob{ R"STYLE({"pitch": 60})STYLE", false });
ASSERT_EQ("", style.getName());
ASSERT_EQ(60, *style.getDefaultCamera().pitch);
- style.loadJSON(R"STYLE({"name": 23, "center": {}, "bearing": "north", "zoom": null, "pitch": "wide"})STYLE");
+ style.loadJSON(Blob{ R"STYLE({"name": 23, "center": {}, "bearing": "north", "zoom": null, "pitch": "wide"})STYLE", false });
ASSERT_EQ("", style.getName());
ASSERT_EQ(LatLng {}, *style.getDefaultCamera().center);
ASSERT_EQ(0, *style.getDefaultCamera().zoom);
@@ -58,7 +58,7 @@ TEST(Style, DuplicateSource) {
StubFileSource fileSource;
Style::Impl style { threadPool, fileSource, 1.0 };
- style.loadJSON(util::read_file("test/fixtures/resources/style-unused-sources.json"));
+ style.loadJSON(util::readFile("test/fixtures/resources/style-unused-sources.json"));
style.addSource(std::make_unique<VectorSource>("sourceId", "mapbox://mapbox.mapbox-terrain-v2"));
@@ -80,7 +80,7 @@ TEST(Style, RemoveSourceInUse) {
StubFileSource fileSource;
Style::Impl style { threadPool, fileSource, 1.0 };
- style.loadJSON(util::read_file("test/fixtures/resources/style-unused-sources.json"));
+ style.loadJSON(util::readFile("test/fixtures/resources/style-unused-sources.json"));
style.addSource(std::make_unique<VectorSource>("sourceId", "mapbox://mapbox.mapbox-terrain-v2"));
style.addLayer(std::make_unique<LineLayer>("layerId", "sourceId"));
diff --git a/test/style/style_layer.test.cpp b/test/style/style_layer.test.cpp
index 77acca2868..36fd7de3f4 100644
--- a/test/style/style_layer.test.cpp
+++ b/test/style/style_layer.test.cpp
@@ -276,7 +276,7 @@ TEST(Layer, DuplicateLayer) {
ThreadPool threadPool{ 1 };
StubFileSource fileSource;
Style::Impl style { threadPool, fileSource, 1.0 };
- style.loadJSON(util::read_file("test/fixtures/resources/style-unused-sources.json"));
+ style.loadJSON(util::readFile("test/fixtures/resources/style-unused-sources.json"));
// Add initial layer
style.addLayer(std::make_unique<LineLayer>("line", "unusedsource"));
diff --git a/test/style/style_parser.test.cpp b/test/style/style_parser.test.cpp
index 43b982c3b9..c6b78cf6d6 100644
--- a/test/style/style_parser.test.cpp
+++ b/test/style/style_parser.test.cpp
@@ -24,16 +24,18 @@ class StyleParserTest : public ::testing::TestWithParam<std::string> {};
TEST_P(StyleParserTest, ParseStyle) {
const std::string base = std::string("test/fixtures/style_parser/") + GetParam();
+ const auto infoFile = util::readFile(base + ".info.json").uncompressedData();
rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> infoDoc;
- infoDoc.Parse<0>(util::read_file(base + ".info.json").c_str());
+ infoDoc.Parse<0>(infoFile->c_str());
ASSERT_FALSE(infoDoc.HasParseError());
ASSERT_TRUE(infoDoc.IsObject());
auto observer = new FixtureLogObserver();
Log::setObserver(std::unique_ptr<Log::Observer>(observer));
+ const auto styleFile = util::readFile(base + ".style.json").uncompressedData();
style::Parser parser;
- auto error = parser.parse(util::read_file(base + ".style.json"));
+ auto error = parser.parse(*styleFile);
if (error) {
Log::Error(Event::ParseStyle, "Failed to parse style: %s", util::toString(error).c_str());
@@ -95,7 +97,7 @@ INSTANTIATE_TEST_CASE_P(StyleParser, StyleParserTest, ::testing::ValuesIn([] {
TEST(StyleParser, FontStacks) {
style::Parser parser;
- parser.parse(util::read_file("test/fixtures/style_parser/font_stacks.json"));
+ parser.parse(*util::readFile("test/fixtures/style_parser/font_stacks.json").uncompressedData());
auto result = parser.fontStacks();
ASSERT_EQ(3u, result.size());
ASSERT_EQ(FontStack({"a"}), result[0]);
diff --git a/test/text/glyph_manager.test.cpp b/test/text/glyph_manager.test.cpp
index a96e1b970c..be1c13eefc 100644
--- a/test/text/glyph_manager.test.cpp
+++ b/test/text/glyph_manager.test.cpp
@@ -92,7 +92,7 @@ TEST(GlyphManager, LoadingSuccess) {
test.fileSource.glyphsResponse = [&] (const Resource& resource) {
EXPECT_EQ(Resource::Kind::Glyphs, resource.kind);
Response response;
- response.data = std::make_shared<std::string>(util::read_file("test/fixtures/resources/glyphs.pbf"));
+ response.data = util::readFile("test/fixtures/resources/glyphs.pbf");
return response;
};
@@ -163,7 +163,7 @@ TEST(GlyphManager, LoadingCorrupted) {
test.fileSource.glyphsResponse = [&] (const Resource&) {
Response response;
- response.data = std::make_unique<std::string>("CORRUPTED");
+ response.data = Blob{ "CORRUPTED", false };
return response;
};
@@ -260,7 +260,7 @@ TEST(GlyphManager, LoadingInvalid) {
test.fileSource.glyphsResponse = [&] (const Resource& resource) {
EXPECT_EQ(Resource::Kind::Glyphs, resource.kind);
Response response;
- response.data = std::make_shared<std::string>(util::read_file("test/fixtures/resources/fake_glyphs-0-255.pbf"));
+ response.data = util::readFile("test/fixtures/resources/fake_glyphs-0-255.pbf");
return response;
};
@@ -320,7 +320,7 @@ TEST(GlyphManager, ImmediateFileSource) {
test.fileSource.glyphsResponse = [&] (const Resource&) {
Response response;
- response.data = std::make_shared<std::string>(util::read_file("test/fixtures/resources/glyphs.pbf"));
+ response.data = util::readFile("test/fixtures/resources/glyphs.pbf");
return response;
};
diff --git a/test/text/glyph_pbf.test.cpp b/test/text/glyph_pbf.test.cpp
index c222ec1dd9..8c6b8a2028 100644
--- a/test/text/glyph_pbf.test.cpp
+++ b/test/text/glyph_pbf.test.cpp
@@ -7,7 +7,7 @@ using namespace mbgl;
TEST(GlyphPBF, Parsing) {
// The fake glyphs contain a number of invalid glyphs, which should be skipped by the parser.
- auto sdfs = parseGlyphPBF(GlyphRange { 0, 255 }, util::read_file("test/fixtures/resources/fake_glyphs-0-255.pbf"));
+ auto sdfs = parseGlyphPBF(GlyphRange { 0, 255 }, util::readFile("test/fixtures/resources/fake_glyphs-0-255.pbf"));
EXPECT_TRUE(sdfs.size() == 1);
auto& sdf = sdfs[0];
diff --git a/test/text/local_glyph_rasterizer.test.cpp b/test/text/local_glyph_rasterizer.test.cpp
index 84c685d66f..49ef1e18ef 100644
--- a/test/text/local_glyph_rasterizer.test.cpp
+++ b/test/text/local_glyph_rasterizer.test.cpp
@@ -60,10 +60,10 @@ TEST(LocalGlyphRasterizer, PingFang) {
test.fileSource.glyphsResponse = [&] (const Resource& resource) {
EXPECT_EQ(Resource::Kind::Glyphs, resource.kind);
Response response;
- response.data = std::make_shared<std::string>(util::read_file("test/fixtures/resources/glyphs.pbf"));
+ response.data = util::readFile("test/fixtures/resources/glyphs.pbf");
return response;
};
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/local_glyphs/mixed.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/local_glyphs/mixed.json"));
test.checkRendering("ping_fang");
}
@@ -77,10 +77,10 @@ TEST(LocalGlyphRasterizer, NoLocal) {
test.fileSource.glyphsResponse = [&] (const Resource& resource) {
EXPECT_EQ(Resource::Kind::Glyphs, resource.kind);
Response response;
- response.data = std::make_shared<std::string>(util::read_file("test/fixtures/resources/glyphs.pbf"));
+ response.data = util::readFile("test/fixtures/resources/glyphs.pbf");
return response;
};
- test.map.getStyle().loadJSON(util::read_file("test/fixtures/local_glyphs/mixed.json"));
+ test.map.getStyle().loadJSON(util::readFile("test/fixtures/local_glyphs/mixed.json"));
test.checkRendering("no_local");
}
diff --git a/test/util/image.test.cpp b/test/util/image.test.cpp
index f4a6473040..f9389a694a 100644
--- a/test/util/image.test.cpp
+++ b/test/util/image.test.cpp
@@ -35,7 +35,7 @@ TEST(Image, PNGRoundTripAlpha) {
}
TEST(Image, PNGReadNoProfile) {
- PremultipliedImage image = decodeImage(util::read_file("test/fixtures/image/no_profile.png"));
+ PremultipliedImage image = decodeImage(util::readFile("test/fixtures/image/no_profile.png"));
EXPECT_EQ(128, image.data[0]);
EXPECT_EQ(0, image.data[1]);
EXPECT_EQ(0, image.data[2]);
@@ -43,7 +43,7 @@ TEST(Image, PNGReadNoProfile) {
}
TEST(Image, PNGReadNoProfileAlpha) {
- PremultipliedImage image = decodeImage(util::read_file("test/fixtures/image/no_profile_alpha.png"));
+ PremultipliedImage image = decodeImage(util::readFile("test/fixtures/image/no_profile_alpha.png"));
EXPECT_EQ(64, image.data[0]);
EXPECT_EQ(0, image.data[1]);
EXPECT_EQ(0, image.data[2]);
@@ -51,7 +51,7 @@ TEST(Image, PNGReadNoProfileAlpha) {
}
TEST(Image, PNGReadProfile) {
- PremultipliedImage image = decodeImage(util::read_file("test/fixtures/image/profile.png"));
+ PremultipliedImage image = decodeImage(util::readFile("test/fixtures/image/profile.png"));
EXPECT_EQ(128, image.data[0]);
EXPECT_EQ(0, image.data[1]);
EXPECT_EQ(0, image.data[2]);
@@ -59,7 +59,7 @@ TEST(Image, PNGReadProfile) {
}
TEST(Image, PNGReadProfileAlpha) {
- PremultipliedImage image = decodeImage(util::read_file("test/fixtures/image/profile_alpha.png"));
+ PremultipliedImage image = decodeImage(util::readFile("test/fixtures/image/profile_alpha.png"));
EXPECT_EQ(64, image.data[0]);
EXPECT_EQ(0, image.data[1]);
EXPECT_EQ(0, image.data[2]);
@@ -67,20 +67,20 @@ TEST(Image, PNGReadProfileAlpha) {
}
TEST(Image, PNGTile) {
- PremultipliedImage image = decodeImage(util::read_file("test/fixtures/image/tile.png"));
+ PremultipliedImage image = decodeImage(util::readFile("test/fixtures/image/tile.png"));
EXPECT_EQ(256u, image.size.width);
EXPECT_EQ(256u, image.size.height);
}
TEST(Image, JPEGTile) {
- PremultipliedImage image = decodeImage(util::read_file("test/fixtures/image/tile.jpeg"));
+ PremultipliedImage image = decodeImage(util::readFile("test/fixtures/image/tile.jpeg"));
EXPECT_EQ(256u, image.size.width);
EXPECT_EQ(256u, image.size.height);
}
#if !defined(__ANDROID__) && !defined(__APPLE__) && !defined(QT_IMAGE_DECODERS)
TEST(Image, WebPTile) {
- PremultipliedImage image = decodeImage(util::read_file("test/fixtures/image/tile.webp"));
+ PremultipliedImage image = decodeImage(util::readFile("test/fixtures/image/tile.webp"));
EXPECT_EQ(256u, image.size.width);
EXPECT_EQ(256u, image.size.height);
}
diff --git a/test/util/memory.test.cpp b/test/util/memory.test.cpp
index 6befb521f0..4f14c762b4 100644
--- a/test/util/memory.test.cpp
+++ b/test/util/memory.test.cpp
@@ -45,9 +45,7 @@ private:
if (it != cache.end()) {
result.data = it->second;
} else {
- auto data = std::make_shared<std::string>(
- util::read_file("test/fixtures/resources/"s + path));
-
+ auto data = util::readFile("test/fixtures/resources/" + path);
cache.insert(it, std::make_pair(path, data));
result.data = data;
}
@@ -63,7 +61,7 @@ private:
}
};
- std::unordered_map<std::string, std::shared_ptr<std::string>> cache;
+ std::unordered_map<std::string, Blob> cache;
};
TEST(Memory, Vector) {