27 #include "xml/dom_docimpl.h" 28 #include "xml/dom_nodeimpl.h" 29 #include "xml/dom_nodelistimpl.h" 30 #include "xml/dom_elementimpl.h" 31 #include "kjs/operations.h" 42 #define DEFINE_FUNCTION_CREATOR(Class) \ 43 static Function *create##Class() { return new Class; } 48 static const int Inf =-1;
51 Interval(
int value );
52 Interval(
int min,
int max );
54 bool contains(
int value )
const;
56 QString asString()
const;
63 class FunLast :
public Function
66 virtual bool isConstant()
const;
69 virtual Value doEvaluate()
const;
72 class FunPosition :
public Function
75 virtual bool isConstant()
const;
78 virtual Value doEvaluate()
const;
81 class FunCount :
public Function
84 virtual bool isConstant()
const;
87 virtual Value doEvaluate()
const;
93 class NodeFunction :
public Function
96 virtual Value doEvaluate()
const;
97 virtual Value evaluateOnNode( DOM::NodeImpl* node )
const = 0;
100 class FunLocalName :
public NodeFunction
103 virtual bool isConstant()
const;
106 virtual Value evaluateOnNode( DOM::NodeImpl* node )
const;
109 class FunNamespaceURI :
public NodeFunction
112 virtual bool isConstant()
const;
115 virtual Value evaluateOnNode( DOM::NodeImpl* node )
const;
118 class FunName :
public NodeFunction
121 virtual bool isConstant()
const;
124 virtual Value evaluateOnNode( DOM::NodeImpl* node )
const;
127 class FunId :
public Function
130 virtual Value doEvaluate()
const;
133 class FunString :
public Function
136 virtual Value doEvaluate()
const;
139 class FunConcat :
public Function
142 virtual Value doEvaluate()
const;
145 class FunStartsWith :
public Function
148 virtual Value doEvaluate()
const;
151 class FunContains :
public Function
154 virtual Value doEvaluate()
const;
157 class FunSubstringBefore :
public Function
160 virtual Value doEvaluate()
const;
163 class FunSubstringAfter :
public Function
166 virtual Value doEvaluate()
const;
169 class FunSubstring :
public Function
172 virtual Value doEvaluate()
const;
175 class FunStringLength :
public Function
178 virtual Value doEvaluate()
const;
181 class FunNormalizeSpace :
public Function
184 virtual Value doEvaluate()
const;
187 class FunTranslate :
public Function
190 virtual Value doEvaluate()
const;
193 class FunBoolean :
public Function
196 virtual Value doEvaluate()
const;
199 class FunNot :
public Function
202 virtual Value doEvaluate()
const;
205 class FunTrue :
public Function
208 virtual bool isConstant()
const;
211 virtual Value doEvaluate()
const;
214 class FunFalse :
public Function
217 virtual bool isConstant()
const;
220 virtual Value doEvaluate()
const;
223 class FunLang :
public Function
226 virtual bool isConstant()
const;
229 virtual Value doEvaluate()
const;
232 class FunNumber :
public Function
235 virtual Value doEvaluate()
const;
238 class FunSum :
public Function
241 virtual Value doEvaluate()
const;
244 class FunFloor :
public Function
247 virtual Value doEvaluate()
const;
250 class FunCeiling :
public Function
253 virtual Value doEvaluate()
const;
256 class FunRound :
public Function
259 virtual Value doEvaluate()
const;
293 #undef DEFINE_FUNCTION_CREATOR 301 Interval::Interval(
int value )
307 Interval::Interval(
int min,
int max )
313 bool Interval::contains(
int value )
const 315 if ( m_min == Inf && m_max == Inf ) {
319 if ( m_min == Inf ) {
320 return value <= m_max;
323 if ( m_max == Inf ) {
324 return value >= m_min;
327 return value >= m_min && value <= m_max;
330 QString Interval::asString()
const 334 if ( m_min == Inf ) {
337 s += QString::number( m_min );
342 if ( m_max == Inf ) {
345 s += QString::number( m_max );
356 addSubExpression( arg );
365 QString Function::dump()
const 367 if ( argCount() == 0 ) {
368 return QString(
"<function name=\"%1\"/>" ).arg(
name().
string() );
371 QString s = QString(
"<function name=\"%1\">" ).arg(
name().
string() );
372 for (
unsigned int i = 0; i < argCount(); ++i ) {
373 s +=
"<operand>" + arg( i )->dump() +
"</operand>";
390 unsigned int Function::argCount()
const 392 return subExprCount();
400 Value FunLast::doEvaluate()
const 402 return Value(
double( Expression::evaluationContext().size ) );
405 bool FunLast::isConstant()
const 410 Value FunPosition::doEvaluate()
const 412 return Value(
double( Expression::evaluationContext().position ) );
415 bool FunPosition::isConstant()
const 420 Value NodeFunction::doEvaluate()
const 423 if ( argCount() > 0 ) {
424 Value a = arg( 0 )->evaluate();
430 node = evaluationContext().node;
436 return evaluateOnNode( node );
439 bool FunLocalName::isConstant()
const 444 Value FunLocalName::evaluateOnNode( DOM::NodeImpl* node )
const 447 switch ( node->nodeType() ) {
449 n = node->nodeName();
452 n = node->localName();
457 bool FunNamespaceURI::isConstant()
const 462 Value FunNamespaceURI::evaluateOnNode( DOM::NodeImpl* node )
const 464 return Value( node->namespaceURI() );
467 Value FunId::doEvaluate()
const 469 Value a = arg( 0 )->evaluate();
471 WTF::Vector<DOM::DOMString> ids;
476 for (
unsigned long i = 0; i <
set->length(); ++i)
477 queryString +=
stringValue( set->item(i) ).
string() + QLatin1Char(
' ');
482 QStringList qids = queryString.simplified().split(
' ');
483 for (
int i = 0; i < qids.size(); ++i)
487 DOM::DocumentImpl* doc = Expression::evaluationContext().node->document();
489 for (
unsigned i = 0; i < ids.size(); ++i ) {
490 DOM::ElementImpl* e = doc->getElementById( ids[i] );
499 bool FunName::isConstant()
const 504 Value FunName::evaluateOnNode( DOM::NodeImpl* node )
const 507 switch ( node->nodeType() ) {
515 n =
static_cast<DOM::ElementImpl*
>( node )->nonCaseFoldedTagName();
519 n = node->nodeName();
524 Value FunCount::doEvaluate()
const 526 Value a = arg( 0 )->evaluate();
528 Expression::reportInvalidExpressionErr();
529 kWarning() <<
"count() expects <nodeset>";
532 a.
toNodeset()->normalizeUpto(StaticNodeListImpl::AxisOrder);
537 bool FunCount::isConstant()
const 542 Value FunString::doEvaluate()
const 544 if ( argCount() == 0 ) {
548 return Value( arg( 0 )->evaluate().toString() );
551 Value FunConcat::doEvaluate()
const 554 for (
unsigned int i = 0; i < argCount(); ++i ) {
555 str.append( arg( i )->evaluate().toString().
string() );
560 Value FunStartsWith::doEvaluate()
const 562 DOMString s1 = arg( 0 )->evaluate().toString();
563 DOMString s2 = arg( 1 )->evaluate().toString();
566 return Value(
true );
572 Value FunContains::doEvaluate()
const 575 QString s2 = arg( 1 )->evaluate().toString().string();
577 if ( s2.isEmpty() ) {
578 return Value(
true );
581 return Value( s1.contains( s2 ) );
584 Value FunSubstringBefore::doEvaluate()
const 587 QString s2 = arg( 1 )->evaluate().toString().string();
589 if ( s2.isEmpty() ) {
593 int i = s1.indexOf( s2 );
601 Value FunSubstringAfter::doEvaluate()
const 604 QString s2 = arg( 1 )->evaluate().toString().string();
606 if ( s2.isEmpty() ) {
610 int i = s1.indexOf( s2 );
618 Value FunSubstring::doEvaluate()
const 621 long pos = long( qRound( arg( 1 )->evaluate().toNumber() ) );
622 bool haveLength = argCount() == 3;
625 len = long( qRound( arg( 2 )->evaluate().toNumber() ) );
628 if ( pos >
long( s.length() ) ) {
632 if ( haveLength && pos < 1 ) {
643 Value FunStringLength::doEvaluate()
const 645 if ( argCount() == 0 ) {
650 return Value(
double( arg( 0 )->evaluate().toString().length() ) );
653 Value FunNormalizeSpace::doEvaluate()
const 655 if ( argCount() == 0 ) {
660 QString s = arg( 0 )->evaluate().toString().string();
665 Value FunTranslate::doEvaluate()
const 668 QString s2 = arg( 1 )->evaluate().toString().string();
669 QString s3 = arg( 2 )->evaluate().toString().string();
672 for (
int i1 = 0; i1 < s1.length(); ++i1 ) {
674 int i2 = s2.indexOf( ch );
677 }
else if ( i2 < s3.length() ) {
678 newString += s3[ i2 ];
685 Value FunBoolean::doEvaluate()
const 687 return Value( arg( 0 )->evaluate().toBoolean() );
690 Value FunNot::doEvaluate()
const 692 return Value( !arg( 0 )->evaluate().toBoolean() );
695 Value FunTrue::doEvaluate()
const 697 return Value(
true );
700 bool FunTrue::isConstant()
const 706 #warning "This looks bogus" 709 Value FunLang::doEvaluate()
const 713 NodeImpl* node = evaluationContext().node;
718 if (node->isElementNode()) {
719 langNodeValue =
static_cast<ElementImpl*
>(node)->getAttribute(
"xml:lang");
720 if ( !langNodeValue.
isNull() )
726 if ( langNodeValue.
isNull() ) {
727 return Value(
false );
731 QString langNodeValueString = langNodeValue.
string();
732 QString langNodeBaseString = langNodeValueString.left( langNodeValueString.indexOf(
'-' ) );
734 return Value( langNodeValueString.toLower() == lang.toLower() ||
735 langNodeBaseString.toLower() == lang.toLower() );
738 bool FunLang::isConstant()
const 743 Value FunFalse::doEvaluate()
const 745 return Value(
false );
748 bool FunFalse::isConstant()
const 753 Value FunNumber::doEvaluate()
const 756 if ( argCount() == 0 ) {
762 vi = arg( 0 )->evaluate();
768 Value FunSum::doEvaluate()
const 770 Value a = arg( 0 )->evaluate();
772 Expression::reportInvalidExpressionErr();
773 kWarning() <<
"sum() expects <nodeset>";
779 for (
unsigned long n = 0; n < nodes->length(); ++n) {
780 NodeImpl* node = nodes->item(n);
786 Value FunFloor::doEvaluate()
const 788 const double num = arg( 0 )->evaluate().
toNumber();
790 if ( KJS::isNaN( num ) || KJS::isInf( num ) ) {
794 return Value( floor( num ) );
797 Value FunCeiling::doEvaluate()
const 799 const double num = arg( 0 )->evaluate().
toNumber();
801 if ( KJS::isNaN( num ) || KJS::isInf( num ) ) {
805 return Value( ceil( num ) );
808 Value FunRound::doEvaluate()
const 810 return Value(
double( qRound( arg( 0 )->evaluate().toNumber() ) ) );
813 struct FunctionLibrary::FunctionRec
821 struct FunctionMapping
824 FunctionLibrary::FunctionRec
function;
828 {
"last", { &createFunLast, 0 } },
829 {
"last", { &createFunLast, 0 } },
830 {
"position", { &createFunPosition, 0 } },
831 {
"count", { &createFunCount, 1 } },
832 {
"sum", { &createFunSum, 1 } },
833 {
"local-name", { &createFunLocalName, Interval( 0, 1 ) } },
834 {
"namespace-uri", { &createFunNamespaceURI, Interval( 0, 1 ) } },
835 {
"id", { &createFunId, 1 } },
836 {
"name", { &createFunName, Interval( 0, 1 ) } },
839 {
"string", { &createFunString, Interval( 0, 1 ) } },
840 {
"concat", { &createFunConcat, Interval( 2, Interval::Inf ) } },
841 {
"starts-with", { &createFunStartsWith, 2 } },
842 {
"contains", { &createFunContains, 2 } },
843 {
"substring-before", { &createFunSubstringBefore, 2 } },
844 {
"substring-after", { &createFunSubstringAfter, 2 } },
845 {
"substring", { &createFunSubstring, Interval( 2, 3 ) } },
846 {
"string-length", { &createFunStringLength, Interval( 0, 1 ) } },
847 {
"normalize-space", { &createFunNormalizeSpace, Interval( 0, 1 ) } },
848 {
"translate", { &createFunTranslate, 3 } },
850 {
"boolean", { &createFunBoolean, 1 } },
851 {
"not", { &createFunNot, 1 } },
852 {
"true", { &createFunTrue, 0 } },
853 {
"false", { &createFunFalse, 0 } },
854 {
"lang", { &createFunLang, 1 } },
856 {
"number", { &createFunNumber, Interval( 0, 1 ) } },
857 {
"floor", { &createFunFloor, 1 } },
858 {
"ceiling", { &createFunCeiling, 1 } },
859 {
"round", { &createFunRound, 1 } }
869 FunctionLibrary::FunctionLibrary()
872 m_functionDict.insert( functions[ i ].
name, functions[ i ].
function );
879 if ( !m_functionDict.contains( name ) ) {
880 kWarning() <<
"Function '" << name <<
"' not supported by this implementation.";
885 FunctionRec functionRec = m_functionDict[ name ];
886 if ( !functionRec.args.contains( args.count() ) ) {
887 kWarning() <<
"Function '" << name <<
"' requires " << functionRec.args.asString() <<
" arguments, but " << args.count() <<
" given.";
891 Function *
function = functionRec.factoryFn();
893 function->setName( name );
DOM::DOMString toString() const
const char * name(StandardAction id)
static const unsigned int numFunctions
SharedPtr< DOM::StaticNodeListImpl > DomNodeList
static FunctionMapping functions[]
DOMString stringValue(NodeImpl *node)
This class implements the basic string we use in the DOM.
bool startsWith(const DOMString &str) const
This library provides a full-featured HTML parser and widget.
void setArguments(const QList< Expression * > &args)
static KJavaAppletServer * self
DOM::NodeImpl * xpathParentNode(DOM::NodeImpl *node)
static QDebug kWarning(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
#define DEFINE_FUNCTION_CREATOR(Class)
DomNodeList & toNodeset()