示例#1
0
double OsmAnd::Utilities::parseLength(const QString& value, double defValue, bool* wasParsed/* = nullptr*/)
{
    int first, last;
    if (wasParsed)
        *wasParsed = false;
    if (!extractFirstNumberPosition(value, first, last, false, true))
        return defValue;
    bool ok;
    auto result = value.midRef(first, last - first + 1).toDouble(&ok);
    if (!ok)
        return defValue;

    if (wasParsed)
        *wasParsed = true;
    if (value.contains(QLatin1String("ft")) || value.contains('"'))
        result *= 0.3048;
    if (value.contains('\''))
    {
        auto inchesSubstr = value.mid(value.indexOf('"') + 1);
        if (!extractFirstNumberPosition(inchesSubstr, first, last, false, true))
        {
            if (wasParsed)
                *wasParsed = false;

            return defValue;
        }
        bool ok;
        auto inches = inchesSubstr.midRef(first, last - first + 1).toDouble(&ok);
        if (ok)
            result += inches * 0.0254;
    }
    return result;
}
bool OsmAnd::MapStyleEvaluator_P::evaluate(
    const MapObject* const mapObject,
    const std::shared_ptr<const IMapStyle::IRuleNode>& ruleNode,
    const std::shared_ptr<const InputValues>& inputValues,
    bool& outDisabled,
    IntermediateEvaluationResult* const outResultStorage,
    OnDemand<IntermediateEvaluationResult>& constantEvaluationResult) const
{
    // Check all values of a rule until all are checked.
    const auto& ruleNodeValues = ruleNode->getValuesRef();
    for (const auto& ruleValueEntry : rangeOf(constOf(ruleNodeValues)))
    {
        const auto valueDefId = ruleValueEntry.key();
        const auto& valueDef = owner->mapStyle->getValueDefinitionRefById(valueDefId);

        // Test only input values
        if (valueDef->valueClass != MapStyleValueDefinition::Class::Input)
            continue;

        const auto constantRuleValue = evaluateConstantValue(
            mapObject,
            valueDef->dataType,
            ruleValueEntry.value(),
            inputValues,
            constantEvaluationResult);

        InputValue inputValue;
        inputValues->get(valueDefId, inputValue);

        bool evaluationResult = false;
        if (valueDefId == _builtinValueDefs->id_INPUT_MINZOOM)
        {
            assert(!constantRuleValue.isComplex);
            evaluationResult = (constantRuleValue.asSimple.asInt <= inputValue.asInt);
        }
        else if (valueDefId == _builtinValueDefs->id_INPUT_MAXZOOM)
        {
            assert(!constantRuleValue.isComplex);
            evaluationResult = (constantRuleValue.asSimple.asInt >= inputValue.asInt);
        }
        else if (valueDefId == _builtinValueDefs->id_INPUT_ADDITIONAL)
        {
            if (!mapObject)
                evaluationResult = true;
            else
            {
                assert(!constantRuleValue.isComplex);
                const auto valueString = owner->mapStyle->getStringById(constantRuleValue.asSimple.asUInt);
                auto equalSignIdx = valueString.indexOf(QLatin1Char('='));
                if (equalSignIdx >= 0)
                {
                    const auto& tagRef = valueString.midRef(0, equalSignIdx);
                    const auto& valueRef = valueString.midRef(equalSignIdx + 1);
                    evaluationResult = mapObject->containsAttribute(tagRef, valueRef, true);
                }
                else
                    evaluationResult = mapObject->containsTag(valueString, true);
            }
        }
        else if (valueDefId == _builtinValueDefs->id_INPUT_TEST)
        {
            evaluationResult = (inputValue.asInt == 1);
        }
        else if (valueDef->dataType == MapStyleValueDataType::Float)
        {
            const auto lvalue = constantRuleValue.isComplex
                ? constantRuleValue.asComplex.asFloat.evaluate(owner->ptScaleFactor)
                : constantRuleValue.asSimple.asFloat;

            evaluationResult = qFuzzyCompare(lvalue, inputValue.asFloat);
        }
        else
        {
            const auto lvalue = constantRuleValue.isComplex
                ? constantRuleValue.asComplex.asInt.evaluate(owner->ptScaleFactor)
                : constantRuleValue.asSimple.asInt;

            evaluationResult = (lvalue == inputValue.asInt);
        }

        // If at least one value of rule does not match, it's failure
        if (!evaluationResult)
            return false;
    }

    // In case rule sets "disable", stop processing
    const auto citDisabledValue = ruleNodeValues.constFind(_builtinValueDefs->id_OUTPUT_DISABLE);
    if (citDisabledValue != ruleNodeValues.cend())
    {
        const auto disableValue = evaluateConstantValue(
            mapObject,
            _builtinValueDefs->OUTPUT_DISABLE->dataType,
            *citDisabledValue,
            inputValues,
            constantEvaluationResult);

        assert(!disableValue.isComplex);
        if (disableValue.asSimple.asUInt != 0)
        {
            outDisabled = true;
            return false;
        }
    }

    if (outResultStorage && !ruleNode->getIsSwitch())
        fillResultFromRuleNode(ruleNode, *outResultStorage, true);

    bool atLeastOneConditionalMatched = false;
    const auto& oneOfConditionalSubnodes = ruleNode->getOneOfConditionalSubnodesRef();
    for (const auto& oneOfConditionalSubnode : constOf(oneOfConditionalSubnodes))
    {
        const auto evaluationResult = evaluate(
            mapObject,
            oneOfConditionalSubnode,
            inputValues,
            outDisabled,
            outResultStorage,
            constantEvaluationResult);

        if (evaluationResult)
        {
            atLeastOneConditionalMatched = true;
            break;
        }
    }
    if (!atLeastOneConditionalMatched && ruleNode->getIsSwitch())
        return false;

    if (outResultStorage && ruleNode->getIsSwitch())
    {
        // Fill values from <switch> keeping values previously set by <case>
        fillResultFromRuleNode(ruleNode, *outResultStorage, false);
    }

    const auto& applySubnodes = ruleNode->getApplySubnodesRef();
    for (const auto& applySubnode : constOf(applySubnodes))
    {
        evaluate(
            mapObject,
            applySubnode,
            inputValues,
            outDisabled,
            outResultStorage,
            constantEvaluationResult);
    }

    if (outDisabled)
        return false;

    return true;
}