optional<std::string> parseProperty(const char* name, const JSValue& value) { if (std::string { "text-font" } == name) { if (!value.IsArray()) { Log::Warning(Event::ParseStyle, "value of '%s' must be an array of strings", name); return {}; } std::string result = ""; for (rapidjson::SizeType i = 0; i < value.Size(); ++i) { const JSValue& stop = value[i]; if (stop.IsString()) { result += stop.GetString(); if (i < value.Size()-1) { result += ","; } } else { Log::Warning(Event::ParseStyle, "text-font members must be strings"); return {}; } } return result; } if (!value.IsString()) { Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name); return {}; } return std::string { value.GetString(), value.GetStringLength() }; }
void Parser::parseLayers(const JSValue& value) { std::vector<std::string> ids; if (!value.IsArray()) { Log::Warning(Event::ParseStyle, "layers must be an array"); return; } for (rapidjson::SizeType i = 0; i < value.Size(); ++i) { const JSValue& layerValue = value[i]; if (!layerValue.IsObject()) { Log::Warning(Event::ParseStyle, "layer must be an object"); continue; } if (!layerValue.HasMember("id")) { Log::Warning(Event::ParseStyle, "layer must have an id"); continue; } const JSValue& id = layerValue["id"]; if (!id.IsString()) { Log::Warning(Event::ParseStyle, "layer id must be a string"); continue; } const std::string layerID = { id.GetString(), id.GetStringLength() }; if (layersMap.find(layerID) != layersMap.end()) { Log::Warning(Event::ParseStyle, "duplicate layer id %s", layerID.c_str()); continue; } layersMap.emplace(layerID, std::pair<const JSValue&, std::unique_ptr<Layer>> { layerValue, nullptr }); ids.push_back(layerID); } for (const auto& id : ids) { auto it = layersMap.find(id); parseLayer(it->first, it->second.first, it->second.second); } for (const auto& id : ids) { auto it = layersMap.find(id); if (it->second.second) { layers.emplace_back(std::move(it->second.second)); } } }
optional<std::array<float, 2>> parseProperty(const char* name, const JSValue& value) { if (value.IsArray() && value.Size() == 2 && value[rapidjson::SizeType(0)].IsNumber() && value[rapidjson::SizeType(1)].IsNumber()) { float first = value[rapidjson::SizeType(0)].GetDouble(); float second = value[rapidjson::SizeType(1)].GetDouble(); return { {{ first, second }} }; } else { Log::Warning(Event::ParseStyle, "value of '%s' must be an array of two numbers", name); return {}; } }
optional<std::vector<float>> parseProperty(const char* name, const JSValue& value) { if (!value.IsArray()) { Log::Warning(Event::ParseStyle, "value of '%s' must be an array of numbers", name); return {}; } std::vector<float> result; for (rapidjson::SizeType i = 0; i < value.Size(); ++i) { const JSValue& part = value[i]; if (!part.IsNumber()) { Log::Warning(Event::ParseStyle, "value of '%s' must be an array of numbers", name); return {}; } result.push_back(part.GetDouble()); } return result; }
optional<std::vector<std::string>> parseConstant(const char* name, const JSValue& value) { if (!value.IsArray()) { Log::Warning(Event::ParseStyle, "value of '%s' must be an array of strings", name); return {}; } std::vector<std::string> result; for (rapidjson::SizeType i = 0; i < value.Size(); ++i) { const JSValue& part = value[i]; if (!part.IsString()) { Log::Warning(Event::ParseStyle, "value of '%s' must be an array of strings", name); return {}; } result.push_back({ part.GetString(), part.GetStringLength() }); } return result; }
optional<std::vector<std::pair<float, T>>> parseStops(const char* name, const JSValue& value) { if (!value.IsArray()) { Log::Warning(Event::ParseStyle, "stops function must specify a stops array"); return {}; } std::vector<std::pair<float, T>> stops; for (rapidjson::SizeType i = 0; i < value.Size(); ++i) { const JSValue& stop = value[i]; if (!stop.IsArray()) { Log::Warning(Event::ParseStyle, "function argument must be a numeric value"); return {}; } if (stop.Size() != 2) { Log::Warning(Event::ParseStyle, "stop must have zoom level and value specification"); return {}; } const JSValue& z = stop[rapidjson::SizeType(0)]; if (!z.IsNumber()) { Log::Warning(Event::ParseStyle, "zoom level in stop must be a number"); return {}; } optional<T> v = parseProperty<T>(name, stop[rapidjson::SizeType(1)]); if (!v) { return {}; } stops.emplace_back(z.GetDouble(), *v); } return stops; }