summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt8
-rw-r--r--bin/offline.cpp6
-rw-r--r--cmake/core-files.cmake1
-rw-r--r--cmake/filesource.cmake3
-rw-r--r--cmake/mbgl.cmake55
-rw-r--r--include/mbgl/storage/default_file_source.hpp15
-rw-r--r--include/mbgl/storage/offline.hpp2
-rw-r--r--platform/android/config.cmake1
-rw-r--r--platform/android/src/offline/offline_manager.cpp23
-rw-r--r--platform/android/src/offline/offline_region.cpp20
-rw-r--r--platform/darwin/src/MGLOfflinePack.mm2
-rw-r--r--platform/darwin/src/MGLOfflineStorage.mm24
-rw-r--r--platform/default/default_file_source.cpp58
-rw-r--r--platform/default/mbgl/storage/offline_database.cpp35
-rw-r--r--platform/default/mbgl/storage/offline_database.hpp16
-rw-r--r--platform/ios/ios.xcodeproj/project.pbxproj10
-rw-r--r--scripts/config.xcconfig.in8
-rw-r--r--test/storage/offline_database.test.cpp37
-rw-r--r--test/storage/offline_download.test.cpp2
19 files changed, 156 insertions, 170 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b6b86d9a8d..a02b4b9173 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -176,8 +176,10 @@ if(WITH_NODEJS AND COMMAND mbgl_platform_node)
endif()
if(CMAKE_GENERATOR STREQUAL "Xcode")
- write_xcconfig_target_properties(
- mbgl-core
- mbgl-filesource
+ set_xcconfig_target_properties(mbgl-core)
+ set_xcconfig_target_properties(mbgl-filesource)
+ file(GENERATE
+ OUTPUT "${CMAKE_BINARY_DIR}/config.xcconfig"
+ INPUT "${CMAKE_SOURCE_DIR}/scripts/config.xcconfig.in"
)
endif()
diff --git a/bin/offline.cpp b/bin/offline.cpp
index 8b42ab7b72..603f0b848a 100644
--- a/bin/offline.cpp
+++ b/bin/offline.cpp
@@ -136,9 +136,9 @@ int main(int argc, char *argv[]) {
std::signal(SIGINT, [] (int) { stop(); });
- fileSource.createOfflineRegion(definition, metadata, [&] (std::exception_ptr error, optional<OfflineRegion> region_) {
- if (error) {
- std::cerr << "Error creating region: " << util::toString(error) << std::endl;
+ fileSource.createOfflineRegion(definition, metadata, [&] (mbgl::expected<OfflineRegion, std::exception_ptr> region_) {
+ if (!region_) {
+ std::cerr << "Error creating region: " << util::toString(region_.error()) << std::endl;
loop.stop();
exit(1);
} else {
diff --git a/cmake/core-files.cmake b/cmake/core-files.cmake
index e875f5b142..02335fef7a 100644
--- a/cmake/core-files.cmake
+++ b/cmake/core-files.cmake
@@ -664,6 +664,7 @@ set(MBGL_CORE_FILES
include/mbgl/util/enum.hpp
include/mbgl/util/event.hpp
include/mbgl/util/exception.hpp
+ include/mbgl/util/expected.hpp
include/mbgl/util/feature.hpp
include/mbgl/util/font_stack.hpp
include/mbgl/util/geo.hpp
diff --git a/cmake/filesource.cmake b/cmake/filesource.cmake
index ccd2192f39..9b7a4a1138 100644
--- a/cmake/filesource.cmake
+++ b/cmake/filesource.cmake
@@ -1,3 +1,5 @@
+add_vendor_target(expected INTERFACE)
+
add_library(mbgl-filesource STATIC
# File source
include/mbgl/storage/default_file_source.hpp
@@ -39,6 +41,7 @@ target_include_directories(mbgl-filesource
target_link_libraries(mbgl-filesource
PUBLIC mbgl-core
+ PUBLIC expected
)
mbgl_filesource()
diff --git a/cmake/mbgl.cmake b/cmake/mbgl.cmake
index bb029a47db..3abc974feb 100644
--- a/cmake/mbgl.cmake
+++ b/cmake/mbgl.cmake
@@ -115,13 +115,15 @@ endfunction()
# Creates a library target for a vendored dependency
function(add_vendor_target NAME TYPE)
- add_library(${NAME} ${TYPE} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/empty.cpp")
set(INCLUDE_TYPE "INTERFACE")
set(SOURCE_TYPE "INTERFACE")
if (TYPE STREQUAL "STATIC" OR TYPE STREQUAL "SHARED")
+ add_library(${NAME} ${TYPE} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/empty.cpp")
set(INCLUDE_TYPE "PUBLIC")
set(SOURCE_TYPE "PRIVATE")
set_target_properties(${NAME} PROPERTIES SOURCES "")
+ else()
+ add_library(${NAME} ${TYPE})
endif()
set_target_properties(${NAME} PROPERTIES INTERFACE_SOURCES "")
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/vendor/${NAME}/files.txt" FILES)
@@ -137,48 +139,25 @@ macro(set_xcode_property TARGET XCODE_PROPERTY XCODE_VALUE)
set_property(TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY} ${XCODE_VALUE})
endmacro (set_xcode_property)
-function(_get_xcconfig_property target var)
- get_property(result TARGET ${target} PROPERTY INTERFACE_${var} SET)
- if (result)
- get_property(result TARGET ${target} PROPERTY INTERFACE_${var})
- if (var STREQUAL "LINK_LIBRARIES")
- # Remove target names from the list of linker flags, since Xcode can't deal with them.
- set(link_flags)
- foreach(item IN LISTS result)
- if (NOT TARGET ${item})
- list(APPEND link_flags ${item})
- endif()
- endforeach()
- set(result "${link_flags}")
+function(set_xcconfig_target_properties target)
+ # Create a list of linked libraries for use in the xcconfig generation script.
+ get_property(result TARGET ${target} PROPERTY INTERFACE_LINK_LIBRARIES)
+ string(GENEX_STRIP "${result}" result)
+ # Remove target names from the list of linker flags, since Xcode can't deal with them.
+ set(link_flags)
+ foreach(item IN LISTS result)
+ if (NOT TARGET ${item})
+ list(APPEND link_flags ${item})
endif()
- string(REPLACE ";-framework " ";-framework;" result "${result}")
- string(REPLACE ";" "\" \"" result "${result}")
- string(REPLACE "-" "_" target "${target}")
- set(${target}_${var} "${result}" PARENT_SCOPE)
- endif()
-endfunction()
-
-if(MBGL_PLATFORM STREQUAL "ios")
- execute_process(
- COMMAND git submodule update --init platform/ios/vendor/mapbox-events-ios
- WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
-endif()
-
-function(write_xcconfig_target_properties)
- foreach(target ${ARGN})
- _get_xcconfig_property(${target} INCLUDE_DIRECTORIES)
- _get_xcconfig_property(${target} LINK_LIBRARIES)
endforeach()
- configure_file(
- "${CMAKE_SOURCE_DIR}/scripts/config.xcconfig.in"
- "${CMAKE_BINARY_DIR}/config.xcconfig"
- @ONLY
- )
+ string(REPLACE ";-framework " ";-framework;" link_flags "${link_flags}")
+ string(REPLACE ";" "\" \"" link_flags "${link_flags}")
+ set_xcode_property(${target} XCCONFIG_LINK_LIBRARIES "${link_flags}")
endfunction()
# Set Xcode project build settings to be consistent with the CXX flags we're
# using. (Otherwise, Xcode's defaults may override some of these.)
-macro(initialize_xcode_cxx_build_settings target)
+function(initialize_xcode_cxx_build_settings target)
# -Wall
set_xcode_property(${target} GCC_WARN_SIGN_COMPARE YES)
set_xcode_property(${target} GCC_WARN_UNINITIALIZED_AUTOS YES)
@@ -206,7 +185,7 @@ macro(initialize_xcode_cxx_build_settings target)
# -flto
set_xcode_property(${target} LLVM_LTO $<$<OR:$<CONFIG:Release>,$<CONFIG:RelWithDebugInfo>>:YES>)
-endmacro(initialize_xcode_cxx_build_settings)
+endfunction()
# CMake 3.1 does not have this yet.
set(CMAKE_CXX14_STANDARD_COMPILE_OPTION "-std=c++14")
diff --git a/include/mbgl/storage/default_file_source.hpp b/include/mbgl/storage/default_file_source.hpp
index b9c8de5052..e048d82af2 100644
--- a/include/mbgl/storage/default_file_source.hpp
+++ b/include/mbgl/storage/default_file_source.hpp
@@ -5,6 +5,7 @@
#include <mbgl/storage/offline.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/optional.hpp>
+#include <mbgl/util/expected.hpp>
#include <vector>
#include <mutex>
@@ -55,8 +56,7 @@ public:
* callback, which will be executed on the database thread; it is the responsibility
* of the SDK bindings to re-execute a user-provided callback on the main thread.
*/
- void listOfflineRegions(std::function<void (std::exception_ptr,
- optional<std::vector<OfflineRegion>>)>);
+ void listOfflineRegions(std::function<void (expected<OfflineRegions, std::exception_ptr>)>);
/*
* Create an offline region in the database.
@@ -71,16 +71,14 @@ public:
*/
void createOfflineRegion(const OfflineRegionDefinition& definition,
const OfflineRegionMetadata& metadata,
- std::function<void (std::exception_ptr,
- optional<OfflineRegion>)>);
+ std::function<void (expected<OfflineRegion, std::exception_ptr>)>);
/*
* Update an offline region metadata in the database.
*/
void updateOfflineMetadata(const int64_t regionID,
const OfflineRegionMetadata& metadata,
- std::function<void (std::exception_ptr,
- optional<OfflineRegionMetadata>)>);
+ std::function<void (expected<OfflineRegionMetadata, std::exception_ptr>)>);
/*
* Register an observer to be notified when the state of the region changes.
*/
@@ -97,8 +95,9 @@ public:
* executed on the database thread; it is the responsibility of the SDK bindings
* to re-execute a user-provided callback on the main thread.
*/
- void getOfflineRegionStatus(OfflineRegion&, std::function<void (std::exception_ptr,
- optional<OfflineRegionStatus>)>) const;
+ void getOfflineRegionStatus(
+ OfflineRegion&,
+ std::function<void (expected<OfflineRegionStatus, std::exception_ptr>)>) const;
/*
* Remove an offline region from the database and perform any resources evictions
diff --git a/include/mbgl/storage/offline.hpp b/include/mbgl/storage/offline.hpp
index 2193f8d09e..62353446fa 100644
--- a/include/mbgl/storage/offline.hpp
+++ b/include/mbgl/storage/offline.hpp
@@ -210,4 +210,6 @@ private:
const OfflineRegionMetadata metadata;
};
+using OfflineRegions = std::vector<OfflineRegion>;
+
} // namespace mbgl
diff --git a/platform/android/config.cmake b/platform/android/config.cmake
index 001a45e613..bd65bc517f 100644
--- a/platform/android/config.cmake
+++ b/platform/android/config.cmake
@@ -97,6 +97,7 @@ macro(mbgl_platform_core)
target_link_libraries(mbgl-core
PRIVATE nunicode
+ PUBLIC expected
PUBLIC -llog
PUBLIC -landroid
PUBLIC -ljnigraphics
diff --git a/platform/android/src/offline/offline_manager.cpp b/platform/android/src/offline/offline_manager.cpp
index 4960ae2845..4f94a1c3a5 100644
--- a/platform/android/src/offline/offline_manager.cpp
+++ b/platform/android/src/offline/offline_manager.cpp
@@ -26,15 +26,18 @@ void OfflineManager::listOfflineRegions(jni::JNIEnv& env_, jni::Object<FileSourc
//Keep a shared ptr to a global reference of the callback and file source so they are not GC'd in the meanwhile
callback = std::shared_ptr<jni::jobject>(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()),
jFileSource = std::shared_ptr<jni::jobject>(jFileSource_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter())
- ](std::exception_ptr error, mbgl::optional<std::vector<mbgl::OfflineRegion>> regions) mutable {
+ ](mbgl::expected<mbgl::OfflineRegions, std::exception_ptr> regions) mutable {
// Reattach, the callback comes from a different thread
android::UniqueEnv env = android::AttachEnv();
- if (error) {
- OfflineManager::ListOfflineRegionsCallback::onError(*env, jni::Object<ListOfflineRegionsCallback>(*callback), error);
- } else if (regions) {
- OfflineManager::ListOfflineRegionsCallback::onList(*env, jni::Object<FileSource>(*jFileSource), jni::Object<ListOfflineRegionsCallback>(*callback), std::move(regions));
+ if (regions) {
+ OfflineManager::ListOfflineRegionsCallback::onList(
+ *env, jni::Object<FileSource>(*jFileSource),
+ jni::Object<ListOfflineRegionsCallback>(*callback), std::move(*regions));
+ } else {
+ OfflineManager::ListOfflineRegionsCallback::onError(
+ *env, jni::Object<ListOfflineRegionsCallback>(*callback), regions.error());
}
});
}
@@ -59,19 +62,19 @@ void OfflineManager::createOfflineRegion(jni::JNIEnv& env_,
//Keep a shared ptr to a global reference of the callback and file source so they are not GC'd in the meanwhile
callback = std::shared_ptr<jni::jobject>(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()),
jFileSource = std::shared_ptr<jni::jobject>(jFileSource_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter())
- ](std::exception_ptr error, mbgl::optional<mbgl::OfflineRegion> region) mutable {
+ ](mbgl::expected<mbgl::OfflineRegion, std::exception_ptr> region) mutable {
// Reattach, the callback comes from a different thread
android::UniqueEnv env = android::AttachEnv();
- if (error) {
- OfflineManager::CreateOfflineRegionCallback::onError(*env, jni::Object<CreateOfflineRegionCallback>(*callback), error);
- } else if (region) {
+ if (region) {
OfflineManager::CreateOfflineRegionCallback::onCreate(
*env,
jni::Object<FileSource>(*jFileSource),
- jni::Object<CreateOfflineRegionCallback>(*callback), std::move(region)
+ jni::Object<CreateOfflineRegionCallback>(*callback), std::move(*region)
);
+ } else {
+ OfflineManager::CreateOfflineRegionCallback::onError(*env, jni::Object<CreateOfflineRegionCallback>(*callback), region.error());
}
});
}
diff --git a/platform/android/src/offline/offline_region.cpp b/platform/android/src/offline/offline_region.cpp
index 27de76fb00..fe4dbecf14 100644
--- a/platform/android/src/offline/offline_region.cpp
+++ b/platform/android/src/offline/offline_region.cpp
@@ -107,14 +107,14 @@ void OfflineRegion::getOfflineRegionStatus(jni::JNIEnv& env_, jni::Object<Offlin
fileSource.getOfflineRegionStatus(*region, [
//Ensure the object is not gc'd in the meanwhile
callback = std::shared_ptr<jni::jobject>(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter())
- ](std::exception_ptr error, mbgl::optional<mbgl::OfflineRegionStatus> status) mutable {
+ ](mbgl::expected<mbgl::OfflineRegionStatus, std::exception_ptr> status) mutable {
// Reattach, the callback comes from a different thread
android::UniqueEnv env = android::AttachEnv();
- if (error) {
- OfflineRegionStatusCallback::onError(*env, jni::Object<OfflineRegionStatusCallback>(*callback), error);
- } else if (status) {
- OfflineRegionStatusCallback::onStatus(*env, jni::Object<OfflineRegionStatusCallback>(*callback), std::move(status));
+ if (status) {
+ OfflineRegionStatusCallback::onStatus(*env, jni::Object<OfflineRegionStatusCallback>(*callback), std::move(*status));
+ } else {
+ OfflineRegionStatusCallback::onError(*env, jni::Object<OfflineRegionStatusCallback>(*callback), status.error());
}
});
}
@@ -144,14 +144,14 @@ void OfflineRegion::updateOfflineRegionMetadata(jni::JNIEnv& env_, jni::Array<jn
fileSource.updateOfflineMetadata(region->getID(), metadata, [
//Ensure the object is not gc'd in the meanwhile
callback = std::shared_ptr<jni::jobject>(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter())
- ](std::exception_ptr error, mbgl::optional<mbgl::OfflineRegionMetadata> data) mutable {
+ ](mbgl::expected<mbgl::OfflineRegionMetadata, std::exception_ptr> data) mutable {
// Reattach, the callback comes from a different thread
android::UniqueEnv env = android::AttachEnv();
- if (error) {
- OfflineRegionUpdateMetadataCallback::onError(*env, jni::Object<OfflineRegionUpdateMetadataCallback>(*callback), error);
- } else if (data) {
- OfflineRegionUpdateMetadataCallback::onUpdate(*env, jni::Object<OfflineRegionUpdateMetadataCallback>(*callback), std::move(data));
+ if (data) {
+ OfflineRegionUpdateMetadataCallback::onUpdate(*env, jni::Object<OfflineRegionUpdateMetadataCallback>(*callback), std::move(*data));
+ } else {
+ OfflineRegionUpdateMetadataCallback::onError(*env, jni::Object<OfflineRegionUpdateMetadataCallback>(*callback), data.error());
}
});
}
diff --git a/platform/darwin/src/MGLOfflinePack.mm b/platform/darwin/src/MGLOfflinePack.mm
index 9d903ee841..7bbc681c88 100644
--- a/platform/darwin/src/MGLOfflinePack.mm
+++ b/platform/darwin/src/MGLOfflinePack.mm
@@ -141,7 +141,7 @@ private:
mbgl::DefaultFileSource *mbglFileSource = [[MGLOfflineStorage sharedOfflineStorage] mbglFileSource];
__weak MGLOfflinePack *weakSelf = self;
- mbglFileSource->getOfflineRegionStatus(*_mbglOfflineRegion, [&, weakSelf](__unused std::exception_ptr exception, mbgl::optional<mbgl::OfflineRegionStatus> status) {
+ mbglFileSource->getOfflineRegionStatus(*_mbglOfflineRegion, [&, weakSelf](mbgl::expected<mbgl::OfflineRegionStatus, std::exception_ptr> status) {
if (status) {
mbgl::OfflineRegionStatus checkedStatus = *status;
dispatch_async(dispatch_get_main_queue(), ^{
diff --git a/platform/darwin/src/MGLOfflineStorage.mm b/platform/darwin/src/MGLOfflineStorage.mm
index e6c10e942b..05e1b06338 100644
--- a/platform/darwin/src/MGLOfflineStorage.mm
+++ b/platform/darwin/src/MGLOfflineStorage.mm
@@ -288,16 +288,16 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio
const mbgl::OfflineTilePyramidRegionDefinition regionDefinition = [(id <MGLOfflineRegion_Private>)region offlineRegionDefinition];
mbgl::OfflineRegionMetadata metadata(context.length);
[context getBytes:&metadata[0] length:metadata.size()];
- self.mbglFileSource->createOfflineRegion(regionDefinition, metadata, [&, completion](std::exception_ptr exception, mbgl::optional<mbgl::OfflineRegion> mbglOfflineRegion) {
+ self.mbglFileSource->createOfflineRegion(regionDefinition, metadata, [&, completion](mbgl::expected<mbgl::OfflineRegion, std::exception_ptr> mbglOfflineRegion) {
NSError *error;
- if (exception) {
- NSString *errorDescription = @(mbgl::util::toString(exception).c_str());
+ if (!mbglOfflineRegion) {
+ NSString *errorDescription = @(mbgl::util::toString(mbglOfflineRegion.error()).c_str());
error = [NSError errorWithDomain:MGLErrorDomain code:-1 userInfo:errorDescription ? @{
NSLocalizedDescriptionKey: errorDescription,
} : nil];
}
if (completion) {
- MGLOfflinePack *pack = mbglOfflineRegion ? [[MGLOfflinePack alloc] initWithMBGLRegion:new mbgl::OfflineRegion(std::move(*mbglOfflineRegion))] : nil;
+ MGLOfflinePack *pack = mbglOfflineRegion ? [[MGLOfflinePack alloc] initWithMBGLRegion:new mbgl::OfflineRegion(std::move(mbglOfflineRegion.value()))] : nil;
dispatch_async(dispatch_get_main_queue(), [&, completion, error, pack](void) {
completion(pack, error);
});
@@ -347,17 +347,17 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio
}
- (void)getPacksWithCompletionHandler:(void (^)(NSArray<MGLOfflinePack *> *packs, NSError * _Nullable error))completion {
- self.mbglFileSource->listOfflineRegions([&, completion](std::exception_ptr exception, mbgl::optional<std::vector<mbgl::OfflineRegion>> regions) {
+ self.mbglFileSource->listOfflineRegions([&, completion](mbgl::expected<mbgl::OfflineRegions, std::exception_ptr> result) {
NSError *error;
- if (exception) {
+ NSMutableArray *packs;
+ if (!result) {
error = [NSError errorWithDomain:MGLErrorDomain code:-1 userInfo:@{
- NSLocalizedDescriptionKey: @(mbgl::util::toString(exception).c_str()),
+ NSLocalizedDescriptionKey: @(mbgl::util::toString(result.error()).c_str()),
}];
- }
- NSMutableArray *packs;
- if (regions) {
- packs = [NSMutableArray arrayWithCapacity:regions->size()];
- for (mbgl::OfflineRegion &region : *regions) {
+ } else {
+ auto& regions = result.value();
+ packs = [NSMutableArray arrayWithCapacity:regions.size()];
+ for (auto &region : regions) {
MGLOfflinePack *pack = [[MGLOfflinePack alloc] initWithMBGLRegion:new mbgl::OfflineRegion(std::move(region))];
[packs addObject:pack];
}
diff --git a/platform/default/default_file_source.cpp b/platform/default/default_file_source.cpp
index 051e1b125c..93f10eea72 100644
--- a/platform/default/default_file_source.cpp
+++ b/platform/default/default_file_source.cpp
@@ -45,61 +45,44 @@ public:
onlineFileSource.setResourceTransform(std::move(transform));
}
- void listRegions(std::function<void (std::exception_ptr, optional<std::vector<OfflineRegion>>)> callback) {
- try {
- callback({}, offlineDatabase->listRegions());
- } catch (...) {
- callback(std::current_exception(), {});
- }
+ void listRegions(std::function<void (expected<OfflineRegions, std::exception_ptr>)> callback) {
+ callback(offlineDatabase->listRegions());
}
void createRegion(const OfflineRegionDefinition& definition,
const OfflineRegionMetadata& metadata,
- std::function<void (std::exception_ptr, optional<OfflineRegion>)> callback) {
- try {
- callback({}, offlineDatabase->createRegion(definition, metadata));
- } catch (...) {
- callback(std::current_exception(), {});
- }
+ std::function<void (expected<OfflineRegion, std::exception_ptr>)> callback) {
+ callback(offlineDatabase->createRegion(definition, metadata));
}
void updateMetadata(const int64_t regionID,
const OfflineRegionMetadata& metadata,
- std::function<void (std::exception_ptr, optional<OfflineRegionMetadata>)> callback) {
- try {
- callback({}, offlineDatabase->updateMetadata(regionID, metadata));
- } catch (...) {
- callback(std::current_exception(), {});
- }
+ std::function<void (expected<OfflineRegionMetadata, std::exception_ptr>)> callback) {
+ callback(offlineDatabase->updateMetadata(regionID, metadata));
}
- void getRegionStatus(int64_t regionID, std::function<void (std::exception_ptr, optional<OfflineRegionStatus>)> callback) {
+ void getRegionStatus(int64_t regionID, std::function<void (expected<OfflineRegionStatus, std::exception_ptr>)> callback) {
if (auto download = getDownload(regionID)) {
- callback({}, download->getStatus());
+ callback(download.value()->getStatus());
} else {
- callback(std::current_exception(), {});
+ callback(unexpected<std::exception_ptr>(download.error()));
}
}
void deleteRegion(OfflineRegion&& region, std::function<void (std::exception_ptr)> callback) {
- try {
- downloads.erase(region.getID());
- offlineDatabase->deleteRegion(std::move(region));
- callback({});
- } catch (...) {
- callback(std::current_exception());
- }
+ downloads.erase(region.getID());
+ callback(offlineDatabase->deleteRegion(std::move(region)));
}
void setRegionObserver(int64_t regionID, std::unique_ptr<OfflineRegionObserver> observer) {
if (auto download = getDownload(regionID)) {
- download->setObserver(std::move(observer));
+ download.value()->setObserver(std::move(observer));
}
}
void setRegionDownloadState(int64_t regionID, OfflineRegionDownloadState state) {
if (auto download = getDownload(regionID)) {
- download->setState(state);
+ download.value()->setState(state);
}
}
@@ -185,17 +168,16 @@ public:
}
private:
- OfflineDownload* getDownload(int64_t regionID) {
+ expected<OfflineDownload*, std::exception_ptr> getDownload(int64_t regionID) {
auto it = downloads.find(regionID);
if (it != downloads.end()) {
return it->second.get();
}
auto definition = offlineDatabase->getRegionDefinition(regionID);
if (!definition) {
- return nullptr;
+ return unexpected<std::exception_ptr>(definition.error());
}
-
- auto download = std::make_unique<OfflineDownload>(regionID, std::move(*definition),
+ auto download = std::make_unique<OfflineDownload>(regionID, std::move(definition.value()),
*offlineDatabase, onlineFileSource);
return downloads.emplace(regionID, std::move(download)).first->second.get();
}
@@ -266,19 +248,19 @@ std::unique_ptr<AsyncRequest> DefaultFileSource::request(const Resource& resourc
return std::move(req);
}
-void DefaultFileSource::listOfflineRegions(std::function<void (std::exception_ptr, optional<std::vector<OfflineRegion>>)> callback) {
+void DefaultFileSource::listOfflineRegions(std::function<void (expected<OfflineRegions, std::exception_ptr>)> callback) {
impl->actor().invoke(&Impl::listRegions, callback);
}
void DefaultFileSource::createOfflineRegion(const OfflineRegionDefinition& definition,
const OfflineRegionMetadata& metadata,
- std::function<void (std::exception_ptr, optional<OfflineRegion>)> callback) {
+ std::function<void (expected<OfflineRegion, std::exception_ptr>)> callback) {
impl->actor().invoke(&Impl::createRegion, definition, metadata, callback);
}
void DefaultFileSource::updateOfflineMetadata(const int64_t regionID,
const OfflineRegionMetadata& metadata,
- std::function<void (std::exception_ptr, optional<OfflineRegionMetadata>)> callback) {
+ std::function<void (expected<OfflineRegionMetadata, std::exception_ptr>)> callback) {
impl->actor().invoke(&Impl::updateMetadata, regionID, metadata, callback);
}
@@ -294,7 +276,7 @@ void DefaultFileSource::setOfflineRegionDownloadState(OfflineRegion& region, Off
impl->actor().invoke(&Impl::setRegionDownloadState, region.getID(), state);
}
-void DefaultFileSource::getOfflineRegionStatus(OfflineRegion& region, std::function<void (std::exception_ptr, optional<OfflineRegionStatus>)> callback) const {
+void DefaultFileSource::getOfflineRegionStatus(OfflineRegion& region, std::function<void (expected<OfflineRegionStatus, std::exception_ptr>)> callback) const {
impl->actor().invoke(&Impl::getRegionStatus, region.getID(), callback);
}
diff --git a/platform/default/mbgl/storage/offline_database.cpp b/platform/default/mbgl/storage/offline_database.cpp
index cfa7f52977..7516185f27 100644
--- a/platform/default/mbgl/storage/offline_database.cpp
+++ b/platform/default/mbgl/storage/offline_database.cpp
@@ -592,14 +592,15 @@ bool OfflineDatabase::putTile(const Resource::TileData& tile,
return true;
}
-std::vector<OfflineRegion> OfflineDatabase::listRegions() try {
+expected<OfflineRegions, std::exception_ptr> OfflineDatabase::listRegions() try {
mapbox::sqlite::Query query{ getStatement("SELECT id, definition, description FROM regions") };
- std::vector<OfflineRegion> result;
+ OfflineRegions result;
while (query.run()) {
const auto id = query.get<int64_t>(0);
const auto definition = query.get<std::string>(1);
const auto description = query.get<std::vector<uint8_t>>(2);
try {
+ // Construct, then move because this constructor is private.
OfflineRegion region(id, decodeOfflineRegionDefinition(definition), description);
result.emplace_back(std::move(region));
} catch (const std::exception& ex) {
@@ -608,14 +609,16 @@ std::vector<OfflineRegion> OfflineDatabase::listRegions() try {
Log::Error(Event::General, "%s", ex.what());
}
}
- return result;
+ // Explicit move to avoid triggering the copy constructor.
+ return { std::move(result) };
} catch (const mapbox::sqlite::Exception& ex) {
handleError(ex, "list regions");
- return {};
+ return unexpected<std::exception_ptr>(std::current_exception());
}
-optional<OfflineRegion> OfflineDatabase::createRegion(const OfflineRegionDefinition& definition,
- const OfflineRegionMetadata& metadata) try {
+expected<OfflineRegion, std::exception_ptr>
+OfflineDatabase::createRegion(const OfflineRegionDefinition& definition,
+ const OfflineRegionMetadata& metadata) try {
// clang-format off
mapbox::sqlite::Query query{ getStatement(
"INSERT INTO regions (definition, description) "
@@ -628,10 +631,11 @@ optional<OfflineRegion> OfflineDatabase::createRegion(const OfflineRegionDefinit
return OfflineRegion(query.lastInsertRowId(), definition, metadata);
} catch (const mapbox::sqlite::Exception& ex) {
handleError(ex, "create region");
- return nullopt;
+ return unexpected<std::exception_ptr>(std::current_exception());
}
-optional<OfflineRegionMetadata> OfflineDatabase::updateMetadata(const int64_t regionID, const OfflineRegionMetadata& metadata) try {
+expected<OfflineRegionMetadata, std::exception_ptr>
+OfflineDatabase::updateMetadata(const int64_t regionID, const OfflineRegionMetadata& metadata) try {
// clang-format off
mapbox::sqlite::Query query{ getStatement(
"UPDATE regions SET description = ?1 "
@@ -644,10 +648,10 @@ optional<OfflineRegionMetadata> OfflineDatabase::updateMetadata(const int64_t re
return metadata;
} catch (const mapbox::sqlite::Exception& ex) {
handleError(ex, "update region metadata");
- return nullopt;
+ return unexpected<std::exception_ptr>(std::current_exception());
}
-void OfflineDatabase::deleteRegion(OfflineRegion&& region) try {
+std::exception_ptr OfflineDatabase::deleteRegion(OfflineRegion&& region) try {
{
mapbox::sqlite::Query query{ getStatement("DELETE FROM regions WHERE id = ?") };
query.bind(1, region.getID());
@@ -660,9 +664,10 @@ void OfflineDatabase::deleteRegion(OfflineRegion&& region) try {
// Ensure that the cached offlineTileCount value is recalculated.
offlineMapboxTileCount = {};
+ return nullptr;
} catch (const mapbox::sqlite::Exception& ex) {
handleError(ex, "delete region");
- return;
+ return std::current_exception();
}
optional<std::pair<Response, uint64_t>> OfflineDatabase::getRegionResource(int64_t regionID, const Resource& resource) try {
@@ -848,7 +853,7 @@ bool OfflineDatabase::markUsed(int64_t regionID, const Resource& resource) {
}
}
-optional<OfflineRegionDefinition> OfflineDatabase::getRegionDefinition(int64_t regionID) try {
+expected<OfflineRegionDefinition, std::exception_ptr> OfflineDatabase::getRegionDefinition(int64_t regionID) try {
mapbox::sqlite::Query query{ getStatement("SELECT definition FROM regions WHERE id = ?1") };
query.bind(1, regionID);
query.run();
@@ -856,10 +861,10 @@ optional<OfflineRegionDefinition> OfflineDatabase::getRegionDefinition(int64_t r
return decodeOfflineRegionDefinition(query.get<std::string>(0));
} catch (const mapbox::sqlite::Exception& ex) {
handleError(ex, "load region");
- return nullopt;
+ return unexpected<std::exception_ptr>(std::current_exception());
}
-optional<OfflineRegionStatus> OfflineDatabase::getRegionCompletedStatus(int64_t regionID) try {
+expected<OfflineRegionStatus, std::exception_ptr> OfflineDatabase::getRegionCompletedStatus(int64_t regionID) try {
OfflineRegionStatus result;
std::tie(result.completedResourceCount, result.completedResourceSize)
@@ -873,7 +878,7 @@ optional<OfflineRegionStatus> OfflineDatabase::getRegionCompletedStatus(int64_t
return result;
} catch (const mapbox::sqlite::Exception& ex) {
handleError(ex, "get region status");
- return nullopt;
+ return unexpected<std::exception_ptr>(std::current_exception());
}
std::pair<int64_t, int64_t> OfflineDatabase::getCompletedResourceCountAndSize(int64_t regionID) {
diff --git a/platform/default/mbgl/storage/offline_database.hpp b/platform/default/mbgl/storage/offline_database.hpp
index cdad11b79e..fbe6c707e1 100644
--- a/platform/default/mbgl/storage/offline_database.hpp
+++ b/platform/default/mbgl/storage/offline_database.hpp
@@ -7,6 +7,7 @@
#include <mbgl/util/optional.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/mapbox.hpp>
+#include <mbgl/util/expected.hpp>
#include <unordered_map>
#include <memory>
@@ -47,14 +48,15 @@ public:
// Return value is (inserted, stored size)
std::pair<bool, uint64_t> put(const Resource&, const Response&);
- std::vector<OfflineRegion> listRegions();
+ expected<OfflineRegions, std::exception_ptr> listRegions();
- optional<OfflineRegion> createRegion(const OfflineRegionDefinition&,
- const OfflineRegionMetadata&);
+ expected<OfflineRegion, std::exception_ptr> createRegion(const OfflineRegionDefinition&,
+ const OfflineRegionMetadata&);
- optional<OfflineRegionMetadata> updateMetadata(const int64_t regionID, const OfflineRegionMetadata&);
+ expected<OfflineRegionMetadata, std::exception_ptr>
+ updateMetadata(const int64_t regionID, const OfflineRegionMetadata&);
- void deleteRegion(OfflineRegion&&);
+ std::exception_ptr deleteRegion(OfflineRegion&&);
// Return value is (response, stored size)
optional<std::pair<Response, uint64_t>> getRegionResource(int64_t regionID, const Resource&);
@@ -62,8 +64,8 @@ public:
uint64_t putRegionResource(int64_t regionID, const Resource&, const Response&);
void putRegionResources(int64_t regionID, const std::list<std::tuple<Resource, Response>>&, OfflineRegionStatus&);
- optional<OfflineRegionDefinition> getRegionDefinition(int64_t regionID);
- optional<OfflineRegionStatus> getRegionCompletedStatus(int64_t regionID);
+ expected<OfflineRegionDefinition, std::exception_ptr> getRegionDefinition(int64_t regionID);
+ expected<OfflineRegionStatus, std::exception_ptr> getRegionCompletedStatus(int64_t regionID);
void setOfflineMapboxTileCountLimit(uint64_t);
uint64_t getOfflineMapboxTileCountLimit();
diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj
index b77c67fbb3..48329cf63a 100644
--- a/platform/ios/ios.xcodeproj/project.pbxproj
+++ b/platform/ios/ios.xcodeproj/project.pbxproj
@@ -3690,7 +3690,10 @@
baseConfigurationReference = 55D8C9941D0F133500F42F10 /* config.xcconfig */;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
- HEADER_SEARCH_PATHS = "$(mbgl_core_INCLUDE_DIRECTORIES)";
+ HEADER_SEARCH_PATHS = (
+ "$(mbgl_core_INCLUDE_DIRECTORIES)",
+ "$(mbgl_filesource_INCLUDE_DIRECTORIES)",
+ );
INFOPLIST_FILE = test/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
OTHER_CFLAGS = "-fvisibility=hidden";
@@ -3714,7 +3717,10 @@
baseConfigurationReference = 55D8C9941D0F133500F42F10 /* config.xcconfig */;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
- HEADER_SEARCH_PATHS = "$(mbgl_core_INCLUDE_DIRECTORIES)";
+ HEADER_SEARCH_PATHS = (
+ "$(mbgl_core_INCLUDE_DIRECTORIES)",
+ "$(mbgl_filesource_INCLUDE_DIRECTORIES)",
+ );
INFOPLIST_FILE = test/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
OTHER_CFLAGS = "-fvisibility=hidden";
diff --git a/scripts/config.xcconfig.in b/scripts/config.xcconfig.in
index 357732c9ae..69ca2424a1 100644
--- a/scripts/config.xcconfig.in
+++ b/scripts/config.xcconfig.in
@@ -1,9 +1,9 @@
// Do not edit -- generated by CMake
// mbgl-core
-mbgl_core_INCLUDE_DIRECTORIES = "@mbgl_core_INCLUDE_DIRECTORIES@"
-mbgl_core_LINK_LIBRARIES = "@mbgl_core_LINK_LIBRARIES@"
+mbgl_core_INCLUDE_DIRECTORIES = "$<JOIN:$<TARGET_PROPERTY:mbgl-core,INTERFACE_INCLUDE_DIRECTORIES>," ">"
+mbgl_core_LINK_LIBRARIES = "$<TARGET_PROPERTY:mbgl-core,XCODE_ATTRIBUTE_XCCONFIG_LINK_LIBRARIES>"
// mbgl-filesource
-mbgl_filesource_INCLUDE_DIRECTORIES = "@mbgl_filesource_INCLUDE_DIRECTORIES@"
-mbgl_filesource_LINK_LIBRARIES = "@mbgl_filesource_LINK_LIBRARIES@"
+mbgl_filesource_INCLUDE_DIRECTORIES = "$<JOIN:$<TARGET_PROPERTY:mbgl-filesource,INTERFACE_INCLUDE_DIRECTORIES>," ">"
+mbgl_filesource_LINK_LIBRARIES = "$<TARGET_PROPERTY:mbgl-filesource,XCODE_ATTRIBUTE_XCCONFIG_LINK_LIBRARIES>"
diff --git a/test/storage/offline_database.test.cpp b/test/storage/offline_database.test.cpp
index de40d8caf7..a1fd2ea619 100644
--- a/test/storage/offline_database.test.cpp
+++ b/test/storage/offline_database.test.cpp
@@ -436,7 +436,8 @@ TEST(OfflineDatabase, UpdateMetadata) {
OfflineRegionMetadata newmetadata {{ 4, 5, 6 }};
db.updateMetadata(region->getID(), newmetadata);
- EXPECT_EQ(db.listRegions().at(0).getMetadata(), newmetadata);
+ auto regions = db.listRegions().value();
+ EXPECT_EQ(regions.at(0).getMetadata(), newmetadata);
EXPECT_EQ(0u, log.uncheckedCount());
}
@@ -449,7 +450,7 @@ TEST(OfflineDatabase, ListRegions) {
auto region = db.createRegion(definition, metadata);
ASSERT_TRUE(region);
- std::vector<OfflineRegion> regions = db.listRegions();
+ auto regions = db.listRegions().value();
ASSERT_EQ(1u, regions.size());
EXPECT_EQ(region->getID(), regions.at(0).getID());
@@ -499,7 +500,8 @@ TEST(OfflineDatabase, DeleteRegion) {
db.deleteRegion(std::move(*region));
- ASSERT_EQ(0u, db.listRegions().size());
+ auto regions = db.listRegions().value();
+ ASSERT_EQ(0u, regions.size());
EXPECT_EQ(0u, log.uncheckedCount());
}
@@ -841,10 +843,9 @@ TEST(OfflineDatabase, BatchInsertionMapboxTileCountExceeded) {
EXPECT_EQ(0u, status.completedTileCount);
EXPECT_EQ(0u, status.completedResourceCount);
- const auto completedStatus = db.getRegionCompletedStatus(region->getID());
- ASSERT_TRUE(completedStatus);
- EXPECT_EQ(1u, completedStatus->completedTileCount);
- EXPECT_EQ(2u, completedStatus->completedResourceCount);
+ const auto completedStatus = db.getRegionCompletedStatus(region->getID()).value();
+ EXPECT_EQ(1u, completedStatus.completedTileCount);
+ EXPECT_EQ(2u, completedStatus.completedResourceCount);
EXPECT_EQ(0u, log.uncheckedCount());
}
@@ -858,7 +859,8 @@ TEST(OfflineDatabase, MigrateFromV2Schema) {
{
OfflineDatabase db(filename, 0);
auto regions = db.listRegions();
- for (auto& region : regions) {
+ ASSERT_TRUE(regions);
+ for (auto& region : regions.value()) {
db.deleteRegion(std::move(region));
}
}
@@ -878,7 +880,7 @@ TEST(OfflineDatabase, MigrateFromV3Schema) {
{
OfflineDatabase db(filename, 0);
- auto regions = db.listRegions();
+ auto regions = db.listRegions().value();
for (auto& region : regions) {
db.deleteRegion(std::move(region));
}
@@ -897,7 +899,7 @@ TEST(OfflineDatabase, MigrateFromV4Schema) {
{
OfflineDatabase db(filename, 0);
- auto regions = db.listRegions();
+ auto regions = db.listRegions().value();
for (auto& region : regions) {
db.deleteRegion(std::move(region));
}
@@ -923,7 +925,7 @@ TEST(OfflineDatabase, MigrateFromV5Schema) {
{
OfflineDatabase db(filename, 0);
- auto regions = db.listRegions();
+ auto regions = db.listRegions().value();
for (auto& region : regions) {
db.deleteRegion(std::move(region));
}
@@ -1046,16 +1048,15 @@ TEST(OfflineDatabase, TEST_REQUIRES_WRITE(DisallowedIO)) {
EXPECT_EQ(1u, log.count(warning(ResultCode::Auth, "Can't write resource: authorization denied")));
EXPECT_EQ(0u, log.uncheckedCount());
- const auto regions = db.listRegions();
- EXPECT_TRUE(regions.empty());
+ EXPECT_FALSE(db.listRegions());
EXPECT_EQ(1u, log.count(warning(ResultCode::Auth, "Can't list regions: authorization denied")));
EXPECT_EQ(0u, log.uncheckedCount());
- EXPECT_EQ(nullopt, db.createRegion(definition, {}));
+ EXPECT_FALSE(db.createRegion(definition, {}));
EXPECT_EQ(1u, log.count(warning(ResultCode::Auth, "Can't create region: authorization denied")));
EXPECT_EQ(0u, log.uncheckedCount());
- EXPECT_EQ(nullopt, db.updateMetadata(region->getID(), {}));
+ EXPECT_FALSE(db.updateMetadata(region->getID(), {}));
EXPECT_EQ(1u, log.count(warning(ResultCode::Auth, "Can't update region metadata: authorization denied")));
EXPECT_EQ(0u, log.uncheckedCount());
@@ -1077,15 +1078,15 @@ TEST(OfflineDatabase, TEST_REQUIRES_WRITE(DisallowedIO)) {
EXPECT_EQ(1u, log.count(warning(ResultCode::Auth, "Can't write region resources: authorization denied")));
EXPECT_EQ(0u, log.uncheckedCount());
- EXPECT_EQ(nullopt, db.getRegionDefinition(region->getID()));
+ EXPECT_FALSE(db.getRegionDefinition(region->getID()));
EXPECT_EQ(1u, log.count(warning(ResultCode::Auth, "Can't load region: authorization denied")));
EXPECT_EQ(0u, log.uncheckedCount());
- EXPECT_EQ(nullopt, db.getRegionCompletedStatus(region->getID()));
+ EXPECT_FALSE(db.getRegionCompletedStatus(region->getID()));
EXPECT_EQ(1u, log.count(warning(ResultCode::Auth, "Can't get region status: authorization denied")));
EXPECT_EQ(0u, log.uncheckedCount());
- db.deleteRegion(std::move(*region));
+ EXPECT_TRUE(db.deleteRegion(std::move(*region)));
EXPECT_EQ(1u, log.count(warning(ResultCode::Auth, "Can't delete region: authorization denied")));
EXPECT_EQ(0u, log.uncheckedCount());
diff --git a/test/storage/offline_download.test.cpp b/test/storage/offline_download.test.cpp
index f979d42601..93b4dd623a 100644
--- a/test/storage/offline_download.test.cpp
+++ b/test/storage/offline_download.test.cpp
@@ -65,7 +65,7 @@ public:
OfflineDatabase db;
std::size_t size = 0;
- optional<OfflineRegion> createRegion() {
+ auto createRegion() {
OfflineRegionDefinition definition { "", LatLngBounds::hull({1, 2}, {3, 4}), 5, 6, 1.0 };
OfflineRegionMetadata metadata;
return db.createRegion(definition, metadata);