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);
}
Beispiel #4
0
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);
}