//
// (C) 2002 Piers Haken
//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
using System;
using System.Collections;
+using System.Globalization;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl;
BaseIterator iter = (BaseIterator) arg;
return iter.MoveNext ();
}
+ if (arg is XPathNavigator)
+ {
+ return ToBoolean (((XPathNavigator) arg).SelectChildren (XPathNodeType.All));
+ }
throw new ArgumentException ();
}
if (arg is bool)
return ((bool) arg) ? "true" : "false";
if (arg is double)
- return ((double) arg).ToString ("R", System.Globalization.NumberFormatInfo.InvariantInfo);
+ return ToString ((double) arg);
if (arg is BaseIterator)
{
BaseIterator iter = (BaseIterator) arg;
return "";
return iter.Current.Value;
}
+ if (arg is XPathNavigator)
+ {
+ return ((XPathNavigator) arg).Value;
+ }
throw new ArgumentException ();
}
+ public static string ToString (double d)
+ {
+ // See XPath 1.0 section 4.2
+ if (d == Double.NegativeInfinity)
+ return "-Infinity";
+ if (d == Double.PositiveInfinity)
+ return "Infinity";
+ // FIXME:
+ // Return string in roundtrip format (currently it
+ // rather breaks things, so we don't use it until
+ // System.Double gets fixed.)
+#if TARGET_JVM
+ return d.ToString ("R", System.Globalization.NumberFormatInfo.InvariantInfo);
+#else
+ return ((double) d).ToString (System.Globalization.NumberFormatInfo.InvariantInfo);
+#endif
+ }
+
public static double ToNumber (object arg)
{
if (arg == null)
throw new ArgumentNullException ();
- if (arg is BaseIterator)
+ if (arg is BaseIterator || arg is XPathNavigator)
arg = ToString (arg); // follow on
if (arg is string) {
string s = arg as string;
public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
+ internal override bool Peer {
+ get { return true; }
+ }
+
public override object Evaluate (BaseIterator iter)
{
return (double) iter.Count;
public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
+ internal override bool Peer {
+ get { return true; }
+ }
+
public override object Evaluate (BaseIterator iter)
{
return (double) iter.CurrentPosition;
}
public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
-
+
+ internal override bool Peer {
+ get { return arg0.Peer; }
+ }
+
public override object Evaluate (BaseIterator iter)
{
return (double) arg0.EvaluateNodeSet (iter).Count;
private static char [] rgchWhitespace = {' ', '\t', '\r', '\n'};
public override XPathResultType ReturnType { get { return XPathResultType.NodeSet; }}
+ internal override bool Peer {
+ get { return arg0.Peer; }
+ }
+
public override object Evaluate (BaseIterator iter)
{
String strArgs;
rgNodes.Add (n.Clone ());
rgNodes.Sort (XPathNavigatorComparer.Instance);
- return new ListIterator (iter, rgNodes, true);
+ return new ListIterator (iter, rgNodes);
}
public override string ToString ()
}
public override XPathResultType ReturnType { get { return XPathResultType.String; }}
+
+ internal override bool Peer {
+ get { return arg0 != null ? arg0.Peer : true; }
+ }
public override object Evaluate (BaseIterator iter)
{
throw new XPathException ("namespace-uri takes 1 or zero args");
}
}
+
+ internal override bool Peer {
+ get { return arg0 != null ? arg0.Peer : true; }
+ }
public override XPathResultType ReturnType { get { return XPathResultType.String; }}
}
public override XPathResultType ReturnType { get { return XPathResultType.String; }}
+
+ internal override bool Peer {
+ get { return arg0 != null ? arg0.Peer : true; }
+ }
public override object Evaluate (BaseIterator iter)
{
public override string ToString ()
{
- return "name(" + arg0.ToString () + ")";
+ return String.Concat ("name(",
+ arg0 != null ? arg0.ToString () : String.Empty,
+ ")");
}
}
if (args != null) {
arg0 = args.Arg;
if (args.Tail != null)
- throw new XPathException ("boolean takes 1 or zero args");
+ throw new XPathException ("string takes 1 or zero args");
}
}
public override XPathResultType ReturnType { get { return XPathResultType.String; }}
+ internal override bool Peer {
+ get { return arg0 != null ? arg0.Peer : true; }
+ }
+
public override object Evaluate (BaseIterator iter)
{
if (arg0 == null)
}
public override XPathResultType ReturnType { get { return XPathResultType.String; }}
+
+ internal override bool Peer {
+ get {
+ for (int i = 0; i < rgs.Count; i++)
+ if (!((Expression) rgs [i]).Peer)
+ return false;
+ return true;
+ }
+ }
public override object Evaluate (BaseIterator iter)
{
StringBuilder sb = new StringBuilder ();
sb.Append ("concat(");
for (int i = 0; i < rgs.Count - 1; i++) {
- sb.Append (rgs [i].ToString ());
+ sb.AppendFormat (CultureInfo.InvariantCulture, "{0}", rgs [i].ToString ());
sb.Append (',');
}
- sb.Append (rgs [rgs.Count - 1].ToString ());
+ sb.AppendFormat (CultureInfo.InvariantCulture, "{0}", rgs [rgs.Count - 1].ToString ());
sb.Append (')');
return sb.ToString ();
}
}
public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
+
+ internal override bool Peer {
+ get { return arg0.Peer && arg1.Peer; }
+ }
public override object Evaluate (BaseIterator iter)
{
}
public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
+
+ internal override bool Peer {
+ get { return arg0.Peer && arg1.Peer; }
+ }
public override object Evaluate (BaseIterator iter)
{
}
public override XPathResultType ReturnType { get { return XPathResultType.String; }}
+
+ internal override bool Peer {
+ get { return arg0.Peer && arg1.Peer; }
+ }
public override object Evaluate (BaseIterator iter)
{
}
public override XPathResultType ReturnType { get { return XPathResultType.String; }}
+
+ internal override bool Peer {
+ get { return arg0.Peer && arg1.Peer; }
+ }
public override object Evaluate (BaseIterator iter)
{
}
public override XPathResultType ReturnType { get { return XPathResultType.String; }}
+
+ internal override bool Peer {
+ get { return arg0.Peer && arg1.Peer && (arg2 != null ? arg2.Peer : true); }
+ }
public override object Evaluate (BaseIterator iter)
{
}
public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
+
+ internal override bool Peer {
+ get { return arg0 != null ? arg0.Peer : true; }
+ }
public override object Evaluate (BaseIterator iter)
{
public override XPathResultType ReturnType { get { return XPathResultType.String; }}
+ internal override bool Peer {
+ get { return arg0 !=null ? arg0.Peer : true; }
+ }
+
public override object Evaluate (BaseIterator iter)
{
string str;
}
public override XPathResultType ReturnType { get { return XPathResultType.String; }}
+
+ internal override bool Peer {
+ get { return arg0.Peer && arg1.Peer && arg2.Peer; }
+ }
public override object Evaluate (BaseIterator iter)
{
}
}
+ internal abstract class XPathBooleanFunction : XPathFunction
+ {
+ public XPathBooleanFunction (FunctionArguments args) : base (args)
+ {
+ }
+
+ public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
+
+ public override object StaticValue {
+ get { return StaticValueAsBoolean; }
+ }
+ }
- internal class XPathFunctionBoolean : XPathFunction
+ internal class XPathFunctionBoolean : XPathBooleanFunction
{
Expression arg0;
}
}
- public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
+ internal override bool Peer {
+ get { return arg0 != null ? arg0.Peer : true; }
+ }
public override object Evaluate (BaseIterator iter)
{
}
- internal class XPathFunctionNot : XPathFunction
+ internal class XPathFunctionNot : XPathBooleanFunction
{
Expression arg0;
arg0 = args.Arg;
}
- public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
+ internal override bool Peer {
+ get { return arg0.Peer; }
+ }
public override object Evaluate (BaseIterator iter)
{
}
- internal class XPathFunctionTrue : XPathFunction
+ internal class XPathFunctionTrue : XPathBooleanFunction
{
public XPathFunctionTrue (FunctionArguments args) : base (args)
{
if (args != null)
throw new XPathException ("true takes 0 args");
}
+
+ public override bool HasStaticValue {
+ get { return true; }
+ }
+
+ public override bool StaticValueAsBoolean {
+ get { return true; }
+ }
- public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
+ internal override bool Peer {
+ get { return true; }
+ }
public override object Evaluate (BaseIterator iter)
{
}
- internal class XPathFunctionFalse : XPathFunction
+ internal class XPathFunctionFalse : XPathBooleanFunction
{
public XPathFunctionFalse (FunctionArguments args) : base (args)
{
if (args != null)
throw new XPathException ("false takes 0 args");
}
- public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
+
+ public override bool HasStaticValue {
+ get { return true; }
+ }
+
+ public override bool StaticValueAsBoolean {
+ get { return false; }
+ }
+
+ internal override bool Peer {
+ get { return true; }
+ }
public override object Evaluate (BaseIterator iter)
{
throw new XPathException ("lang takes one arg");
arg0 = args.Arg;
}
-
+
public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
+ internal override bool Peer {
+ get { return arg0.Peer; }
+ }
+
public override object Evaluate (BaseIterator iter)
{
- string lang = arg0.EvaluateString (iter).ToLower ();
- string actualLang = iter.Current.XmlLang.ToLower ();
+ return EvaluateBoolean (iter);
+ }
+
+ public override bool EvaluateBoolean (BaseIterator iter)
+ {
+ string lang = arg0.EvaluateString (iter).ToLower (CultureInfo.InvariantCulture);
+ string actualLang = iter.Current.XmlLang.ToLower (CultureInfo.InvariantCulture);
return lang == actualLang || lang == (actualLang.Split ('-')[0]);
}
}
}
+ internal abstract class XPathNumericFunction : XPathFunction
+ {
+ internal XPathNumericFunction (FunctionArguments args)
+ : base (args)
+ {
+ }
+
+ public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
+
+ public override object StaticValue {
+ get { return StaticValueAsNumber; }
+ }
+ }
- internal class XPathFunctionNumber : XPathFunction
+ internal class XPathFunctionNumber : XPathNumericFunction
{
Expression arg0;
throw new XPathException ("number takes 1 or zero args");
}
}
-
- public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
+
+ public override Expression Optimize ()
+ {
+ if (arg0 == null)
+ return this;
+ arg0 = arg0.Optimize ();
+ return !arg0.HasStaticValue ?
+ (Expression) this :
+ new ExprNumber (StaticValueAsNumber);
+ }
+
+ public override bool HasStaticValue {
+ get { return arg0 != null && arg0.HasStaticValue; }
+ }
+
+ public override double StaticValueAsNumber {
+ get { return arg0 != null ? arg0.StaticValueAsNumber : 0; }
+ }
+
+ internal override bool Peer {
+ get { return arg0 != null ? arg0.Peer : true; }
+ }
public override object Evaluate (BaseIterator iter)
{
}
- internal class XPathFunctionSum : XPathFunction
+ internal class XPathFunctionSum : XPathNumericFunction
{
Expression arg0;
arg0 = args.Arg;
}
- public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
+ internal override bool Peer {
+ get { return arg0.Peer; }
+ }
public override object Evaluate (BaseIterator iter)
{
}
- internal class XPathFunctionFloor : XPathFunction
+ internal class XPathFunctionFloor : XPathNumericFunction
{
Expression arg0;
throw new XPathException ("floor takes one arg");
arg0 = args.Arg;
}
+
+ public override bool HasStaticValue {
+ get { return arg0.HasStaticValue; }
+ }
+
+ public override double StaticValueAsNumber {
+ get { return HasStaticValue ? Math.Floor (arg0.StaticValueAsNumber) : 0; }
+ }
- public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
+ internal override bool Peer {
+ get { return arg0.Peer; }
+ }
public override object Evaluate (BaseIterator iter)
{
}
- internal class XPathFunctionCeil : XPathFunction
+ internal class XPathFunctionCeil : XPathNumericFunction
{
Expression arg0;
throw new XPathException ("ceil takes one arg");
arg0 = args.Arg;
}
+
+ public override bool HasStaticValue {
+ get { return arg0.HasStaticValue; }
+ }
+
+ public override double StaticValueAsNumber {
+ get { return HasStaticValue ? Math.Ceiling (arg0.StaticValueAsNumber) : 0; }
+ }
- public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
+ internal override bool Peer {
+ get { return arg0.Peer; }
+ }
public override object Evaluate (BaseIterator iter)
{
}
- internal class XPathFunctionRound : XPathFunction
+ internal class XPathFunctionRound : XPathNumericFunction
{
Expression arg0;
arg0 = args.Arg;
}
- public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
+ public override bool HasStaticValue {
+ get { return arg0.HasStaticValue; }
+ }
+
+ public override double StaticValueAsNumber {
+ get { return HasStaticValue ? Round (arg0.StaticValueAsNumber) : 0; }
+ }
+
+ internal override bool Peer {
+ get { return arg0.Peer; }
+ }
public override object Evaluate (BaseIterator iter)
{
- double arg = arg0.EvaluateNumber (iter);
+ return Round (arg0.EvaluateNumber (iter));
+ }
+
+ private double Round (double arg)
+ {
if (arg < -0.5 || arg > 0)
return Math.Floor (arg + 0.5);
return Math.Round (arg);