• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KHTML

functions.cpp

Go to the documentation of this file.
00001 /*
00002  * functions.cc - Copyright 2005 Frerich Raabe <raabe@kde.org>
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  *
00014  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00015  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00016  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00017  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00018  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00019  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00020  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00021  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00022  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00023  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00024  */
00025 #include "functions.h"
00026 
00027 #include "xml/dom_docimpl.h"
00028 #include "xml/dom_nodeimpl.h"
00029 #include "xml/dom_nodelistimpl.h"
00030 #include "xml/dom_elementimpl.h"
00031 #include "kjs/operations.h"
00032 
00033 #include <QtDebug>
00034 
00035 #include <math.h>
00036 
00037 using namespace DOM;
00038 
00039 namespace khtml {
00040 namespace XPath {
00041 
00042 #define DEFINE_FUNCTION_CREATOR(Class) \
00043 static Function *create##Class() { return new Class; }
00044 
00045 class Interval
00046 {
00047     public:
00048         static const int Inf =-1;
00049 
00050         Interval();
00051         Interval( int value );
00052         Interval( int min, int max );
00053 
00054         bool contains( int value ) const;
00055 
00056         QString asString() const;
00057 
00058     private:
00059         int m_min;
00060         int m_max;
00061 };
00062 
00063 class FunLast : public Function
00064 {
00065     public:
00066         virtual bool isConstant() const;
00067 
00068     private:
00069         virtual Value doEvaluate() const;
00070 };
00071 
00072 class FunPosition : public Function
00073 {
00074     public:
00075         virtual bool isConstant() const;
00076 
00077     private:
00078         virtual Value doEvaluate() const;
00079 };
00080 
00081 class FunCount : public Function
00082 {
00083     public:
00084         virtual bool isConstant() const;
00085 
00086     private:
00087         virtual Value doEvaluate() const;
00088 };
00089 
00090 // Base for various node-property functions, that have
00091 // the same node picking logic. It passes the proper node,
00092 // if any, or otherwise returns an empty string by itself
00093 class NodeFunction : public Function
00094 {
00095     private:
00096         virtual Value doEvaluate() const;
00097         virtual Value evaluateOnNode( DOM::NodeImpl* node ) const = 0;
00098 };
00099 
00100 class FunLocalName : public NodeFunction
00101 {
00102     public:
00103         virtual bool isConstant() const;
00104 
00105     private:
00106         virtual Value evaluateOnNode( DOM::NodeImpl* node ) const;
00107 };
00108 
00109 class FunNamespaceURI : public NodeFunction
00110 {
00111     public:
00112         virtual bool isConstant() const;
00113 
00114     private:
00115         virtual Value evaluateOnNode( DOM::NodeImpl* node ) const;
00116 };
00117 
00118 class FunName : public NodeFunction
00119 {
00120     public:
00121         virtual bool isConstant() const;
00122 
00123     private:
00124         virtual Value evaluateOnNode( DOM::NodeImpl* node ) const;
00125 };
00126 
00127 class FunId : public Function
00128 {
00129     private:
00130         virtual Value doEvaluate() const;
00131 };
00132 
00133 class FunString : public Function
00134 {
00135     private:
00136         virtual Value doEvaluate() const;
00137 };
00138 
00139 class FunConcat : public Function
00140 {
00141     private:
00142         virtual Value doEvaluate() const;
00143 };
00144 
00145 class FunStartsWith : public Function
00146 {
00147     private:
00148         virtual Value doEvaluate() const;
00149 };
00150 
00151 class FunContains : public Function
00152 {
00153     private:
00154         virtual Value doEvaluate() const;
00155 };
00156 
00157 class FunSubstringBefore : public Function
00158 {
00159     private:
00160         virtual Value doEvaluate() const;
00161 };
00162 
00163 class FunSubstringAfter : public Function
00164 {
00165     private:
00166         virtual Value doEvaluate() const;
00167 };
00168 
00169 class FunSubstring : public Function
00170 {
00171     private:
00172         virtual Value doEvaluate() const;
00173 };
00174 
00175 class FunStringLength : public Function
00176 {
00177     private:
00178         virtual Value doEvaluate() const;
00179 };
00180 
00181 class FunNormalizeSpace : public Function
00182 {
00183     private:
00184         virtual Value doEvaluate() const;
00185 };
00186 
00187 class FunTranslate : public Function
00188 {
00189     private:
00190         virtual Value doEvaluate() const;
00191 };
00192 
00193 class FunBoolean : public Function
00194 {
00195     private:
00196         virtual Value doEvaluate() const;
00197 };
00198 
00199 class FunNot : public Function
00200 {
00201     private:
00202         virtual Value doEvaluate() const;
00203 };
00204 
00205 class FunTrue : public Function
00206 {
00207     public:
00208         virtual bool isConstant() const;
00209 
00210     private:
00211         virtual Value doEvaluate() const;
00212 };
00213 
00214 class FunFalse : public Function
00215 {
00216     public:
00217         virtual bool isConstant() const;
00218 
00219     private:
00220         virtual Value doEvaluate() const;
00221 };
00222 
00223 class FunLang : public Function
00224 {
00225     public:
00226         virtual bool isConstant() const;
00227 
00228     private:
00229         virtual Value doEvaluate() const;
00230 };
00231 
00232 class FunNumber : public Function
00233 {
00234     private:
00235         virtual Value doEvaluate() const;
00236 };
00237 
00238 class FunSum : public Function
00239 {
00240     private:
00241         virtual Value doEvaluate() const;
00242 };
00243 
00244 class FunFloor : public Function
00245 {
00246     private:
00247         virtual Value doEvaluate() const;
00248 };
00249 
00250 class FunCeiling : public Function
00251 {
00252     private:
00253         virtual Value doEvaluate() const;
00254 };
00255 
00256 class FunRound : public Function
00257 {
00258     private:
00259         virtual Value doEvaluate() const;
00260 };
00261 
00262 DEFINE_FUNCTION_CREATOR( FunLast )
00263 DEFINE_FUNCTION_CREATOR( FunPosition )
00264 DEFINE_FUNCTION_CREATOR( FunCount )
00265 DEFINE_FUNCTION_CREATOR( FunLocalName )
00266 DEFINE_FUNCTION_CREATOR( FunNamespaceURI )
00267 DEFINE_FUNCTION_CREATOR( FunName )
00268 DEFINE_FUNCTION_CREATOR( FunId )
00269 
00270 DEFINE_FUNCTION_CREATOR( FunString )
00271 DEFINE_FUNCTION_CREATOR( FunConcat )
00272 DEFINE_FUNCTION_CREATOR( FunStartsWith )
00273 DEFINE_FUNCTION_CREATOR( FunContains )
00274 DEFINE_FUNCTION_CREATOR( FunSubstringBefore )
00275 DEFINE_FUNCTION_CREATOR( FunSubstringAfter )
00276 DEFINE_FUNCTION_CREATOR( FunSubstring )
00277 DEFINE_FUNCTION_CREATOR( FunStringLength )
00278 DEFINE_FUNCTION_CREATOR( FunNormalizeSpace )
00279 DEFINE_FUNCTION_CREATOR( FunTranslate )
00280 
00281 DEFINE_FUNCTION_CREATOR( FunBoolean )
00282 DEFINE_FUNCTION_CREATOR( FunNot )
00283 DEFINE_FUNCTION_CREATOR( FunTrue )
00284 DEFINE_FUNCTION_CREATOR( FunFalse )
00285 DEFINE_FUNCTION_CREATOR( FunLang )
00286 
00287 DEFINE_FUNCTION_CREATOR( FunNumber )
00288 DEFINE_FUNCTION_CREATOR( FunSum )
00289 DEFINE_FUNCTION_CREATOR( FunFloor )
00290 DEFINE_FUNCTION_CREATOR( FunCeiling )
00291 DEFINE_FUNCTION_CREATOR( FunRound )
00292 
00293 #undef DEFINE_FUNCTION_CREATOR
00294 
00295 Interval::Interval()
00296     : m_min( Inf ),
00297     m_max( Inf )
00298 {
00299 }
00300 
00301 Interval::Interval( int value )
00302     : m_min( value ),
00303     m_max( value )
00304 {
00305 }
00306 
00307 Interval::Interval( int min, int max )
00308     : m_min( min ),
00309     m_max( max )
00310 {
00311 }
00312 
00313 bool Interval::contains( int value ) const
00314 {
00315     if ( m_min == Inf && m_max == Inf ) {
00316         return true;
00317     }
00318 
00319     if ( m_min == Inf ) {
00320         return value <= m_max;
00321     }
00322 
00323     if ( m_max == Inf ) {
00324         return value >= m_min;
00325     }
00326 
00327     return value >= m_min && value <= m_max;
00328 }
00329 
00330 QString Interval::asString() const
00331 {
00332     QString s = "[";
00333 
00334     if ( m_min == Inf ) {
00335         s += "-Infinity";
00336     } else {
00337         s += QString::number( m_min );
00338     }
00339 
00340     s += "..";
00341 
00342     if ( m_max == Inf ) {
00343         s += "Infinity";
00344     } else {
00345         s += QString::number( m_max );
00346     }
00347 
00348     s += "]";
00349 
00350     return s;
00351 }
00352 
00353 void Function::setArguments( const QList<Expression *> &args )
00354 {
00355     foreach( Expression *arg, args ) {
00356         addSubExpression( arg );
00357     }
00358 }
00359 
00360 void Function::setName( const DOM::DOMString &name )
00361 {
00362     m_name = name;
00363 }
00364 
00365 QString Function::dump() const
00366 {
00367     if ( argCount() == 0 ) {
00368         return QString( "<function name=\"%1\"/>" ).arg( name().string() );
00369     }
00370 
00371     QString s = QString( "<function name=\"%1\">" ).arg( name().string() );
00372     for ( unsigned int i = 0; i < argCount(); ++i ) {
00373         s += "<operand>" + arg( i )->dump() + "</operand>";
00374     }
00375     s += "</function>";
00376     return s;
00377 }
00378 
00379 
00380 Expression *Function::arg( int i )
00381 {
00382     return subExpr( i );
00383 }
00384 
00385 const Expression *Function::arg( int i ) const
00386 {
00387     return subExpr( i );
00388 }
00389 
00390 unsigned int Function::argCount() const
00391 {
00392     return subExprCount();
00393 }
00394 
00395 DOM::DOMString Function::name() const
00396 {
00397     return m_name;
00398 }
00399 
00400 Value FunLast::doEvaluate() const
00401 {
00402     return Value( double( Expression::evaluationContext().size ) );
00403 }
00404 
00405 bool FunLast::isConstant() const
00406 {
00407     return false;
00408 }
00409 
00410 Value FunPosition::doEvaluate() const
00411 {
00412     return Value( double( Expression::evaluationContext().position ) );
00413 }
00414 
00415 bool FunPosition::isConstant() const
00416 {
00417     return false;
00418 }
00419 
00420 Value NodeFunction::doEvaluate() const
00421 {
00422     NodeImpl *node = 0;
00423     if ( argCount() > 0 ) {
00424         Value a = arg( 0 )->evaluate();
00425         if ( a.isNodeset() && a.toNodeset()->length() ) {
00426             node = a.toNodeset()->first();
00427         }
00428     } else {
00429         // no argument -> default to context node
00430         node = evaluationContext().node;
00431     }
00432 
00433     if ( !node )
00434         return Value( DOMString() );
00435 
00436     return evaluateOnNode( node );
00437 }
00438 
00439 bool FunLocalName::isConstant() const
00440 {
00441     return false;
00442 }
00443 
00444 Value FunLocalName::evaluateOnNode( DOM::NodeImpl* node ) const
00445 {
00446     DOM::DOMString n;
00447     switch ( node->nodeType() ) {
00448     case Node::PROCESSING_INSTRUCTION_NODE:
00449         n = node->nodeName(); // target name
00450         break;
00451     default:
00452         n = node->localName();
00453     }
00454     return Value( n );
00455 }
00456 
00457 bool FunNamespaceURI::isConstant() const
00458 {
00459     return false;
00460 }
00461 
00462 Value FunNamespaceURI::evaluateOnNode( DOM::NodeImpl* node ) const
00463 {
00464     return Value( node->namespaceURI() );
00465 }
00466 
00467 Value FunId::doEvaluate() const
00468 {
00469     Value a = arg( 0 )->evaluate();
00470 
00471     WTF::Vector<DOM::DOMString> ids;
00472 
00473     QString queryString; // whitespace-separated IDs
00474     if ( a.isNodeset() ) {
00475         DomNodeList set = a.toNodeset();
00476         for ( unsigned long i = 0; i < set->length(); ++i)
00477             queryString += stringValue( set->item(i) ).string() + QLatin1Char(' ');
00478     } else {
00479         queryString = a.toString().string();
00480     }
00481     
00482     QStringList qids = queryString.simplified().split(' ');
00483     for ( int i = 0; i < qids.size(); ++i)
00484             ids.append( DOM::DOMString( qids[i] ) );
00485 
00486     DomNodeList out = new StaticNodeListImpl();
00487     DOM::DocumentImpl* doc = Expression::evaluationContext().node->document();
00488 
00489     for ( unsigned i = 0; i < ids.size(); ++i ) {
00490         DOM::ElementImpl* e = doc->getElementById( ids[i] );
00491 
00492         if ( e )
00493             out->append( e );
00494     }
00495 
00496     return Value( out );
00497 }
00498 
00499 bool FunName::isConstant() const
00500 {
00501     return false;
00502 }
00503 
00504 Value FunName::evaluateOnNode( DOM::NodeImpl* node ) const
00505 {
00506     DOM::DOMString n;
00507     switch ( node->nodeType() ) {
00508     case Node::TEXT_NODE:
00509     case Node::CDATA_SECTION_NODE:
00510     case Node::COMMENT_NODE:
00511     case Node::DOCUMENT_NODE:
00512         // All of these have an empty XPath name
00513         break;
00514     case Node::ELEMENT_NODE: {
00515         n = static_cast<DOM::ElementImpl*>( node )->nonCaseFoldedTagName();
00516         break;
00517     }
00518     default:
00519         n = node->nodeName();
00520     }
00521     return Value( n );
00522 }
00523 
00524 Value FunCount::doEvaluate() const
00525 {
00526     Value a = arg( 0 )->evaluate();
00527     if ( !a.isNodeset() ) {
00528         Expression::reportInvalidExpressionErr();
00529         kWarning() << "count() expects <nodeset>";
00530         return Value( );
00531     }
00532     a.toNodeset()->normalizeUpto(StaticNodeListImpl::AxisOrder);
00533 
00534     return Value( double( a.toNodeset()->length() ) );
00535 }
00536 
00537 bool FunCount::isConstant() const
00538 {
00539     return false;
00540 }
00541 
00542 Value FunString::doEvaluate() const
00543 {
00544     if ( argCount() == 0 ) {
00545         DOMString s = Value( Expression::evaluationContext().node ).toString();
00546         return Value( s );
00547     }
00548     return Value( arg( 0 )->evaluate().toString() );
00549 }
00550 
00551 Value FunConcat::doEvaluate() const
00552 {
00553     QString str;
00554     for ( unsigned int i = 0; i < argCount(); ++i ) {
00555         str.append( arg( i )->evaluate().toString().string() );
00556     }
00557     return Value( DOMString( str ) );
00558 }
00559 
00560 Value FunStartsWith::doEvaluate() const
00561 {
00562     DOMString s1 = arg( 0 )->evaluate().toString();
00563     DOMString s2 = arg( 1 )->evaluate().toString();
00564 
00565     if ( s2.isEmpty() ) {
00566         return Value( true );
00567     }
00568 
00569     return Value( s1.startsWith( s2 ) );
00570 }
00571 
00572 Value FunContains::doEvaluate() const
00573 {
00574     QString s1 = arg( 0 )->evaluate().toString().string();
00575     QString s2 = arg( 1 )->evaluate().toString().string();
00576 
00577     if ( s2.isEmpty() ) {
00578         return Value( true );
00579     }
00580 
00581     return Value( s1.contains( s2 ) );
00582 }
00583 
00584 Value FunSubstringBefore::doEvaluate() const
00585 {
00586     QString s1 = arg( 0 )->evaluate().toString().string();
00587     QString s2 = arg( 1 )->evaluate().toString().string();
00588 
00589     if ( s2.isEmpty() ) {
00590         return Value( DOMString() );
00591     }
00592 
00593     int i = s1.indexOf( s2 );
00594     if ( i == -1 ) {
00595         return Value( DOMString() );
00596     }
00597 
00598     return Value( DOMString( s1.left( i ) ) );
00599 }
00600 
00601 Value FunSubstringAfter::doEvaluate() const
00602 {
00603     QString s1 = arg( 0 )->evaluate().toString().string();
00604     QString s2 = arg( 1 )->evaluate().toString().string();
00605 
00606     if ( s2.isEmpty() ) {
00607         return Value( s1 );
00608     }
00609 
00610     int i = s1.indexOf( s2 );
00611     if ( i == -1 ) {
00612         return Value( DOMString() );
00613     }
00614 
00615     return Value( DOMString( s1.mid( i + s2.length() ) ) );
00616 }
00617 
00618 Value FunSubstring::doEvaluate() const
00619 {
00620     QString s = arg( 0 )->evaluate().toString().string();
00621     long pos = long( qRound( arg( 1 )->evaluate().toNumber() ) );
00622     bool haveLength = argCount() == 3;
00623     long len = -1;
00624     if ( haveLength ) {
00625         len = long( qRound( arg( 2 )->evaluate().toNumber() ) );
00626     }
00627 
00628     if ( pos > long( s.length() ) ) {
00629         return Value( DOMString() );
00630     }
00631 
00632     if ( haveLength && pos < 1 ) {
00633         len -= 1 - pos;
00634         pos = 1;
00635         if ( len < 1 ) {
00636             return Value( DOMString() );
00637         }
00638     }
00639 
00640     return Value( DOMString( s.mid( pos - 1, len ) ) );
00641 }
00642 
00643 Value FunStringLength::doEvaluate() const
00644 {
00645     if ( argCount() == 0 ) {
00646         DOMString s = Value( Expression::evaluationContext().node ).toString();
00647         return Value( double( s.length() ) );
00648     }
00649 
00650     return Value( double( arg( 0 )->evaluate().toString().length() ) );
00651 }
00652 
00653 Value FunNormalizeSpace::doEvaluate() const
00654 {
00655     if ( argCount() == 0 ) {
00656         DOMString s = Value( Expression::evaluationContext().node ).toString();
00657         return Value( DOMString( s.string().simplified() ) );
00658     }
00659 
00660     QString s = arg( 0 )->evaluate().toString().string();
00661     s = s.simplified();
00662     return Value( DOMString( s ) );
00663 }
00664 
00665 Value FunTranslate::doEvaluate() const
00666 {
00667     QString s1 = arg( 0 )->evaluate().toString().string();
00668     QString s2 = arg( 1 )->evaluate().toString().string();
00669     QString s3 = arg( 2 )->evaluate().toString().string();
00670     QString newString;
00671 
00672     for ( int i1 = 0; i1 < s1.length(); ++i1 ) {
00673         QChar ch = s1[ i1 ];
00674         int i2 = s2.indexOf( ch );
00675         if ( i2 == -1 ) {
00676             newString += ch;
00677         } else if ( i2 < s3.length() ) {
00678             newString += s3[ i2 ];
00679         }
00680     }
00681 
00682     return Value( DOMString( newString ) );
00683 }
00684 
00685 Value FunBoolean::doEvaluate() const
00686 {
00687     return Value( arg( 0 )->evaluate().toBoolean() );
00688 }
00689 
00690 Value FunNot::doEvaluate() const
00691 {
00692     return Value( !arg( 0 )->evaluate().toBoolean() );
00693 }
00694 
00695 Value FunTrue::doEvaluate() const
00696 {
00697     return Value( true );
00698 }
00699 
00700 bool FunTrue::isConstant() const
00701 {
00702     return true;
00703 }
00704 
00705 #ifdef __GNUC__
00706 #warning "This looks bogus"
00707 #endif
00708 
00709 Value FunLang::doEvaluate() const
00710 {
00711     QString lang = arg( 0 )->evaluate().toString().string();
00712 
00713     NodeImpl* node = evaluationContext().node;
00714 
00715     DOMString langNodeValue;
00716 
00717     while ( node ) {
00718         if (node->isElementNode()) {
00719             langNodeValue = static_cast<ElementImpl*>(node)->getAttribute("xml:lang");
00720             if ( !langNodeValue.isNull() )
00721                 break;
00722         }
00723         node = xpathParentNode( node );     
00724     }
00725 
00726     if ( langNodeValue.isNull() ) {
00727         return Value( false );
00728     }
00729 
00730     // extract 'en' out of 'en-us'
00731     QString langNodeValueString = langNodeValue.string();
00732     QString langNodeBaseString = langNodeValueString.left( langNodeValueString.indexOf( '-' ) );
00733 
00734     return Value( langNodeValueString.toLower() == lang.toLower() ||
00735                   langNodeBaseString.toLower()  == lang.toLower() );
00736 }
00737 
00738 bool FunLang::isConstant() const
00739 {
00740     return false;
00741 }
00742 
00743 Value FunFalse::doEvaluate() const
00744 {
00745     return Value( false );
00746 }
00747 
00748 bool FunFalse::isConstant() const
00749 {
00750     return true;
00751 }
00752 
00753 Value FunNumber::doEvaluate() const
00754 {
00755     Value vi;
00756     if ( argCount() == 0 ) {
00757         // Spec'd: convert context node to singleton nodeset, call
00758         // string on that --> that's just stringValue on that node.
00759         // then we call number on that string
00760         vi = Value(stringValue(evaluationContext().node));
00761     } else {
00762         vi = arg( 0 )->evaluate();
00763     }
00764     
00765     return Value( vi.toNumber() );
00766 }
00767 
00768 Value FunSum::doEvaluate() const
00769 {
00770     Value a = arg( 0 )->evaluate();
00771     if ( !a.isNodeset() ) {
00772         Expression::reportInvalidExpressionErr();
00773         kWarning() << "sum() expects <nodeset>";
00774         return Value( 0.0 );
00775     }
00776 
00777     double sum = 0.0;
00778     const DomNodeList nodes = a.toNodeset();
00779     for (unsigned long n = 0; n < nodes->length(); ++n) {
00780         NodeImpl* node = nodes->item(n);
00781         sum += Value( stringValue( node ) ).toNumber();
00782     }
00783     return Value( sum );
00784 }
00785 
00786 Value FunFloor::doEvaluate() const
00787 {
00788     const double num = arg( 0 )->evaluate().toNumber();
00789 
00790     if ( KJS::isNaN( num ) || KJS::isInf( num ) ) {
00791         return Value( num );
00792     }
00793 
00794     return Value( floor( num ) );
00795 }
00796 
00797 Value FunCeiling::doEvaluate() const
00798 {
00799     const double num = arg( 0 )->evaluate().toNumber();
00800 
00801     if ( KJS::isNaN( num ) || KJS::isInf( num ) ) {
00802         return Value( num );
00803     }
00804 
00805     return Value( ceil( num ) );
00806 }
00807 
00808 Value FunRound::doEvaluate() const
00809 {
00810     return Value( double( qRound( arg( 0 )->evaluate().toNumber() ) ) );
00811 }
00812 
00813 struct FunctionLibrary::FunctionRec
00814 {
00815     typedef Function *(*FactoryFn )();
00816 
00817     FactoryFn factoryFn;
00818     Interval args;
00819 };
00820 
00821 struct FunctionMapping
00822 {
00823     const char *name;
00824     FunctionLibrary::FunctionRec function;
00825 };
00826 
00827 static FunctionMapping functions[] = {
00828     { "last", { &createFunLast, 0 } },
00829     { "last", { &createFunLast, 0 } },
00830     { "position", { &createFunPosition, 0 } },
00831     { "count", { &createFunCount, 1 } },
00832     { "sum", { &createFunSum, 1 } },
00833     { "local-name", { &createFunLocalName, Interval( 0, 1 ) } },
00834     { "namespace-uri", { &createFunNamespaceURI, Interval( 0, 1 ) } },
00835     { "id",   { &createFunId, 1 } },
00836     { "name", { &createFunName, Interval( 0, 1 ) } },
00837     
00838 
00839     { "string", { &createFunString, Interval( 0, 1 ) } },
00840     { "concat", { &createFunConcat, Interval( 2, Interval::Inf ) } },
00841     { "starts-with", { &createFunStartsWith, 2 } },
00842     { "contains", { &createFunContains, 2 } },
00843     { "substring-before", { &createFunSubstringBefore, 2 } },
00844     { "substring-after", { &createFunSubstringAfter, 2 } },
00845     { "substring", { &createFunSubstring, Interval( 2, 3 ) } },
00846     { "string-length", { &createFunStringLength, Interval( 0, 1 ) } },
00847     { "normalize-space", { &createFunNormalizeSpace, Interval( 0, 1 ) } },
00848     { "translate", { &createFunTranslate, 3 } },
00849 
00850     { "boolean", { &createFunBoolean, 1 } },
00851     { "not", { &createFunNot, 1 } },
00852     { "true", { &createFunTrue, 0 } },
00853     { "false", { &createFunFalse, 0 } },
00854     { "lang", { &createFunLang, 1 } },
00855 
00856     { "number", { &createFunNumber, Interval( 0, 1 ) } },
00857     { "floor", { &createFunFloor, 1 } },
00858     { "ceiling", { &createFunCeiling, 1 } },
00859     { "round", { &createFunRound, 1 } }
00860 };
00861 static const unsigned int numFunctions = sizeof( functions ) / sizeof( functions[ 0 ] );
00862 
00863 FunctionLibrary &FunctionLibrary::self()
00864 {
00865     static FunctionLibrary instance;
00866     return instance;
00867 }
00868 
00869 FunctionLibrary::FunctionLibrary()
00870 {
00871     for ( unsigned int i = 0; i < numFunctions; ++i ) {
00872         m_functionDict.insert( functions[ i ].name, functions[ i ].function );
00873     }
00874 }
00875 
00876 Function *FunctionLibrary::getFunction( const DOM::DOMString& name,
00877                                         const QList<Expression *> &args ) const
00878 {
00879     if ( !m_functionDict.contains( name ) ) {
00880         kWarning() << "Function '" << name << "' not supported by this implementation.";
00881 
00882         return 0;
00883     }
00884 
00885     FunctionRec functionRec = m_functionDict[ name ];
00886     if ( !functionRec.args.contains( args.count() ) ) {
00887         kWarning() << "Function '" << name << "' requires " << functionRec.args.asString() << " arguments, but " << args.count() << " given.";
00888         return 0;
00889     }
00890 
00891     Function *function = functionRec.factoryFn();
00892     function->setArguments( args );
00893     function->setName( name );
00894     return function;
00895 }
00896 
00897 } //namespace XPath
00898 } //namespace khtml
00899 
00900 // kate: indent-width 4; replace-tabs off; tab-width 4; space-indent off;

KHTML

Skip menu "KHTML"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal