Value FunStartsWith::evaluate() const { String s1 = arg(0)->evaluate().toString(); String s2 = arg(1)->evaluate().toString(); if (s2.isEmpty()) return BOOL_TO_VALUE_CAST true; return BOOL_TO_VALUE_CAST (s1.startsWith(s2)); }
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 BOOL_TO_VALUE_CAST lhsBool; return BOOL_TO_VALUE_CAST (subExpr(1)->evaluate().toBoolean()); }
Value FunNot::evaluate() const { return BOOL_TO_VALUE_CAST (!arg(0)->evaluate().toBoolean()); }
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(BOOL_TO_VALUE_CAST (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, BOOL_TO_VALUE_CAST (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; }