2003-07-29 Piers Haken <piersh@friskit.com>
[mono.git] / mcs / class / System.XML / System.Xml.XPath / DefaultContext.cs
1 //
2 // System.Xml.XPath.DefaultContext & support classes
3 //
4 // Author:
5 //   Piers Haken (piersh@friskit.com)
6 //
7 // (C) 2002 Piers Haken
8 //
9 using System;
10 using System.Collections;
11 using System.Xml;
12 using System.Xml.XPath;
13 using System.Xml.Xsl;
14 using System.Text;
15
16 namespace System.Xml.XPath
17 {
18         /// <summary>
19         /// Summary description for DefaultContext.
20         /// </summary>
21         internal class DefaultContext : XsltContext
22         {
23                 protected static Hashtable _htFunctions = new Hashtable ();
24
25                 static DefaultContext()
26                 {
27                         Add (new XPathFunctionLast ());
28                         Add (new XPathFunctionPosition ());
29                         Add (new XPathFunctionCount ());
30                         Add (new XPathFunctionId ());
31                         Add (new XPathFunctionLocalName ());
32                         Add (new XPathFunctionNamespaceUri ());
33                         Add (new XPathFunctionName ());
34                         Add (new XPathFunctionString ());
35                         Add (new XPathFunctionConcat ());
36                         Add (new XPathFunctionStartsWith ());
37                         Add (new XPathFunctionContains ());
38                         Add (new XPathFunctionSubstringBefore ());
39                         Add (new XPathFunctionSubstringAfter ());
40                         Add (new XPathFunctionSubstring ());
41                         Add (new XPathFunctionStringLength ());
42                         Add (new XPathFunctionNormalizeSpace ());
43                         Add (new XPathFunctionTranslate ());
44                         Add (new XPathFunctionBoolean ());
45                         Add (new XPathFunctionNot ());
46                         Add (new XPathFunctionTrue ());
47                         Add (new XPathFunctionFalse ());
48                         Add (new XPathFunctionLang ());
49                         Add (new XPathFunctionNumber ());
50                         Add (new XPathFunctionSum ());
51                         Add (new XPathFunctionFloor ());
52                         Add (new XPathFunctionCeil ());
53                         Add (new XPathFunctionRound ());
54                 }
55
56                 [MonoTODO]
57                 public override IXsltContextFunction ResolveFunction (string prefix, string name, XPathResultType[] ArgTypes)
58                 {
59                         // match the prefix
60                         if (prefix != null && prefix != "")     // TODO: should we allow some namespaces here?
61                                 return null;
62
63                         // match the function name
64                         XPathFunction fn = (XPathFunction) _htFunctions [name];
65                         if (fn == null)
66                                 return null;
67
68                         // check the number of arguments
69                         int cArgs = ArgTypes.Length;
70                         if (cArgs < fn.Minargs || cArgs > fn.Maxargs)
71                                 return null;
72
73                         // check the types of the arguments
74                         XPathResultType [] rgTypes = fn.ArgTypes;
75                         if (rgTypes == null)
76                         {
77                                 if (cArgs != 0)
78                                         return null;
79                         }
80                         else
81                         {
82                                 int cTypes = rgTypes.Length;
83                                 XPathResultType [] rgTypesRequested = ArgTypes;
84                                 for (int iArg = 0; iArg < cArgs; iArg ++)
85                                 {
86                                         XPathResultType typeRequested = rgTypesRequested [iArg];
87                                         XPathResultType typeDefined = (iArg >= cTypes) ? rgTypes [cTypes - 1] : rgTypes [iArg];
88
89                                         // if the arguments don't match...
90                                         if (typeDefined != XPathResultType.Any &&
91                                                 typeDefined != typeRequested)
92                                         {
93                                                 // if the function requires a nodeset
94                                                 // then the arg should be .Any
95                                                 // other conversions are illegal
96                                                 if (typeDefined == XPathResultType.NodeSet &&
97                                                         typeRequested != XPathResultType.Any)
98                                                 {
99                                                         return null;
100                                                 }
101                                         }
102                                 }
103                         }
104                         return fn;
105                 }
106                 public override IXsltContextVariable ResolveVariable (string prefix, string name)
107                 {
108                         return null;
109                 }
110                 [MonoTODO]
111                 public override int CompareDocument (string baseUri, string nextBaseUri) { throw new NotImplementedException (); }
112                 [MonoTODO]
113                 public override bool PreserveWhitespace (XPathNavigator nav) { throw new NotImplementedException (); }
114                 [MonoTODO]
115                 public override bool Whitespace { get { throw new NotImplementedException (); }}
116                 protected static void Add (XPathFunction fn)
117                 {
118                         _htFunctions.Add (fn.Name, fn);
119                 }
120         }
121
122
123         internal class XPathFunctions
124         {
125                 public static bool ToBoolean (object arg)
126                 {
127                         if (arg == null)
128                                 throw new ArgumentNullException ();
129                         if (arg is bool)
130                                 return (bool) arg;
131                         if (arg is double)
132                         {
133                                 double dArg = (double) arg;
134                                 return (dArg != 0.0 && !double.IsNaN (dArg));
135                         }
136                         if (arg is string)
137                                 return ((string) arg).Length != 0;
138                         if (arg is BaseIterator)
139                         {
140                                 BaseIterator iter = (BaseIterator) arg;
141                                 return iter.MoveNext ();
142                         }
143                         throw new ArgumentException ();
144                 }
145                 [MonoTODO]
146                 public static string ToString (object arg)
147                 {
148                         if (arg == null)
149                                 throw new ArgumentNullException ();
150                         if (arg is string)
151                                 return (string) arg;
152                         if (arg is bool)
153                                 return ((bool) arg) ? "true" : "false";
154                         if (arg is double)
155                                 return ((double) arg).ToString ("R", System.Globalization.NumberFormatInfo.InvariantInfo);
156                         if (arg is BaseIterator)
157                         {
158                                 BaseIterator iter = (BaseIterator) arg;
159                                 if (!iter.MoveNext ())
160                                         return "";
161                                 return iter.Current.Value;
162                         }
163                         throw new ArgumentException ();
164                 }
165                 [MonoTODO]
166                 public static double ToNumber (object arg)
167                 {
168                         if (arg == null)
169                                 throw new ArgumentNullException ();
170                         if (arg is string)
171                         {
172                                 try
173                                 {
174                                         return XmlConvert.ToDouble ((string) arg);      // TODO: spec? convert string to number
175                                 }
176                                 catch (System.FormatException)
177                                 {
178                                         return double.NaN;
179                                 }
180                         }
181                         if (arg is BaseIterator)
182                                 arg = ToString (arg);   // follow on
183                         if (arg is double)
184                                 return (double) arg;
185                         if (arg is bool)
186                                 return Convert.ToDouble ((bool) arg);
187                         throw new ArgumentException ();
188                 }
189         }
190
191         internal abstract class XPathFunction : IXsltContextFunction
192         {
193                 public abstract XPathResultType ReturnType { get; }
194                 public abstract int Minargs { get; }
195                 public abstract int Maxargs { get; }
196                 public abstract XPathResultType [] ArgTypes { get; }
197                 public object Invoke (XsltContext xsltContext, object[] args, XPathNavigator docContext)
198                 {
199                         return TypesafeInvoke (xsltContext, args, docContext);
200                 }
201
202                 public abstract string Name { get; }
203                 public abstract object TypesafeInvoke (XsltContext xsltContext, object[] args, XPathNavigator docContext);
204         }
205
206
207         internal class XPathFunctionLast : XPathFunction
208         {
209                 public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
210                 public override int Minargs { get { return 0; }}
211                 public override int Maxargs { get { return 0; }}
212                 public override XPathResultType [] ArgTypes { get { return null; }}
213                 public override object TypesafeInvoke (XsltContext xsltContext, object[] args, XPathNavigator docContext)
214                 {
215                         throw new NotImplementedException ();   // special-cased
216                 }
217                 public override string Name { get { return "last"; }}
218         }
219
220
221         internal class XPathFunctionPosition : XPathFunction
222         {
223                 public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
224                 public override int Minargs { get { return 0; }}
225                 public override int Maxargs { get { return 0; }}
226                 public override XPathResultType [] ArgTypes { get { return null; }}
227                 public override object TypesafeInvoke (XsltContext xsltContext, object[] args, XPathNavigator docContext)
228                 {
229                         throw new NotImplementedException ();   // special-cased
230                 }
231                 public override string Name { get { return "position"; }}
232         }
233
234
235         internal class XPathFunctionCount : XPathFunction
236         {
237                 public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
238                 public override int Minargs { get { return 1; }}
239                 public override int Maxargs { get { return 1; }}
240                 public override XPathResultType [] ArgTypes { get { return new XPathResultType [] { XPathResultType.NodeSet }; }}
241                 public override object TypesafeInvoke (XsltContext xsltContext, object[] args, XPathNavigator docContext)
242                 {
243                         return (double) ((BaseIterator) args [0]).Count;
244                 }
245                 public override string Name { get { return "count"; }}
246         }
247
248
249         internal class XPathFunctionId : XPathFunction
250         {
251                 private static char [] rgchWhitespace = {' ', '\t', '\r', '\n'};
252                 public override XPathResultType ReturnType { get { return XPathResultType.NodeSet; }}
253                 public override int Minargs { get { return 1; }}
254                 public override int Maxargs { get { return 1; }}
255                 public override XPathResultType [] ArgTypes { get { return new XPathResultType [] { XPathResultType.Any }; }}
256                 [MonoTODO]
257                 public override object TypesafeInvoke (XsltContext xsltContext, object[] args, XPathNavigator docContext)
258                 {
259                         String strArgs;
260                         BaseIterator iter = args [0] as BaseIterator;
261                         if (iter != null)
262                         {
263                                 strArgs = "";
264                                 while (!iter.MoveNext ())
265                                         strArgs += iter.Current.Value + " ";
266                         }
267                         else
268                                 strArgs = XPathFunctions.ToString (args [0]);
269                         string [] rgstrArgs = strArgs.Split (rgchWhitespace);
270                         ArrayList rgNodes = new ArrayList ();
271                         foreach (string strArg in rgstrArgs)
272                         {
273                                 if (docContext.MoveToId (strArg))
274                                         rgNodes.Add (docContext.Clone ());
275                         }
276                         return new EnumeratorIterator (iter, rgNodes.GetEnumerator ());
277                 }
278                 public override string Name { get { return "id"; }}
279         }
280
281
282         internal class XPathFunctionLocalName : XPathFunction
283         {
284                 public override XPathResultType ReturnType { get { return XPathResultType.NodeSet; }}
285                 public override int Minargs { get { return 0; }}
286                 public override int Maxargs { get { return 1; }}
287                 public override XPathResultType [] ArgTypes { get { return new XPathResultType [] { XPathResultType.NodeSet }; }}
288                 public override object TypesafeInvoke (XsltContext xsltContext, object[] args, XPathNavigator docContext)
289                 {
290                         if (args.Length == 0)
291                                 return docContext.LocalName;
292                         BaseIterator iter = (BaseIterator) args [0];
293                         if (iter == null || !iter.MoveNext ())
294                                 return "";
295                         return iter.Current.LocalName;
296                 }
297                 public override string Name { get { return "local-name"; }}
298         }
299
300
301         internal class XPathFunctionNamespaceUri : XPathFunction
302         {
303                 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
304                 public override int Minargs { get { return 0; }}
305                 public override int Maxargs { get { return 1; }}
306                 public override XPathResultType [] ArgTypes { get { return new XPathResultType [] { XPathResultType.NodeSet }; }}
307                 [MonoTODO]
308                 public override object TypesafeInvoke (XsltContext xsltContext, object[] args, XPathNavigator docContext)
309                 {
310                         if (args.Length == 0)
311                                 return docContext.NamespaceURI;
312                         BaseIterator iter = (BaseIterator) args [0];
313                         if (iter == null || !iter.MoveNext ())
314                                 return "";
315                         return iter.Current.NamespaceURI;       // TODO: should the namespace be expanded wrt. the given context?
316                 }
317                 public override string Name { get { return "namespace-uri"; }}
318         }
319
320
321         internal class XPathFunctionName : XPathFunction
322         {
323                 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
324                 public override int Minargs { get { return 0; }}
325                 public override int Maxargs { get { return 1; }}
326                 public override XPathResultType [] ArgTypes { get { return new XPathResultType [] { XPathResultType.NodeSet }; }}
327                 [MonoTODO]
328                 public override object TypesafeInvoke (XsltContext xsltContext, object[] args, XPathNavigator docContext)
329                 {
330                         if (args.Length == 0)
331                                 return docContext.Name;
332                         BaseIterator iter = (BaseIterator) args [0];
333                         if (iter == null || !iter.MoveNext ())
334                                 return "";
335                         return iter.Current.Name;
336                 }
337                 public override string Name { get { return "name"; }}
338         }
339
340
341         internal class XPathFunctionString : XPathFunction
342         {
343                 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
344                 public override int Minargs { get { return 0; }}
345                 public override int Maxargs { get { return 1; }}
346                 public override XPathResultType [] ArgTypes { get { return new XPathResultType [] { XPathResultType.Any }; }}
347                 public override object TypesafeInvoke (XsltContext xsltContext, object[] args, XPathNavigator docContext)
348                 {
349                         return XPathFunctions.ToString (args [0]);
350                 }
351                 public override string Name { get { return "string"; }}
352         }
353
354
355         internal class XPathFunctionConcat : XPathFunction
356         {
357                 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
358                 public override int Minargs { get { return 2; }}
359                 public override int Maxargs { get { return int.MaxValue; }}
360                 public override XPathResultType [] ArgTypes { get { return new XPathResultType [] { XPathResultType.Any, XPathResultType.Any, XPathResultType.Any }; }}
361                 public override object TypesafeInvoke (XsltContext xsltContext, object[] args, XPathNavigator docContext)
362                 {
363                         StringBuilder sb = new StringBuilder ();
364                         foreach (object arg in args)
365                                 sb.Append (XPathFunctions.ToString (arg));
366                         return sb.ToString ();
367                 }
368                 public override string Name { get { return "concat"; }}
369         }
370
371
372         internal class XPathFunctionStartsWith : XPathFunction
373         {
374                 public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
375                 public override int Minargs { get { return 2; }}
376                 public override int Maxargs { get { return 2; }}
377                 public override XPathResultType [] ArgTypes { get { return new XPathResultType [] { XPathResultType.String, XPathResultType.String }; }}
378                 public override object TypesafeInvoke (XsltContext xsltContext, object[] args, XPathNavigator docContext)
379                 {
380                         string str1 = (string) args [0];
381                         string str2 = (string) args [1];
382                         return str1.StartsWith (str2);
383                 }
384                 public override string Name { get { return "starts-with"; }}
385         }
386
387
388         internal class XPathFunctionContains : XPathFunction
389         {
390                 public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
391                 public override int Minargs { get { return 2; }}
392                 public override int Maxargs { get { return 2; }}
393                 public override XPathResultType [] ArgTypes { get { return new XPathResultType [] { XPathResultType.String, XPathResultType.String }; }}
394                 public override object TypesafeInvoke (XsltContext xsltContext, object[] args, XPathNavigator docContext)
395                 {
396                         string str1 = (string) args [0];
397                         string str2 = (string) args [1];
398                         return str1.IndexOf (str2) != -1;
399                 }
400                 public override string Name { get { return "contains"; }}
401         }
402
403
404         internal class XPathFunctionSubstringBefore : XPathFunction
405         {
406                 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
407                 public override int Minargs { get { return 2; }}
408                 public override int Maxargs { get { return 2; }}
409                 public override XPathResultType [] ArgTypes { get { return new XPathResultType [] { XPathResultType.String, XPathResultType.String }; }}
410                 public override object TypesafeInvoke (XsltContext xsltContext, object[] args, XPathNavigator docContext)
411                 {
412                         string str1 = (string) args [0];
413                         string str2 = (string) args [1];
414                         int ich = str1.IndexOf (str2);
415                         if (ich <= 0)
416                                 return "";
417                         return str1.Substring (0, ich);
418                 }
419                 public override string Name { get { return "substring-before"; }}
420         }
421
422
423         internal class XPathFunctionSubstringAfter : XPathFunction
424         {
425                 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
426                 public override int Minargs { get { return 2; }}
427                 public override int Maxargs { get { return 2; }}
428                 public override XPathResultType [] ArgTypes { get { return new XPathResultType [] { XPathResultType.String, XPathResultType.String }; }}
429                 public override object TypesafeInvoke (XsltContext xsltContext, object[] args, XPathNavigator docContext)
430                 {
431                         string str1 = (string) args [0];
432                         string str2 = (string) args [1];
433                         int ich = str1.IndexOf (str2);
434                         if (ich < 0)
435                                 return "";
436                         return str1.Substring (ich + str2.Length);
437                 }
438                 public override string Name { get { return "substring-after"; }}
439         }
440
441
442         internal class XPathFunctionSubstring : XPathFunction
443         {
444                 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
445                 public override int Minargs { get { return 2; }}
446                 public override int Maxargs { get { return 3; }}
447                 public override XPathResultType [] ArgTypes { get { return new XPathResultType [] { XPathResultType.String, XPathResultType.Number, XPathResultType.Number }; }}
448                 [MonoTODO]
449                 public override object TypesafeInvoke (XsltContext xsltContext, object[] args, XPathNavigator docContext)
450                 {
451                         // TODO: check this, what the hell were they smoking?
452                         string str = (string) args [0];
453                         double ich = Math.Round ((double) args [1]) - 1;
454                         if (Double.IsNaN (ich) || ich >= (double) str.Length)
455                                 return "";
456
457                         if (args.Length == 2)
458                         {
459                                 if (ich < 0)
460                                         ich = 0.0;
461                                 return str.Substring ((int) ich);
462                         }
463                         else
464                         {
465                                 double cch = Math.Round ((double) args [2]);
466                                 if (Double.IsNaN (cch))
467                                         return "";
468                                 if (ich < 0.0 || cch < 0.0) 
469                                 {
470                                         cch = ich + cch;
471                                         if (cch <= 0.0)
472                                                 return "";
473                                         ich = 0.0;
474                                 }
475                                 double cchMax = (double) str.Length - ich;
476                                 if (cch > cchMax)
477                                         cch = cchMax;
478                                 return str.Substring ((int) ich, (int) cch);
479                         }
480                 }
481                 public override string Name { get { return "substring"; }}
482         }
483
484
485         internal class XPathFunctionStringLength : XPathFunction
486         {
487                 public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
488                 public override int Minargs { get { return 0; }}
489                 public override int Maxargs { get { return 1; }}
490                 public override XPathResultType [] ArgTypes { get { return new XPathResultType [] { XPathResultType.String }; }}
491                 public override object TypesafeInvoke (XsltContext xsltContext, object[] args, XPathNavigator docContext)
492                 {
493                         string str;
494                         if (args.Length == 1)
495                                 str = (string) args [0];
496                         else
497                                 str = docContext.Value;
498                         return (double) str.Length;
499                 }
500                 public override string Name { get { return "string-length"; }}
501         }
502
503
504         internal class XPathFunctionNormalizeSpace : XPathFunction
505         {
506                 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
507                 public override int Minargs { get { return 0; }}
508                 public override int Maxargs { get { return 1; }}
509                 public override XPathResultType [] ArgTypes { get { return new XPathResultType [] { XPathResultType.String }; }}
510                 [MonoTODO]
511                 public override object TypesafeInvoke (XsltContext xsltContext, object[] args, XPathNavigator docContext)
512                 {
513                         string str;
514                         if (args.Length == 1)
515                                 str = (string) args [0];
516                         else
517                                 str = docContext.Value;
518                         System.Text.StringBuilder sb = new System.Text.StringBuilder ();
519                         bool fSpace = false;
520                         foreach (char ch in str)
521                         {
522                                 if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n')
523                                 {
524                                         fSpace = true;
525                                 }
526                                 else
527                                 {
528                                         if (fSpace)
529                                         {
530                                                 fSpace = false;
531                                                 if (sb.Length > 0)
532                                                         sb.Append (' ');
533                                         }
534                                         sb.Append (ch);
535                                 }
536                         }
537                         return sb.ToString ();
538                 }
539                 public override string Name { get { return "normalize-space"; }}
540         }
541
542
543         internal class XPathFunctionTranslate : XPathFunction
544         {
545                 public override XPathResultType ReturnType { get { return XPathResultType.String; }}
546                 public override int Minargs { get { return 3; }}
547                 public override int Maxargs { get { return 3; }}
548                 public override XPathResultType [] ArgTypes { get { return new XPathResultType [] { XPathResultType.String, XPathResultType.String, XPathResultType.String }; }}
549                 [MonoTODO]
550                 public override object TypesafeInvoke (XsltContext xsltContext, object[] args, XPathNavigator docContext)
551                 {
552                         throw new NotImplementedException ();
553                 }
554                 public override string Name { get { return "translate"; }}
555         }
556
557
558         internal class XPathFunctionBoolean : XPathFunction
559         {
560                 public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
561                 public override int Minargs { get { return 1; }}
562                 public override int Maxargs { get { return 1; }}
563                 public override XPathResultType [] ArgTypes { get { return new XPathResultType [] { XPathResultType.Any }; }}
564                 public override object TypesafeInvoke (XsltContext xsltContext, object[] args, XPathNavigator docContext)
565                 {
566                         return XPathFunctions.ToBoolean (args [0]);
567                 }
568                 public override string Name { get { return "boolean"; }}
569         }
570
571
572         internal class XPathFunctionNot : XPathFunction
573         {
574                 public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
575                 public override int Minargs { get { return 1; }}
576                 public override int Maxargs { get { return 1; }}
577                 public override XPathResultType [] ArgTypes { get { return new XPathResultType [] { XPathResultType.Any }; }}
578                 public override object TypesafeInvoke (XsltContext xsltContext, object[] args, XPathNavigator docContext)
579                 {
580                         return !(XPathFunctions.ToBoolean (args [0]));
581                 }
582                 public override string Name { get { return "not"; }}
583         }
584
585
586         internal class XPathFunctionTrue : XPathFunction
587         {
588                 public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
589                 public override int Minargs { get { return 0; }}
590                 public override int Maxargs { get { return 0; }}
591                 public override XPathResultType [] ArgTypes { get { return null; }}
592                 public override object TypesafeInvoke (XsltContext xsltContext, object[] args, XPathNavigator docContext)
593                 {
594                         return true;
595                 }
596                 public override string Name { get { return "true"; }}
597         }
598
599
600         internal class XPathFunctionFalse : XPathFunction
601         {
602                 public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
603                 public override int Minargs { get { return 0; }}
604                 public override int Maxargs { get { return 0; }}
605                 public override XPathResultType [] ArgTypes { get { return null; }}
606                 public override object TypesafeInvoke (XsltContext xsltContext, object[] args, XPathNavigator docContext)
607                 {
608                         return false;
609                 }
610                 public override string Name { get { return "false"; }}
611         }
612
613
614         internal class XPathFunctionLang : XPathFunction
615         {
616                 public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
617                 public override int Minargs { get { return 1; }}
618                 public override int Maxargs { get { return 1; }}
619                 public override XPathResultType [] ArgTypes { get { return new XPathResultType [] { XPathResultType.String }; }}
620                 public override object TypesafeInvoke (XsltContext xsltContext, object[] args, XPathNavigator docContext)
621                 {
622                         string lang = ((string)args[0]).ToLower ();
623                         string actualLang = docContext.XmlLang.ToLower ();
624                         
625                         return lang == actualLang || lang == (actualLang.Split ('-')[0]);
626                 }
627                 public override string Name { get { return "lang"; }}
628         }
629
630
631         internal class XPathFunctionNumber : XPathFunction
632         {
633                 public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
634                 public override int Minargs { get { return 0; }}
635                 public override int Maxargs { get { return 1; }}
636                 public override XPathResultType [] ArgTypes { get { return new XPathResultType [] { XPathResultType.Any }; }}
637                 public override object TypesafeInvoke (XsltContext xsltContext, object[] args, XPathNavigator docContext)
638                 {
639                         return XPathFunctions.ToNumber (args [0]);
640                 }
641                 public override string Name { get { return "number"; }}
642         }
643
644
645         internal class XPathFunctionSum : XPathFunction
646         {
647                 public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
648                 public override int Minargs { get { return 1; }}
649                 public override int Maxargs { get { return 1; }}
650                 public override XPathResultType [] ArgTypes { get { return new XPathResultType [] { XPathResultType.NodeSet }; }}
651                 [MonoTODO]
652                 public override object TypesafeInvoke (XsltContext xsltContext, object[] args, XPathNavigator docContext)
653                 {
654                         throw new NotImplementedException ();
655                 }
656                 public override string Name { get { return "sum"; }}
657         }
658
659
660         internal class XPathFunctionFloor : XPathFunction
661         {
662                 public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
663                 public override int Minargs { get { return 1; }}
664                 public override int Maxargs { get { return 1; }}
665                 public override XPathResultType [] ArgTypes { get { return new XPathResultType [] { XPathResultType.Number }; }}
666                 public override object TypesafeInvoke (XsltContext xsltContext, object[] args, XPathNavigator docContext)
667                 {
668                         return Math.Floor ((double) args [0]);
669                 }
670                 public override string Name { get { return "floor"; }}
671         }
672
673
674         internal class XPathFunctionCeil : XPathFunction
675         {
676                 public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
677                 public override int Minargs { get { return 1; }}
678                 public override int Maxargs { get { return 1; }}
679                 public override XPathResultType [] ArgTypes { get { return new XPathResultType [] { XPathResultType.Number }; }}
680                 public override object TypesafeInvoke (XsltContext xsltContext, object[] args, XPathNavigator docContext)
681                 {
682                         return Math.Ceiling ((double) args [0]);
683                 }
684                 public override string Name { get { return "ceil"; }}
685         }
686
687
688         internal class XPathFunctionRound : XPathFunction
689         {
690                 public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
691                 public override int Minargs { get { return 1; }}
692                 public override int Maxargs { get { return 1; }}
693                 public override XPathResultType [] ArgTypes { get { return new XPathResultType [] { XPathResultType.Number }; }}
694                 public override object TypesafeInvoke (XsltContext xsltContext, object[] args, XPathNavigator docContext)
695                 {
696                         double arg = (double) args [0];
697                         if (arg < -0.5 || arg > 0)
698                                 return Math.Floor (arg + 0.5);
699                         return Math.Round (arg);
700                 }
701                 public override string Name { get { return "round"; }}
702         }
703 }