optional<Function<T>> parseFunction(const char* name, const JSValue& value) { if (!value.IsObject()) { auto constant = parseProperty<T>(name, value); if (!constant) { return {}; } return { Function<T>(*constant) }; } if (!value.HasMember("stops")) { Log::Warning(Event::ParseStyle, "function must specify a function type"); return {}; } float base = 1.0f; if (value.HasMember("base")) { const JSValue& value_base = value["base"]; if (!value_base.IsNumber()) { Log::Warning(Event::ParseStyle, "base must be numeric"); return {}; } base = value_base.GetDouble(); } auto stops = parseStops<T>(name, value["stops"]); if (!stops) { return {}; } return { Function<T>(*stops, base) }; }
optional<PropertyTransition> parseProperty(const char *, const JSValue& value) { PropertyTransition transition; if (value.IsObject()) { bool parsed = false; if (value.HasMember("duration") && value["duration"].IsNumber()) { transition.duration.emplace(Milliseconds(value["duration"].GetUint())); parsed = true; } if (value.HasMember("delay") && value["delay"].IsNumber()) { transition.delay.emplace(Milliseconds(value["delay"].GetUint())); parsed = true; } if (!parsed) { return {}; } } return transition; }
optional<TransitionOptions> parseTransitionOptions(const char *, const JSValue& value) { if (!value.IsObject()) { return {}; } optional<Duration> duration; if (value.HasMember("duration") && value["duration"].IsNumber()) { duration.emplace(Milliseconds(value["duration"].GetUint())); } optional<Duration> delay; if (value.HasMember("delay") && value["delay"].IsNumber()) { delay.emplace(Milliseconds(value["delay"].GetUint())); } if (!duration && !delay) { return {}; } return TransitionOptions(duration, delay); }
void Parser::parseLayer(const std::string& id, const JSValue& value, std::unique_ptr<Layer>& layer) { if (layer) { // Skip parsing this again. We already have a valid layer definition. return; } // Make sure we have not previously attempted to parse this layer. if (std::find(stack.begin(), stack.end(), id) != stack.end()) { Log::Warning(Event::ParseStyle, "layer reference of '%s' is circular", id.c_str()); return; } if (value.HasMember("ref")) { // This layer is referencing another layer. Recursively parse that layer. const JSValue& refVal = value["ref"]; if (!refVal.IsString()) { Log::Warning(Event::ParseStyle, "layer ref of '%s' must be a string", id.c_str()); return; } const std::string ref { refVal.GetString(), refVal.GetStringLength() }; auto it = layersMap.find(ref); if (it == layersMap.end()) { Log::Warning(Event::ParseStyle, "layer '%s' references unknown layer %s", id.c_str(), ref.c_str()); return; } // Recursively parse the referenced layer. stack.push_front(id); parseLayer(it->first, it->second.first, it->second.second); stack.pop_front(); Layer* reference = it->second.second.get(); if (!reference) { return; } layer = reference->cloneRef(id); conversion::setPaintProperties(*layer, value); } else { conversion::Error error; optional<std::unique_ptr<Layer>> converted = conversion::convert<std::unique_ptr<Layer>>(value, error); if (!converted) { Log::Warning(Event::ParseStyle, error.message); return; } layer = std::move(*converted); } }
optional<Function<Faded<T>>> parseFadedFunction(const JSValue& value) { if (!value.HasMember("stops")) { Log::Warning(Event::ParseStyle, "function must specify a function type"); return {}; } auto stops = parseStops<T>("", value["stops"]); if (!stops) { return {}; } return Function<Faded<T>>(*stops); }
std::unique_ptr<RasterSource> RasterSource::parse(std::string id, const JSValue& value) { optional<variant<std::string, Tileset>> urlOrTileset = TileSource::parseURLOrTileset(value); if (!urlOrTileset) { return nullptr; } uint16_t tileSize = util::tileSize; if (value.HasMember("tileSize")) { const JSValue& tileSizeVal = value["tileSize"]; if (tileSizeVal.IsNumber() && tileSizeVal.GetUint64() <= std::numeric_limits<uint16_t>::max()) { tileSize = tileSizeVal.GetUint64(); } else { Log::Error(Event::ParseStyle, "invalid tileSize"); return nullptr; } } return std::make_unique<RasterSource>(std::move(id), std::move(*urlOrTileset), tileSize); }