⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xpathpredicate.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
字号:
/* * Copyright 2005 Frerich Raabe <raabe@kde.org> * Copyright (C) 2006 Apple Computer, Inc. * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: *  * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. *  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#include "config.h"#if ENABLE(XPATH)#include "XPathPredicate.h"#include "Node.h"#include "XPathFunctions.h"#include "XPathUtil.h"#include "XPathValue.h"#include <math.h>#include <wtf/MathExtras.h>namespace WebCore {namespace XPath {        Number::Number(double value)    : m_value(value){}Value Number::evaluate() const{    return m_value;}StringExpression::StringExpression(const String& value)    : m_value(value){}Value StringExpression::evaluate() const{    return m_value;}Value Negative::evaluate() const{    Value p(subExpr(0)->evaluate());    return -p.toNumber();}NumericOp::NumericOp(Opcode opcode, Expression* lhs, Expression* rhs)    : m_opcode(opcode){    addSubExpression(lhs);    addSubExpression(rhs);}Value NumericOp::evaluate() const{    Value lhs(subExpr(0)->evaluate());    Value rhs(subExpr(1)->evaluate());        double leftVal = lhs.toNumber();    double rightVal = rhs.toNumber();    switch (m_opcode) {        case OP_Add:            return leftVal + rightVal;        case OP_Sub:            return leftVal - rightVal;        case OP_Mul:            return leftVal * rightVal;        case OP_Div:            return leftVal / rightVal;        case OP_Mod:            return fmod(leftVal, rightVal);    }    ASSERT_NOT_REACHED();    return 0.0;}EqTestOp::EqTestOp(Opcode opcode, Expression* lhs, Expression* rhs)    : m_opcode(opcode){    addSubExpression(lhs);    addSubExpression(rhs);}bool EqTestOp::compare(const Value& lhs, const Value& rhs) const{    if (lhs.isNodeSet()) {        const NodeSet& lhsSet = lhs.toNodeSet();        if (rhs.isNodeSet()) {            // If both objects to be compared are node-sets, then the comparison will be true if and only if            // there is a node in the first node-set and a node in the second node-set such that the result of            // performing the comparison on the string-values of the two nodes is true.            const NodeSet& rhsSet = rhs.toNodeSet();            for (unsigned lindex = 0; lindex < lhsSet.size(); ++lindex)                for (unsigned rindex = 0; rindex < rhsSet.size(); ++rindex)                    if (compare(stringValue(lhsSet[lindex]), stringValue(rhsSet[rindex])))                        return true;            return false;        }        if (rhs.isNumber()) {            // If one object to be compared is a node-set and the other is a number, then the comparison will be true            // if and only if there is a node in the node-set such that the result of performing the comparison on the number            // to be compared and on the result of converting the string-value of that node to a number using the number function is true.            for (unsigned lindex = 0; lindex < lhsSet.size(); ++lindex)                if (compare(Value(stringValue(lhsSet[lindex])).toNumber(), rhs))                    return true;            return false;        }        if (rhs.isString()) {            // If one object to be compared is a node-set and the other is a string, then the comparison will be true            // if and only if there is a node in the node-set such that the result of performing the comparison on            // the string-value of the node and the other string is true.            for (unsigned lindex = 0; lindex < lhsSet.size(); ++lindex)                if (compare(stringValue(lhsSet[lindex]), rhs))                    return true;            return false;        }        if (rhs.isBoolean()) {            // If one object to be compared is a node-set and the other is a boolean, then the comparison will be true            // if and only if the result of performing the comparison on the boolean and on the result of converting            // the node-set to a boolean using the boolean function is true.            return compare(lhs.toBoolean(), rhs);        }        ASSERT(0);    }    if (rhs.isNodeSet()) {        const NodeSet& rhsSet = rhs.toNodeSet();        if (lhs.isNumber()) {            for (unsigned rindex = 0; rindex < rhsSet.size(); ++rindex)                if (compare(lhs, Value(stringValue(rhsSet[rindex])).toNumber()))                    return true;            return false;        }        if (lhs.isString()) {            for (unsigned rindex = 0; rindex < rhsSet.size(); ++rindex)                if (compare(lhs, stringValue(rhsSet[rindex])))                    return true;            return false;        }        if (lhs.isBoolean())            return compare(lhs, rhs.toBoolean());        ASSERT(0);    }        // Neither side is a NodeSet.    switch (m_opcode) {        case OP_EQ:        case OP_NE:            bool equal;            if (lhs.isBoolean() || rhs.isBoolean())                equal = lhs.toBoolean() == rhs.toBoolean();            else if (lhs.isNumber() || rhs.isNumber())                equal = lhs.toNumber() == rhs.toNumber();            else                equal = lhs.toString() == rhs.toString();            if (m_opcode == OP_EQ)                return equal;            return !equal;        case OP_GT:            return lhs.toNumber() > rhs.toNumber();        case OP_GE:            return lhs.toNumber() >= rhs.toNumber();        case OP_LT:            return lhs.toNumber() < rhs.toNumber();        case OP_LE:            return lhs.toNumber() <= rhs.toNumber();    }    ASSERT(0);    return false;}Value EqTestOp::evaluate() const{    Value lhs(subExpr(0)->evaluate());    Value rhs(subExpr(1)->evaluate());    return compare(lhs, rhs);}LogicalOp::LogicalOp(Opcode opcode, Expression* lhs, Expression* rhs)    : m_opcode(opcode){    addSubExpression(lhs);    addSubExpression(rhs);}bool LogicalOp::shortCircuitOn() const{    if (m_opcode == OP_And)        return false; //false and foo    return true;  //true or bar}Value LogicalOp::evaluate() const{    Value lhs(subExpr(0)->evaluate());    // This is not only an optimization, http://www.w3.org/TR/xpath    // dictates that we must do short-circuit evaluation    bool lhsBool = lhs.toBoolean();    if (lhsBool == shortCircuitOn())        return lhsBool;    return subExpr(1)->evaluate().toBoolean();}Value Union::evaluate() const{    Value lhsResult = subExpr(0)->evaluate();    Value rhs = subExpr(1)->evaluate();    if (!lhsResult.isNodeSet() || !rhs.isNodeSet())        return NodeSet();        NodeSet& resultSet = lhsResult.modifiableNodeSet();    const NodeSet& rhsNodes = rhs.toNodeSet();        HashSet<Node*> nodes;    for (size_t i = 0; i < resultSet.size(); ++i)        nodes.add(resultSet[i]);        for (size_t i = 0; i < rhsNodes.size(); ++i) {        Node* node = rhsNodes[i];        if (nodes.add(node).second)            resultSet.append(node);    }    // It is also possible to use merge sort to avoid making the result unsorted;    // but this would waste the time in cases when order is not important.    resultSet.markSorted(false);    return lhsResult;}Predicate::Predicate(Expression* expr)    : m_expr(expr){}Predicate::~Predicate(){    delete m_expr;}bool Predicate::evaluate() const{    ASSERT(m_expr != 0);    Value result(m_expr->evaluate());    // foo[3] means foo[position()=3]    if (result.isNumber())        return EqTestOp(EqTestOp::OP_EQ, createFunction("position"), new Number(result.toNumber())).evaluate().toBoolean();    return result.toBoolean();}}}#endif // ENABLE(XPATH)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -