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;
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 );
367 if ( argCount() == 0 ) {
368 return 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();
425 if ( a.isNodeset() && a.toNodeset()->length() ) {
426 node = a.toNodeset()->first();
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() ) {
448 case Node::PROCESSING_INSTRUCTION_NODE:
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;
474 if ( a.isNodeset() ) {
476 for (
unsigned long i = 0; i < set->length(); ++i)
477 queryString +=
stringValue( set->item(i) ).
string() + QLatin1Char(
' ');
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] );
499 bool FunName::isConstant()
const
504 Value FunName::evaluateOnNode( DOM::NodeImpl* node )
const
507 switch ( node->nodeType() ) {
508 case Node::TEXT_NODE:
509 case Node::CDATA_SECTION_NODE:
510 case Node::COMMENT_NODE:
511 case Node::DOCUMENT_NODE:
514 case Node::ELEMENT_NODE: {
515 n =
static_cast<DOM::ElementImpl*
>( node )->nonCaseFoldedTagName();
519 n = node->nodeName();
524 Value 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() ) );
537 bool FunCount::isConstant()
const
542 Value FunString::doEvaluate()
const
544 if ( argCount() == 0 ) {
545 DOMString s = Value( Expression::evaluationContext().node ).toString();
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
577 if ( s2.isEmpty() ) {
578 return Value(
true );
581 return Value( s1.contains( s2 ) );
584 Value 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 ) ) );
601 Value 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() ) ) );
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 ) {
640 return Value(
DOMString( s.mid( pos - 1, len ) ) );
643 Value 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() ) );
653 Value FunNormalizeSpace::doEvaluate()
const
655 if ( argCount() == 0 ) {
656 DOMString s = Value( Expression::evaluationContext().node ).toString();
665 Value 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 ];
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
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 );
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();
765 return Value( vi.toNumber() );
768 Value 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);
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
815 typedef Function *(*FactoryFn )();
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()
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 );
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
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)