📄 xpathfunctions.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"#include "XPathFunctions.h"#if ENABLE(XPATH)#include "Document.h"#include "Element.h"#include "NamedAttrMap.h"#include "XMLNames.h"#include "XPathUtil.h"#include "XPathValue.h"#include <wtf/MathExtras.h>namespace WebCore {namespace XPath {static inline bool isWhitespace(UChar c){ return c == ' ' || c == '\n' || c == '\r' || c == '\t';}#define DEFINE_FUNCTION_CREATOR(Class) static Function* create##Class() { return new Class; }class Interval {public: static const int Inf = -1; Interval(); Interval(int value); Interval(int min, int max); bool contains(int value) const;private: int m_min; int m_max;};struct FunctionRec { typedef Function *(*FactoryFn)(); FactoryFn factoryFn; Interval args;};static HashMap<String, FunctionRec>* functionMap;class FunLast : public Function { virtual Value evaluate() const;};class FunPosition : public Function { virtual Value evaluate() const;};class FunCount : public Function { virtual Value evaluate() const;};class FunId : public Function { virtual Value evaluate() const;};class FunLocalName : public Function { virtual Value evaluate() const;};class FunNamespaceURI : public Function { virtual Value evaluate() const;};class FunName : public Function { virtual Value evaluate() const;};class FunString : public Function { virtual Value evaluate() const;};class FunConcat : public Function { virtual Value evaluate() const;};class FunStartsWith : public Function { virtual Value evaluate() const;};class FunContains : public Function { virtual Value evaluate() const;};class FunSubstringBefore : public Function { virtual Value evaluate() const;};class FunSubstringAfter : public Function { virtual Value evaluate() const;};class FunSubstring : public Function { virtual Value evaluate() const;};class FunStringLength : public Function { virtual Value evaluate() const;};class FunNormalizeSpace : public Function { virtual Value evaluate() const;};class FunTranslate : public Function { virtual Value evaluate() const;};class FunBoolean : public Function { virtual Value evaluate() const;};class FunNot : public Function { virtual Value evaluate() const;};class FunTrue : public Function { virtual Value evaluate() const;};class FunFalse : public Function { virtual Value evaluate() const;};class FunLang : public Function { virtual Value evaluate() const;};class FunNumber : public Function { virtual Value evaluate() const;};class FunSum : public Function { virtual Value evaluate() const;};class FunFloor : public Function { virtual Value evaluate() const;};class FunCeiling : public Function { virtual Value evaluate() const;};class FunRound : public Function { virtual Value evaluate() const;public: static double round(double);};DEFINE_FUNCTION_CREATOR(FunLast)DEFINE_FUNCTION_CREATOR(FunPosition)DEFINE_FUNCTION_CREATOR(FunCount)DEFINE_FUNCTION_CREATOR(FunId)DEFINE_FUNCTION_CREATOR(FunLocalName)DEFINE_FUNCTION_CREATOR(FunNamespaceURI)DEFINE_FUNCTION_CREATOR(FunName)DEFINE_FUNCTION_CREATOR(FunString)DEFINE_FUNCTION_CREATOR(FunConcat)DEFINE_FUNCTION_CREATOR(FunStartsWith)DEFINE_FUNCTION_CREATOR(FunContains)DEFINE_FUNCTION_CREATOR(FunSubstringBefore)DEFINE_FUNCTION_CREATOR(FunSubstringAfter)DEFINE_FUNCTION_CREATOR(FunSubstring)DEFINE_FUNCTION_CREATOR(FunStringLength)DEFINE_FUNCTION_CREATOR(FunNormalizeSpace)DEFINE_FUNCTION_CREATOR(FunTranslate)DEFINE_FUNCTION_CREATOR(FunBoolean)DEFINE_FUNCTION_CREATOR(FunNot)DEFINE_FUNCTION_CREATOR(FunTrue)DEFINE_FUNCTION_CREATOR(FunFalse)DEFINE_FUNCTION_CREATOR(FunLang)DEFINE_FUNCTION_CREATOR(FunNumber)DEFINE_FUNCTION_CREATOR(FunSum)DEFINE_FUNCTION_CREATOR(FunFloor)DEFINE_FUNCTION_CREATOR(FunCeiling)DEFINE_FUNCTION_CREATOR(FunRound)#undef DEFINE_FUNCTION_CREATORinline Interval::Interval() : m_min(Inf), m_max(Inf){}inline Interval::Interval(int value) : m_min(value), m_max(value){}inline Interval::Interval(int min, int max) : m_min(min), m_max(max){}inline bool Interval::contains(int value) const{ if (m_min == Inf && m_max == Inf) return true; if (m_min == Inf) return value <= m_max; if (m_max == Inf) return value >= m_min; return value >= m_min && value <= m_max;}void Function::setArguments(const Vector<Expression*>& args){ Vector<Expression*>::const_iterator end = args.end(); for (Vector<Expression*>::const_iterator it = args.begin(); it != end; it++) addSubExpression(*it);}Value FunLast::evaluate() const{ return Expression::evaluationContext().size;}Value FunPosition::evaluate() const{ return Expression::evaluationContext().position;}Value FunId::evaluate() const{ Value a = arg(0)->evaluate(); Vector<UChar> idList; // A whitespace-separated list of IDs if (a.isNodeSet()) { const NodeSet& nodes = a.toNodeSet(); for (size_t i = 0; i < nodes.size(); ++i) { String str = stringValue(nodes[i]); idList.append(str.characters(), str.length()); idList.append(' '); } } else { String str = a.toString(); idList.append(str.characters(), str.length()); } Document* contextDocument = evaluationContext().node->document(); NodeSet result; HashSet<Node*> resultSet; size_t startPos = 0; size_t length = idList.size(); while (true) { while (startPos < length && isWhitespace(idList[startPos])) ++startPos; if (startPos == length) break; size_t endPos = startPos; while (endPos < length && !isWhitespace(idList[endPos])) ++endPos; // If there are several nodes with the same id, id() should return the first one. // In WebKit, getElementById behaves so, too, although its behavior in this case is formally undefined. Node* node = contextDocument->getElementById(String(&idList[startPos], endPos - startPos)); if (node && resultSet.add(node).second) result.append(node); startPos = endPos; } result.markSorted(false); return Value(result, Value::adopt);}Value FunLocalName::evaluate() const{ Node* node = 0; if (argCount() > 0) { Value a = arg(0)->evaluate(); if (!a.isNodeSet()) return ""; node = a.toNodeSet().firstNode(); if (!node) return ""; } if (!node) node = evaluationContext().node.get(); return node->localName().string();}Value FunNamespaceURI::evaluate() const{ Node* node = 0; if (argCount() > 0) { Value a = arg(0)->evaluate(); if (!a.isNodeSet()) return ""; node = a.toNodeSet().firstNode(); if (!node) return "";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -