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) \
43static 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;
63class FunLast :
public Function
66 virtual bool isConstant()
const;
69 virtual Value doEvaluate()
const;
72class FunPosition :
public Function
75 virtual bool isConstant()
const;
78 virtual Value doEvaluate()
const;
81class FunCount :
public Function
84 virtual bool isConstant()
const;
87 virtual Value doEvaluate()
const;
93class NodeFunction :
public Function
96 virtual Value doEvaluate()
const;
97 virtual Value evaluateOnNode( DOM::NodeImpl* node )
const = 0;
100class FunLocalName :
public NodeFunction
103 virtual bool isConstant()
const;
106 virtual Value evaluateOnNode( DOM::NodeImpl* node )
const;
109class FunNamespaceURI :
public NodeFunction
112 virtual bool isConstant()
const;
115 virtual Value evaluateOnNode( DOM::NodeImpl* node )
const;
118class FunName :
public NodeFunction
121 virtual bool isConstant()
const;
124 virtual Value evaluateOnNode( DOM::NodeImpl* node )
const;
127class FunId :
public Function
130 virtual Value doEvaluate()
const;
133class FunString :
public Function
136 virtual Value doEvaluate()
const;
139class FunConcat :
public Function
142 virtual Value doEvaluate()
const;
145class FunStartsWith :
public Function
148 virtual Value doEvaluate()
const;
151class FunContains :
public Function
154 virtual Value doEvaluate()
const;
157class FunSubstringBefore :
public Function
160 virtual Value doEvaluate()
const;
163class FunSubstringAfter :
public Function
166 virtual Value doEvaluate()
const;
169class FunSubstring :
public Function
172 virtual Value doEvaluate()
const;
175class FunStringLength :
public Function
178 virtual Value doEvaluate()
const;
181class FunNormalizeSpace :
public Function
184 virtual Value doEvaluate()
const;
187class FunTranslate :
public Function
190 virtual Value doEvaluate()
const;
193class FunBoolean :
public Function
196 virtual Value doEvaluate()
const;
199class FunNot :
public Function
202 virtual Value doEvaluate()
const;
205class FunTrue :
public Function
208 virtual bool isConstant()
const;
211 virtual Value doEvaluate()
const;
214class FunFalse :
public Function
217 virtual bool isConstant()
const;
220 virtual Value doEvaluate()
const;
223class FunLang :
public Function
226 virtual bool isConstant()
const;
229 virtual Value doEvaluate()
const;
232class FunNumber :
public Function
235 virtual Value doEvaluate()
const;
238class FunSum :
public Function
241 virtual Value doEvaluate()
const;
244class FunFloor :
public Function
247 virtual Value doEvaluate()
const;
250class FunCeiling :
public Function
253 virtual Value doEvaluate()
const;
256class FunRound :
public Function
259 virtual Value doEvaluate()
const;
293#undef DEFINE_FUNCTION_CREATOR
301Interval::Interval(
int value )
307Interval::Interval(
int min,
int max )
313bool 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;
330QString 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 );
365QString 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>";
390unsigned int Function::argCount()
const
392 return subExprCount();
400Value FunLast::doEvaluate()
const
402 return Value(
double( Expression::evaluationContext().size ) );
405bool FunLast::isConstant()
const
410Value FunPosition::doEvaluate()
const
412 return Value(
double( Expression::evaluationContext().position ) );
415bool FunPosition::isConstant()
const
420Value NodeFunction::doEvaluate()
const
423 if ( argCount() > 0 ) {
424 Value a = arg( 0 )->evaluate();
425 if ( a.isNodeset() && a.toNodeset()->length() ) {
426 node = a.toNodeset()->first();
430 node = evaluationContext().node;
436 return evaluateOnNode( node );
439bool FunLocalName::isConstant()
const
444Value FunLocalName::evaluateOnNode( DOM::NodeImpl* node )
const
447 switch ( node->nodeType() ) {
449 n = node->nodeName();
452 n = node->localName();
457bool FunNamespaceURI::isConstant()
const
462Value FunNamespaceURI::evaluateOnNode( DOM::NodeImpl* node )
const
464 return Value( node->namespaceURI() );
467Value FunId::doEvaluate()
const
469 Value a = arg( 0 )->evaluate();
471 WTF::Vector<DOM::DOMString> ids;
474 if ( a.isNodeset() ) {
476 for (
unsigned long i = 0; i < set->length(); ++i)
479 queryString = a.toString().string();
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] );
499bool FunName::isConstant()
const
504Value FunName::evaluateOnNode( DOM::NodeImpl* node )
const
507 switch ( node->nodeType() ) {
515 n =
static_cast<DOM::ElementImpl*
>( node )->nonCaseFoldedTagName();
519 n = node->nodeName();
524Value FunCount::doEvaluate()
const
526 Value a = arg( 0 )->evaluate();
527 if ( !a.isNodeset() ) {
528 Expression::reportInvalidExpressionErr();
529 kWarning() <<
"count() expects <nodeset>";
532 a.toNodeset()->normalizeUpto(StaticNodeListImpl::AxisOrder);
534 return Value(
double( a.toNodeset()->length() ) );
537bool FunCount::isConstant()
const
542Value FunString::doEvaluate()
const
544 if ( argCount() == 0 ) {
545 DOMString s = Value( Expression::evaluationContext().node ).toString();
548 return Value( arg( 0 )->evaluate().toString() );
551Value FunConcat::doEvaluate()
const
554 for (
unsigned int i = 0; i < argCount(); ++i ) {
555 str.append( arg( i )->evaluate().toString().string() );
560Value FunStartsWith::doEvaluate()
const
562 DOMString s1 = arg( 0 )->evaluate().toString();
563 DOMString s2 = arg( 1 )->evaluate().toString();
566 return Value(
true );
572Value FunContains::doEvaluate()
const
574 QString s1 = arg( 0 )->evaluate().toString().
string();
575 QString s2 = arg( 1 )->evaluate().toString().
string();
577 if ( s2.isEmpty() ) {
578 return Value(
true );
581 return Value( s1.contains( s2 ) );
584Value FunSubstringBefore::doEvaluate()
const
586 QString s1 = arg( 0 )->evaluate().toString().string();
587 QString s2 = arg( 1 )->evaluate().toString().string();
589 if ( s2.isEmpty() ) {
593 int i = s1.indexOf( s2 );
598 return Value(
DOMString( s1.left( i ) ) );
601Value FunSubstringAfter::doEvaluate()
const
603 QString s1 = arg( 0 )->evaluate().toString().string();
604 QString s2 = arg( 1 )->evaluate().toString().string();
606 if ( s2.isEmpty() ) {
610 int i = s1.indexOf( s2 );
615 return Value(
DOMString( s1.mid( i + s2.length() ) ) );
618Value FunSubstring::doEvaluate()
const
620 QString s = arg( 0 )->evaluate().toString().
string();
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 ) {
640 return Value(
DOMString( s.mid( pos - 1, len ) ) );
643Value FunStringLength::doEvaluate()
const
645 if ( argCount() == 0 ) {
646 DOMString s = Value( Expression::evaluationContext().node ).toString();
647 return Value(
double( s.
length() ) );
650 return Value(
double( arg( 0 )->evaluate().toString().length() ) );
653Value FunNormalizeSpace::doEvaluate()
const
655 if ( argCount() == 0 ) {
656 DOMString s = Value( Expression::evaluationContext().node ).toString();
660 QString s = arg( 0 )->evaluate().toString().
string();
665Value FunTranslate::doEvaluate()
const
667 QString s1 = arg( 0 )->evaluate().toString().string();
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 ];
685Value FunBoolean::doEvaluate()
const
687 return Value( arg( 0 )->evaluate().toBoolean() );
690Value FunNot::doEvaluate()
const
692 return Value( !arg( 0 )->evaluate().toBoolean() );
695Value FunTrue::doEvaluate()
const
697 return Value(
true );
700bool FunTrue::isConstant()
const
706#warning "This looks bogus"
709Value FunLang::doEvaluate()
const
711 QString lang = arg( 0 )->evaluate().toString().string();
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() );
738bool FunLang::isConstant()
const
743Value FunFalse::doEvaluate()
const
745 return Value(
false );
748bool FunFalse::isConstant()
const
753Value FunNumber::doEvaluate()
const
756 if ( argCount() == 0 ) {
762 vi = arg( 0 )->evaluate();
765 return Value( vi.toNumber() );
768Value FunSum::doEvaluate()
const
770 Value a = arg( 0 )->evaluate();
771 if ( !a.isNodeset() ) {
772 Expression::reportInvalidExpressionErr();
773 kWarning() <<
"sum() expects <nodeset>";
779 for (
unsigned long n = 0; n < nodes->
length(); ++n) {
780 NodeImpl* node = nodes->item(n);
786Value FunFloor::doEvaluate()
const
788 const double num = arg( 0 )->evaluate().toNumber();
790 if ( KJS::isNaN( num ) || KJS::isInf( num ) ) {
794 return Value( floor( num ) );
797Value FunCeiling::doEvaluate()
const
799 const double num = arg( 0 )->evaluate().toNumber();
801 if ( KJS::isNaN( num ) || KJS::isInf( num ) ) {
805 return Value( ceil( num ) );
808Value FunRound::doEvaluate()
const
810 return Value(
double( qRound( arg( 0 )->evaluate().toNumber() ) ) );
813struct FunctionLibrary::FunctionRec
815 typedef Function *(*FactoryFn )();
821struct 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 } }
869FunctionLibrary::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();
This class implements the basic string we use in the DOM.
bool startsWith(const DOMString &str) const
@ PROCESSING_INSTRUCTION_NODE
void setArguments(const QList< Expression * > &args)
void setName(const DOM::DOMString &name)
#define DEFINE_FUNCTION_CREATOR(Class)
This library provides a full-featured HTML parser and widget.
const char * name(StandardAction id)
static const unsigned int numFunctions
static FunctionMapping functions[]
DOM::NodeImpl * xpathParentNode(DOM::NodeImpl *node)
DOMString stringValue(NodeImpl *node)
SharedPtr< DOM::StaticNodeListImpl > DomNodeList