From 021d4199cb9ee754e9f0f5bc42f7f75285afd405 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 23 Jun 2016 12:00:25 -0700 Subject: [core, node] Implement bindings for addSource --- include/mbgl/style/conversion.hpp | 6 +- include/mbgl/style/conversion/geojson.hpp | 15 ++++ include/mbgl/style/conversion/source.hpp | 123 ++++++++++++++++++++++++++ include/mbgl/style/conversion/tileset.hpp | 67 ++++++++++++++ include/mbgl/style/sources/geojson_source.hpp | 14 ++- include/mbgl/util/geojson.hpp | 22 +++++ 6 files changed, 235 insertions(+), 12 deletions(-) create mode 100644 include/mbgl/style/conversion/geojson.hpp create mode 100644 include/mbgl/style/conversion/source.hpp create mode 100644 include/mbgl/style/conversion/tileset.hpp create mode 100644 include/mbgl/util/geojson.hpp (limited to 'include') diff --git a/include/mbgl/style/conversion.hpp b/include/mbgl/style/conversion.hpp index 2cb3ced376..bd7db3adfb 100644 --- a/include/mbgl/style/conversion.hpp +++ b/include/mbgl/style/conversion.hpp @@ -83,9 +83,9 @@ public: template struct Converter; -template -Result convert(const V& value) { - return Converter()(value); +template +Result convert(const V& value, Args&&...args) { + return Converter()(value, std::forward(args)...); } } // namespace conversion diff --git a/include/mbgl/style/conversion/geojson.hpp b/include/mbgl/style/conversion/geojson.hpp new file mode 100644 index 0000000000..ba10b3ecc8 --- /dev/null +++ b/include/mbgl/style/conversion/geojson.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include +#include + +namespace mbgl { +namespace style { +namespace conversion { + +template +Result convertGeoJSON(const V& value); + +} // namespace conversion +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/conversion/source.hpp b/include/mbgl/style/conversion/source.hpp new file mode 100644 index 0000000000..00c6afb9fe --- /dev/null +++ b/include/mbgl/style/conversion/source.hpp @@ -0,0 +1,123 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace mbgl { +namespace style { +namespace conversion { + +template <> +struct Converter> { +public: + template + Result> operator()(const V& value, const std::string& id) const { + if (!isObject(value)) { + return Error { "source must be an object" }; + } + + auto typeValue = objectMember(value, "type"); + if (!typeValue) { + return Error { "source must have a type" }; + } + + optional type = toString(*typeValue); + if (!type) { + return Error { "source type must be a string" }; + } + + if (*type == "raster") { + return convertRasterSource(id, value); + } else if (*type == "vector") { + return convertVectorSource(id, value); + } else if (*type == "geojson") { + return convertGeoJSONSource(id, value); + } else { + return Error { "invalid source type" }; + } + } + +private: + // A tile source can either specify a URL to TileJSON, or inline TileJSON. + template + Result> convertURLOrTileset(const V& value) const { + auto urlVal = objectMember(value, "url"); + if (!urlVal) { + Result tileset = convert(value); + if (!tileset) { + return tileset.error(); + } + return *tileset; + } + + optional url = toString(*urlVal); + if (!url) { + return Error { "source url must be a string" }; + } + + return *url; + } + + template + Result> convertRasterSource(const std::string& id, const V& value) const { + Result> urlOrTileset = convertURLOrTileset(value); + if (!urlOrTileset) { + return urlOrTileset.error(); + } + + uint16_t tileSize = util::tileSize; + auto tileSizeValue = objectMember(value, "tileSize"); + if (tileSizeValue) { + optional size = toNumber(*tileSizeValue); + if (!size || *size < 0 || *size > std::numeric_limits::max()) { + return Error { "invalid tileSize" }; + } + tileSize = *size; + } + + return std::make_unique(id, std::move(*urlOrTileset), tileSize); + } + + template + Result> convertVectorSource(const std::string& id, const V& value) const { + Result> urlOrTileset = convertURLOrTileset(value); + if (!urlOrTileset) { + return urlOrTileset.error(); + } + + return std::make_unique(id, std::move(*urlOrTileset)); + } + + template + Result> convertGeoJSONSource(const std::string& id, const V& value) const { + auto dataValue = objectMember(value, "data"); + if (!dataValue) { + return Error { "GeoJSON source must have a data value" }; + } + + auto result = std::make_unique(id); + + if (isObject(*dataValue)) { + Result geoJSON = convertGeoJSON(*dataValue); + if (!geoJSON) { + return geoJSON.error(); + } + result->setGeoJSON(std::move(*geoJSON)); + } else if (toString(*dataValue)) { + result->setURL(*toString(*dataValue)); + } else { + return Error { "GeoJSON data must be a URL or an object" }; + } + + return std::move(result); + } +}; + +} // namespace conversion +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/conversion/tileset.hpp b/include/mbgl/style/conversion/tileset.hpp new file mode 100644 index 0000000000..46425597af --- /dev/null +++ b/include/mbgl/style/conversion/tileset.hpp @@ -0,0 +1,67 @@ +#pragma once + +#include +#include + +namespace mbgl { +namespace style { +namespace conversion { + +template <> +struct Converter { +public: + template + Result operator()(const V& value) const { + Tileset result; + + auto tiles = objectMember(value, "tiles"); + if (!tiles) { + return Error { "source must have tiles" }; + } + + if (!isArray(*tiles)) { + return Error { "source tiles must be an array" }; + } + + for (std::size_t i = 0; i < arrayLength(*tiles); i++) { + optional urlTemplate = toString(arrayMember(*tiles, i)); + if (!urlTemplate) { + return Error { "source tiles member must be a string" }; + } + result.tiles.push_back(std::move(*urlTemplate)); + } + + auto minzoomValue = objectMember(value, "minzoom"); + if (minzoomValue) { + optional minzoom = toNumber(*minzoomValue); + if (!minzoom || *minzoom < 0 || *minzoom > std::numeric_limits::max()) { + return Error { "invalid minzoom" }; + } + result.zoomRange.min = *minzoom; + } + + auto maxzoomValue = objectMember(value, "maxzoom"); + if (maxzoomValue) { + optional maxzoom = toNumber(*maxzoomValue); + if (!maxzoom || *maxzoom < 0 || *maxzoom > std::numeric_limits::max()) { + return Error { "invalid maxzoom" }; + } + result.zoomRange.max = *maxzoom; + } + + auto attributionValue = objectMember(value, "attribution"); + if (attributionValue) { + optional attribution = toString(*attributionValue); + if (!attribution) { + return Error { "source attribution must be a string" }; + } + result.attribution = std::move(*attribution); + } + + return result; + } +}; + +} // namespace conversion +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/sources/geojson_source.hpp b/include/mbgl/style/sources/geojson_source.hpp index 96b9a99606..3736dd44bc 100644 --- a/include/mbgl/style/sources/geojson_source.hpp +++ b/include/mbgl/style/sources/geojson_source.hpp @@ -1,26 +1,22 @@ #pragma once #include +#include namespace mbgl { namespace style { class GeoJSONSource : public Source { public: - // Future public API: - // void setData(FeatureCollection&&); - // void setJSON(const std::string& json); - // void loadData(const std::string& url); + GeoJSONSource(const std::string& id); + void setURL(const std::string& url); + void setGeoJSON(GeoJSON&&); // Private implementation class Impl; - - template - GeoJSONSource(Fn&& fn) - : Source(SourceType::GeoJSON, fn(*this)) { - } + Impl* const impl; }; } // namespace style diff --git a/include/mbgl/util/geojson.hpp b/include/mbgl/util/geojson.hpp new file mode 100644 index 0000000000..3fd8c6ac4b --- /dev/null +++ b/include/mbgl/util/geojson.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include + +namespace mapbox { +namespace geojsonvt { +class GeoJSONVT; +} // namespace geojsonvt +} // namespace mapbox + +namespace mbgl { + +class GeoJSON { +public: + GeoJSON(std::unique_ptr); + GeoJSON(GeoJSON&&); + ~GeoJSON(); + + std::unique_ptr impl; +}; + +} // namespace mbgl -- cgit v1.2.1