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() };
}
Esempio n. 2
0
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;
}