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

KHTML

  • sources
  • kde-4.12
  • kdelibs
  • khtml
  • xpath
functions.cpp
Go to the documentation of this file.
1 /*
2  * functions.cc - Copyright 2005 Frerich Raabe <raabe@kde.org>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 #include "functions.h"
26 
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"
32 
33 #include <QtDebug>
34 
35 #include <math.h>
36 
37 using namespace DOM;
38 
39 namespace khtml {
40 namespace XPath {
41 
42 #define DEFINE_FUNCTION_CREATOR(Class) \
43 static Function *create##Class() { return new Class; }
44 
45 class Interval
46 {
47  public:
48  static const int Inf =-1;
49 
50  Interval();
51  Interval( int value );
52  Interval( int min, int max );
53 
54  bool contains( int value ) const;
55 
56  QString asString() const;
57 
58  private:
59  int m_min;
60  int m_max;
61 };
62 
63 class FunLast : public Function
64 {
65  public:
66  virtual bool isConstant() const;
67 
68  private:
69  virtual Value doEvaluate() const;
70 };
71 
72 class FunPosition : public Function
73 {
74  public:
75  virtual bool isConstant() const;
76 
77  private:
78  virtual Value doEvaluate() const;
79 };
80 
81 class FunCount : public Function
82 {
83  public:
84  virtual bool isConstant() const;
85 
86  private:
87  virtual Value doEvaluate() const;
88 };
89 
90 // Base for various node-property functions, that have
91 // the same node picking logic. It passes the proper node,
92 // if any, or otherwise returns an empty string by itself
93 class NodeFunction : public Function
94 {
95  private:
96  virtual Value doEvaluate() const;
97  virtual Value evaluateOnNode( DOM::NodeImpl* node ) const = 0;
98 };
99 
100 class FunLocalName : public NodeFunction
101 {
102  public:
103  virtual bool isConstant() const;
104 
105  private:
106  virtual Value evaluateOnNode( DOM::NodeImpl* node ) const;
107 };
108 
109 class FunNamespaceURI : public NodeFunction
110 {
111  public:
112  virtual bool isConstant() const;
113 
114  private:
115  virtual Value evaluateOnNode( DOM::NodeImpl* node ) const;
116 };
117 
118 class FunName : public NodeFunction
119 {
120  public:
121  virtual bool isConstant() const;
122 
123  private:
124  virtual Value evaluateOnNode( DOM::NodeImpl* node ) const;
125 };
126 
127 class FunId : public Function
128 {
129  private:
130  virtual Value doEvaluate() const;
131 };
132 
133 class FunString : public Function
134 {
135  private:
136  virtual Value doEvaluate() const;
137 };
138 
139 class FunConcat : public Function
140 {
141  private:
142  virtual Value doEvaluate() const;
143 };
144 
145 class FunStartsWith : public Function
146 {
147  private:
148  virtual Value doEvaluate() const;
149 };
150 
151 class FunContains : public Function
152 {
153  private:
154  virtual Value doEvaluate() const;
155 };
156 
157 class FunSubstringBefore : public Function
158 {
159  private:
160  virtual Value doEvaluate() const;
161 };
162 
163 class FunSubstringAfter : public Function
164 {
165  private:
166  virtual Value doEvaluate() const;
167 };
168 
169 class FunSubstring : public Function
170 {
171  private:
172  virtual Value doEvaluate() const;
173 };
174 
175 class FunStringLength : public Function
176 {
177  private:
178  virtual Value doEvaluate() const;
179 };
180 
181 class FunNormalizeSpace : public Function
182 {
183  private:
184  virtual Value doEvaluate() const;
185 };
186 
187 class FunTranslate : public Function
188 {
189  private:
190  virtual Value doEvaluate() const;
191 };
192 
193 class FunBoolean : public Function
194 {
195  private:
196  virtual Value doEvaluate() const;
197 };
198 
199 class FunNot : public Function
200 {
201  private:
202  virtual Value doEvaluate() const;
203 };
204 
205 class FunTrue : public Function
206 {
207  public:
208  virtual bool isConstant() const;
209 
210  private:
211  virtual Value doEvaluate() const;
212 };
213 
214 class FunFalse : public Function
215 {
216  public:
217  virtual bool isConstant() const;
218 
219  private:
220  virtual Value doEvaluate() const;
221 };
222 
223 class FunLang : public Function
224 {
225  public:
226  virtual bool isConstant() const;
227 
228  private:
229  virtual Value doEvaluate() const;
230 };
231 
232 class FunNumber : public Function
233 {
234  private:
235  virtual Value doEvaluate() const;
236 };
237 
238 class FunSum : public Function
239 {
240  private:
241  virtual Value doEvaluate() const;
242 };
243 
244 class FunFloor : public Function
245 {
246  private:
247  virtual Value doEvaluate() const;
248 };
249 
250 class FunCeiling : public Function
251 {
252  private:
253  virtual Value doEvaluate() const;
254 };
255 
256 class FunRound : public Function
257 {
258  private:
259  virtual Value doEvaluate() const;
260 };
261 
262 DEFINE_FUNCTION_CREATOR( FunLast )
263 DEFINE_FUNCTION_CREATOR( FunPosition )
264 DEFINE_FUNCTION_CREATOR( FunCount )
265 DEFINE_FUNCTION_CREATOR( FunLocalName )
266 DEFINE_FUNCTION_CREATOR( FunNamespaceURI )
267 DEFINE_FUNCTION_CREATOR( FunName )
268 DEFINE_FUNCTION_CREATOR( FunId )
269 
270 DEFINE_FUNCTION_CREATOR( FunString )
271 DEFINE_FUNCTION_CREATOR( FunConcat )
272 DEFINE_FUNCTION_CREATOR( FunStartsWith )
273 DEFINE_FUNCTION_CREATOR( FunContains )
274 DEFINE_FUNCTION_CREATOR( FunSubstringBefore )
275 DEFINE_FUNCTION_CREATOR( FunSubstringAfter )
276 DEFINE_FUNCTION_CREATOR( FunSubstring )
277 DEFINE_FUNCTION_CREATOR( FunStringLength )
278 DEFINE_FUNCTION_CREATOR( FunNormalizeSpace )
279 DEFINE_FUNCTION_CREATOR( FunTranslate )
280 
281 DEFINE_FUNCTION_CREATOR( FunBoolean )
282 DEFINE_FUNCTION_CREATOR( FunNot )
283 DEFINE_FUNCTION_CREATOR( FunTrue )
284 DEFINE_FUNCTION_CREATOR( FunFalse )
285 DEFINE_FUNCTION_CREATOR( FunLang )
286 
287 DEFINE_FUNCTION_CREATOR( FunNumber )
288 DEFINE_FUNCTION_CREATOR( FunSum )
289 DEFINE_FUNCTION_CREATOR( FunFloor )
290 DEFINE_FUNCTION_CREATOR( FunCeiling )
291 DEFINE_FUNCTION_CREATOR( FunRound )
292 
293 #undef DEFINE_FUNCTION_CREATOR
294 
295 Interval::Interval()
296  : m_min( Inf ),
297  m_max( Inf )
298 {
299 }
300 
301 Interval::Interval( int value )
302  : m_min( value ),
303  m_max( value )
304 {
305 }
306 
307 Interval::Interval( int min, int max )
308  : m_min( min ),
309  m_max( max )
310 {
311 }
312 
313 bool Interval::contains( int value ) const
314 {
315  if ( m_min == Inf && m_max == Inf ) {
316  return true;
317  }
318 
319  if ( m_min == Inf ) {
320  return value <= m_max;
321  }
322 
323  if ( m_max == Inf ) {
324  return value >= m_min;
325  }
326 
327  return value >= m_min && value <= m_max;
328 }
329 
330 QString Interval::asString() const
331 {
332  QString s = "[";
333 
334  if ( m_min == Inf ) {
335  s += "-Infinity";
336  } else {
337  s += QString::number( m_min );
338  }
339 
340  s += "..";
341 
342  if ( m_max == Inf ) {
343  s += "Infinity";
344  } else {
345  s += QString::number( m_max );
346  }
347 
348  s += "]";
349 
350  return s;
351 }
352 
353 void Function::setArguments( const QList<Expression *> &args )
354 {
355  foreach( Expression *arg, args ) {
356  addSubExpression( arg );
357  }
358 }
359 
360 void Function::setName( const DOM::DOMString &name )
361 {
362  m_name = name;
363 }
364 
365 QString Function::dump() const
366 {
367  if ( argCount() == 0 ) {
368  return QString( "<function name=\"%1\"/>" ).arg( name().string() );
369  }
370 
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>";
374  }
375  s += "</function>";
376  return s;
377 }
378 
379 
380 Expression *Function::arg( int i )
381 {
382  return subExpr( i );
383 }
384 
385 const Expression *Function::arg( int i ) const
386 {
387  return subExpr( i );
388 }
389 
390 unsigned int Function::argCount() const
391 {
392  return subExprCount();
393 }
394 
395 DOM::DOMString Function::name() const
396 {
397  return m_name;
398 }
399 
400 Value FunLast::doEvaluate() const
401 {
402  return Value( double( Expression::evaluationContext().size ) );
403 }
404 
405 bool FunLast::isConstant() const
406 {
407  return false;
408 }
409 
410 Value FunPosition::doEvaluate() const
411 {
412  return Value( double( Expression::evaluationContext().position ) );
413 }
414 
415 bool FunPosition::isConstant() const
416 {
417  return false;
418 }
419 
420 Value NodeFunction::doEvaluate() const
421 {
422  NodeImpl *node = 0;
423  if ( argCount() > 0 ) {
424  Value a = arg( 0 )->evaluate();
425  if ( a.isNodeset() && a.toNodeset()->length() ) {
426  node = a.toNodeset()->first();
427  }
428  } else {
429  // no argument -> default to context node
430  node = evaluationContext().node;
431  }
432 
433  if ( !node )
434  return Value( DOMString() );
435 
436  return evaluateOnNode( node );
437 }
438 
439 bool FunLocalName::isConstant() const
440 {
441  return false;
442 }
443 
444 Value FunLocalName::evaluateOnNode( DOM::NodeImpl* node ) const
445 {
446  DOM::DOMString n;
447  switch ( node->nodeType() ) {
448  case Node::PROCESSING_INSTRUCTION_NODE:
449  n = node->nodeName(); // target name
450  break;
451  default:
452  n = node->localName();
453  }
454  return Value( n );
455 }
456 
457 bool FunNamespaceURI::isConstant() const
458 {
459  return false;
460 }
461 
462 Value FunNamespaceURI::evaluateOnNode( DOM::NodeImpl* node ) const
463 {
464  return Value( node->namespaceURI() );
465 }
466 
467 Value FunId::doEvaluate() const
468 {
469  Value a = arg( 0 )->evaluate();
470 
471  WTF::Vector<DOM::DOMString> ids;
472 
473  QString queryString; // whitespace-separated IDs
474  if ( a.isNodeset() ) {
475  DomNodeList set = a.toNodeset();
476  for ( unsigned long i = 0; i < set->length(); ++i)
477  queryString += stringValue( set->item(i) ).string() + QLatin1Char(' ');
478  } else {
479  queryString = a.toString().string();
480  }
481 
482  QStringList qids = queryString.simplified().split(' ');
483  for ( int i = 0; i < qids.size(); ++i)
484  ids.append( DOM::DOMString( qids[i] ) );
485 
486  DomNodeList out = new StaticNodeListImpl();
487  DOM::DocumentImpl* doc = Expression::evaluationContext().node->document();
488 
489  for ( unsigned i = 0; i < ids.size(); ++i ) {
490  DOM::ElementImpl* e = doc->getElementById( ids[i] );
491 
492  if ( e )
493  out->append( e );
494  }
495 
496  return Value( out );
497 }
498 
499 bool FunName::isConstant() const
500 {
501  return false;
502 }
503 
504 Value FunName::evaluateOnNode( DOM::NodeImpl* node ) const
505 {
506  DOM::DOMString n;
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:
512  // All of these have an empty XPath name
513  break;
514  case Node::ELEMENT_NODE: {
515  n = static_cast<DOM::ElementImpl*>( node )->nonCaseFoldedTagName();
516  break;
517  }
518  default:
519  n = node->nodeName();
520  }
521  return Value( n );
522 }
523 
524 Value FunCount::doEvaluate() const
525 {
526  Value a = arg( 0 )->evaluate();
527  if ( !a.isNodeset() ) {
528  Expression::reportInvalidExpressionErr();
529  kWarning() << "count() expects <nodeset>";
530  return Value( );
531  }
532  a.toNodeset()->normalizeUpto(StaticNodeListImpl::AxisOrder);
533 
534  return Value( double( a.toNodeset()->length() ) );
535 }
536 
537 bool FunCount::isConstant() const
538 {
539  return false;
540 }
541 
542 Value FunString::doEvaluate() const
543 {
544  if ( argCount() == 0 ) {
545  DOMString s = Value( Expression::evaluationContext().node ).toString();
546  return Value( s );
547  }
548  return Value( arg( 0 )->evaluate().toString() );
549 }
550 
551 Value FunConcat::doEvaluate() const
552 {
553  QString str;
554  for ( unsigned int i = 0; i < argCount(); ++i ) {
555  str.append( arg( i )->evaluate().toString().string() );
556  }
557  return Value( DOMString( str ) );
558 }
559 
560 Value FunStartsWith::doEvaluate() const
561 {
562  DOMString s1 = arg( 0 )->evaluate().toString();
563  DOMString s2 = arg( 1 )->evaluate().toString();
564 
565  if ( s2.isEmpty() ) {
566  return Value( true );
567  }
568 
569  return Value( s1.startsWith( s2 ) );
570 }
571 
572 Value FunContains::doEvaluate() const
573 {
574  QString s1 = arg( 0 )->evaluate().toString().string();
575  QString s2 = arg( 1 )->evaluate().toString().string();
576 
577  if ( s2.isEmpty() ) {
578  return Value( true );
579  }
580 
581  return Value( s1.contains( s2 ) );
582 }
583 
584 Value FunSubstringBefore::doEvaluate() const
585 {
586  QString s1 = arg( 0 )->evaluate().toString().string();
587  QString s2 = arg( 1 )->evaluate().toString().string();
588 
589  if ( s2.isEmpty() ) {
590  return Value( DOMString() );
591  }
592 
593  int i = s1.indexOf( s2 );
594  if ( i == -1 ) {
595  return Value( DOMString() );
596  }
597 
598  return Value( DOMString( s1.left( i ) ) );
599 }
600 
601 Value FunSubstringAfter::doEvaluate() const
602 {
603  QString s1 = arg( 0 )->evaluate().toString().string();
604  QString s2 = arg( 1 )->evaluate().toString().string();
605 
606  if ( s2.isEmpty() ) {
607  return Value( s1 );
608  }
609 
610  int i = s1.indexOf( s2 );
611  if ( i == -1 ) {
612  return Value( DOMString() );
613  }
614 
615  return Value( DOMString( s1.mid( i + s2.length() ) ) );
616 }
617 
618 Value FunSubstring::doEvaluate() const
619 {
620  QString s = arg( 0 )->evaluate().toString().string();
621  long pos = long( qRound( arg( 1 )->evaluate().toNumber() ) );
622  bool haveLength = argCount() == 3;
623  long len = -1;
624  if ( haveLength ) {
625  len = long( qRound( arg( 2 )->evaluate().toNumber() ) );
626  }
627 
628  if ( pos > long( s.length() ) ) {
629  return Value( DOMString() );
630  }
631 
632  if ( haveLength && pos < 1 ) {
633  len -= 1 - pos;
634  pos = 1;
635  if ( len < 1 ) {
636  return Value( DOMString() );
637  }
638  }
639 
640  return Value( DOMString( s.mid( pos - 1, len ) ) );
641 }
642 
643 Value FunStringLength::doEvaluate() const
644 {
645  if ( argCount() == 0 ) {
646  DOMString s = Value( Expression::evaluationContext().node ).toString();
647  return Value( double( s.length() ) );
648  }
649 
650  return Value( double( arg( 0 )->evaluate().toString().length() ) );
651 }
652 
653 Value FunNormalizeSpace::doEvaluate() const
654 {
655  if ( argCount() == 0 ) {
656  DOMString s = Value( Expression::evaluationContext().node ).toString();
657  return Value( DOMString( s.string().simplified() ) );
658  }
659 
660  QString s = arg( 0 )->evaluate().toString().string();
661  s = s.simplified();
662  return Value( DOMString( s ) );
663 }
664 
665 Value FunTranslate::doEvaluate() const
666 {
667  QString s1 = arg( 0 )->evaluate().toString().string();
668  QString s2 = arg( 1 )->evaluate().toString().string();
669  QString s3 = arg( 2 )->evaluate().toString().string();
670  QString newString;
671 
672  for ( int i1 = 0; i1 < s1.length(); ++i1 ) {
673  QChar ch = s1[ i1 ];
674  int i2 = s2.indexOf( ch );
675  if ( i2 == -1 ) {
676  newString += ch;
677  } else if ( i2 < s3.length() ) {
678  newString += s3[ i2 ];
679  }
680  }
681 
682  return Value( DOMString( newString ) );
683 }
684 
685 Value FunBoolean::doEvaluate() const
686 {
687  return Value( arg( 0 )->evaluate().toBoolean() );
688 }
689 
690 Value FunNot::doEvaluate() const
691 {
692  return Value( !arg( 0 )->evaluate().toBoolean() );
693 }
694 
695 Value FunTrue::doEvaluate() const
696 {
697  return Value( true );
698 }
699 
700 bool FunTrue::isConstant() const
701 {
702  return true;
703 }
704 
705 #ifdef __GNUC__
706 #warning "This looks bogus"
707 #endif
708 
709 Value FunLang::doEvaluate() const
710 {
711  QString lang = arg( 0 )->evaluate().toString().string();
712 
713  NodeImpl* node = evaluationContext().node;
714 
715  DOMString langNodeValue;
716 
717  while ( node ) {
718  if (node->isElementNode()) {
719  langNodeValue = static_cast<ElementImpl*>(node)->getAttribute("xml:lang");
720  if ( !langNodeValue.isNull() )
721  break;
722  }
723  node = xpathParentNode( node );
724  }
725 
726  if ( langNodeValue.isNull() ) {
727  return Value( false );
728  }
729 
730  // extract 'en' out of 'en-us'
731  QString langNodeValueString = langNodeValue.string();
732  QString langNodeBaseString = langNodeValueString.left( langNodeValueString.indexOf( '-' ) );
733 
734  return Value( langNodeValueString.toLower() == lang.toLower() ||
735  langNodeBaseString.toLower() == lang.toLower() );
736 }
737 
738 bool FunLang::isConstant() const
739 {
740  return false;
741 }
742 
743 Value FunFalse::doEvaluate() const
744 {
745  return Value( false );
746 }
747 
748 bool FunFalse::isConstant() const
749 {
750  return true;
751 }
752 
753 Value FunNumber::doEvaluate() const
754 {
755  Value vi;
756  if ( argCount() == 0 ) {
757  // Spec'd: convert context node to singleton nodeset, call
758  // string on that --> that's just stringValue on that node.
759  // then we call number on that string
760  vi = Value(stringValue(evaluationContext().node));
761  } else {
762  vi = arg( 0 )->evaluate();
763  }
764 
765  return Value( vi.toNumber() );
766 }
767 
768 Value FunSum::doEvaluate() const
769 {
770  Value a = arg( 0 )->evaluate();
771  if ( !a.isNodeset() ) {
772  Expression::reportInvalidExpressionErr();
773  kWarning() << "sum() expects <nodeset>";
774  return Value( 0.0 );
775  }
776 
777  double sum = 0.0;
778  const DomNodeList nodes = a.toNodeset();
779  for (unsigned long n = 0; n < nodes->length(); ++n) {
780  NodeImpl* node = nodes->item(n);
781  sum += Value( stringValue( node ) ).toNumber();
782  }
783  return Value( sum );
784 }
785 
786 Value FunFloor::doEvaluate() const
787 {
788  const double num = arg( 0 )->evaluate().toNumber();
789 
790  if ( KJS::isNaN( num ) || KJS::isInf( num ) ) {
791  return Value( num );
792  }
793 
794  return Value( floor( num ) );
795 }
796 
797 Value FunCeiling::doEvaluate() const
798 {
799  const double num = arg( 0 )->evaluate().toNumber();
800 
801  if ( KJS::isNaN( num ) || KJS::isInf( num ) ) {
802  return Value( num );
803  }
804 
805  return Value( ceil( num ) );
806 }
807 
808 Value FunRound::doEvaluate() const
809 {
810  return Value( double( qRound( arg( 0 )->evaluate().toNumber() ) ) );
811 }
812 
813 struct FunctionLibrary::FunctionRec
814 {
815  typedef Function *(*FactoryFn )();
816 
817  FactoryFn factoryFn;
818  Interval args;
819 };
820 
821 struct FunctionMapping
822 {
823  const char *name;
824  FunctionLibrary::FunctionRec function;
825 };
826 
827 static FunctionMapping functions[] = {
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 ) } },
837 
838 
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 } },
849 
850  { "boolean", { &createFunBoolean, 1 } },
851  { "not", { &createFunNot, 1 } },
852  { "true", { &createFunTrue, 0 } },
853  { "false", { &createFunFalse, 0 } },
854  { "lang", { &createFunLang, 1 } },
855 
856  { "number", { &createFunNumber, Interval( 0, 1 ) } },
857  { "floor", { &createFunFloor, 1 } },
858  { "ceiling", { &createFunCeiling, 1 } },
859  { "round", { &createFunRound, 1 } }
860 };
861 static const unsigned int numFunctions = sizeof( functions ) / sizeof( functions[ 0 ] );
862 
863 FunctionLibrary &FunctionLibrary::self()
864 {
865  static FunctionLibrary instance;
866  return instance;
867 }
868 
869 FunctionLibrary::FunctionLibrary()
870 {
871  for ( unsigned int i = 0; i < numFunctions; ++i ) {
872  m_functionDict.insert( functions[ i ].name, functions[ i ].function );
873  }
874 }
875 
876 Function *FunctionLibrary::getFunction( const DOM::DOMString& name,
877  const QList<Expression *> &args ) const
878 {
879  if ( !m_functionDict.contains( name ) ) {
880  kWarning() << "Function '" << name << "' not supported by this implementation.";
881 
882  return 0;
883  }
884 
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.";
888  return 0;
889  }
890 
891  Function *function = functionRec.factoryFn();
892  function->setArguments( args );
893  function->setName( name );
894  return function;
895 }
896 
897 } //namespace XPath
898 } //namespace khtml
899 
900 // kate: indent-width 4; replace-tabs off; tab-width 4; space-indent off;
khtml::XPath::Function
Definition: functions.h:39
DOM::DOMString::length
uint length() const
Definition: dom_string.cpp:185
khtml::XPath::FunctionLibrary
Definition: functions.h:57
name
const char * name(StandardAction id)
khtml::XPath::numFunctions
static const unsigned int numFunctions
Definition: functions.cpp:861
DOM::DOMString::string
QString string() const
Definition: dom_string.cpp:236
QString
khtml::XPath::DomNodeList
SharedPtr< DOM::StaticNodeListImpl > DomNodeList
Definition: util.h:41
khtml::XPath::functions
static FunctionMapping functions[]
Definition: functions.cpp:827
DOM::DOMString::isEmpty
bool isEmpty() const
Definition: dom_string.cpp:315
khtml::XPath::Value
Definition: expression.h:75
DOM::DOMString::isNull
bool isNull() const
Definition: dom_string.h:121
QStringList
khtml::XPath::stringValue
DOMString stringValue(NodeImpl *node)
Definition: util.cpp:68
DOM::DOMString
This class implements the basic string we use in the DOM.
Definition: dom_string.h:43
DOM::DOMString::startsWith
bool startsWith(const DOMString &str) const
Definition: dom_string.cpp:287
khtml::XPath::Function::setArguments
void setArguments(const QList< Expression * > &args)
Definition: functions.cpp:353
self
static KJavaAppletServer * self
Definition: kjavaappletserver.cpp:133
functions.h
khtml::XPath::xpathParentNode
DOM::NodeImpl * xpathParentNode(DOM::NodeImpl *node)
Definition: util.cpp:112
kWarning
static QDebug kWarning(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
khtml::XPath::Expression
Definition: expression.h:114
DEFINE_FUNCTION_CREATOR
#define DEFINE_FUNCTION_CREATOR(Class)
Definition: functions.cpp:42
QList
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:51:20 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KHTML

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

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal