diff options
-rw-r--r-- | src/mbgl/map/map.cpp | 9 | ||||
-rw-r--r-- | src/mbgl/style/observer.hpp | 1 | ||||
-rw-r--r-- | src/mbgl/style/parser.cpp | 15 | ||||
-rw-r--r-- | src/mbgl/style/parser.hpp | 5 | ||||
-rw-r--r-- | src/mbgl/style/style.cpp | 10 | ||||
-rw-r--r-- | test/fixtures/style_parser/non-object.info.json | 4 | ||||
-rw-r--r-- | test/map/map.cpp | 2 | ||||
-rw-r--r-- | test/style/style_parser.cpp | 7 |
8 files changed, 41 insertions, 12 deletions
diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index 2e7dc06e8b..3a307735ab 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -38,6 +38,7 @@ public: Impl(View&, FileSource&, MapMode, GLContextMode, ConstrainMode, ViewportMode); void onNeedsRepaint() override; + void onStyleError() override; void onResourceError(std::exception_ptr) override; void update(); @@ -316,6 +317,8 @@ void Map::setStyleURL(const std::string& url) { } else { Log::Error(Event::Setup, "loading style failed: %s", res.error->message.c_str()); } + impl->onStyleError(); + impl->onResourceError(std::make_exception_ptr(std::runtime_error(res.error->message))); } else if (res.notModified || res.noContent) { return; } else { @@ -343,8 +346,8 @@ void Map::setStyleJSON(const std::string& json) { } void Map::Impl::loadStyleJSON(const std::string& json) { - style->setJSON(json); style->setObserver(this); + style->setJSON(json); styleJSON = json; // force style cascade, causing all pending transitions to complete. @@ -908,6 +911,10 @@ void Map::Impl::onNeedsRepaint() { asyncUpdate.send(); } +void Map::Impl::onStyleError() { + view.notifyMapChange(MapChangeDidFailLoadingMap); +} + void Map::Impl::onResourceError(std::exception_ptr error) { if (mode == MapMode::Still && callback) { callback(error, {}); diff --git a/src/mbgl/style/observer.hpp b/src/mbgl/style/observer.hpp index 2c48114669..c4d31ae249 100644 --- a/src/mbgl/style/observer.hpp +++ b/src/mbgl/style/observer.hpp @@ -18,6 +18,7 @@ public: * and `onNeedsRepaint` will be called. */ void onNeedsRepaint() override {} + virtual void onStyleError() {} virtual void onResourceError(std::exception_ptr) {} }; diff --git a/src/mbgl/style/parser.cpp b/src/mbgl/style/parser.cpp index bc05b5484a..e53fac2667 100644 --- a/src/mbgl/style/parser.cpp +++ b/src/mbgl/style/parser.cpp @@ -14,24 +14,27 @@ #include <algorithm> #include <set> +#include <sstream> namespace mbgl { namespace style { Parser::~Parser() = default; -void Parser::parse(const std::string& json) { +StyleParseResult Parser::parse(const std::string& json) { rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> document; document.Parse<0>(json.c_str()); if (document.HasParseError()) { - Log::Error(Event::ParseStyle, "Error parsing style JSON at %i: %s", document.GetErrorOffset(), rapidjson::GetParseError_En(document.GetParseError())); - return; + std::stringstream message; + message << document.GetErrorOffset() << " - " + << rapidjson::GetParseError_En(document.GetParseError()); + + return std::make_exception_ptr(std::runtime_error(message.str())); } if (!document.IsObject()) { - Log::Error(Event::ParseStyle, "Style JSON must be an object"); - return; + return std::make_exception_ptr(std::runtime_error("style must be an object")); } if (document.HasMember("version")) { @@ -100,6 +103,8 @@ void Parser::parse(const std::string& json) { glyphURL = { glyphs.GetString(), glyphs.GetStringLength() }; } } + + return nullptr; } void Parser::parseSources(const JSValue& value) { diff --git a/src/mbgl/style/parser.hpp b/src/mbgl/style/parser.hpp index a6a71ed817..a05a0b316a 100644 --- a/src/mbgl/style/parser.hpp +++ b/src/mbgl/style/parser.hpp @@ -9,6 +9,7 @@ #include <vector> #include <memory> +#include <stdexcept> #include <string> #include <unordered_map> #include <forward_list> @@ -16,11 +17,13 @@ namespace mbgl { namespace style { +using StyleParseResult = std::exception_ptr; + class Parser { public: ~Parser(); - void parse(const std::string&); + StyleParseResult parse(const std::string&); std::string spriteURL; std::string glyphURL; diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp index 1cf64002fb..e04384a96e 100644 --- a/src/mbgl/style/style.cpp +++ b/src/mbgl/style/style.cpp @@ -90,7 +90,15 @@ void Style::setJSON(const std::string& json) { classes.clear(); Parser parser; - parser.parse(json); + auto error = parser.parse(json); + + if (error) { + Log::Error(Event::ParseStyle, "Failed to parse style: %s", util::toString(error).c_str()); + observer->onStyleError(); + observer->onResourceError(error); + + return; + } for (auto& source : parser.sources) { addSource(std::move(source)); diff --git a/test/fixtures/style_parser/non-object.info.json b/test/fixtures/style_parser/non-object.info.json index d1b67e2ea6..ac6ea00d97 100644 --- a/test/fixtures/style_parser/non-object.info.json +++ b/test/fixtures/style_parser/non-object.info.json @@ -1,7 +1,7 @@ { "default": { "log": [ - [1, "ERROR", "ParseStyle", "Style JSON must be an object"] + [1, "ERROR", "ParseStyle", "Failed to parse style: style must be an object"] ] } -}
\ No newline at end of file +} diff --git a/test/map/map.cpp b/test/map/map.cpp index 2dc8aad927..7e0bbd0234 100644 --- a/test/map/map.cpp +++ b/test/map/map.cpp @@ -68,7 +68,7 @@ TEST(Map, SetStyleInvalidJSON) { auto observer = Log::removeObserver(); auto flo = dynamic_cast<FixtureLogObserver*>(observer.get()); EXPECT_EQ(1u, flo->count({ EventSeverity::Error, Event::ParseStyle, -1, - "Error parsing style JSON at 0: Invalid value." })); + "Failed to parse style: 0 - Invalid value." })); auto unchecked = flo->unchecked(); EXPECT_TRUE(unchecked.empty()) << unchecked; } diff --git a/test/style/style_parser.cpp b/test/style/style_parser.cpp index b7806c11cc..3e1149c997 100644 --- a/test/style/style_parser.cpp +++ b/test/style/style_parser.cpp @@ -4,6 +4,7 @@ #include <mbgl/style/parser.hpp> #include <mbgl/util/io.hpp> #include <mbgl/util/enum.hpp> +#include <mbgl/util/string.hpp> #include <mbgl/util/tileset.hpp> #include <rapidjson/document.h> @@ -32,7 +33,11 @@ TEST_P(StyleParserTest, ParseStyle) { Log::setObserver(std::unique_ptr<Log::Observer>(observer)); style::Parser parser; - parser.parse(util::read_file(base + ".style.json")); + auto error = parser.parse(util::read_file(base + ".style.json")); + + if (error) { + Log::Error(Event::ParseStyle, "Failed to parse style: %s", util::toString(error).c_str()); + } for (auto it = infoDoc.MemberBegin(), end = infoDoc.MemberEnd(); it != end; it++) { const std::string name { it->name.GetString(), it->name.GetStringLength() }; |