File: FrameworkFork\Microsoft.Xml\Xml\XPath\Internal\NumberFunctions.cs
Web Access
Project: src\src\dotnet-svcutil\lib\src\dotnet-svcutil-lib.csproj (dotnet-svcutil-lib)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
namespace MS.Internal.Xml.XPath
{
    using System;
    using Microsoft.Xml;
    using Microsoft.Xml.XPath;
    using System.Diagnostics;
    using System.Globalization;
    using Microsoft.Xml.Xsl;
    using System.Text;
    using FT = MS.Internal.Xml.XPath.Function.FunctionType;
 
    internal sealed class NumberFunctions : ValueQuery
    {
        private Query _arg = null;
        private FT _ftype;
 
        public NumberFunctions(FT ftype, Query arg)
        {
            _arg = arg;
            _ftype = ftype;
        }
        private NumberFunctions(NumberFunctions other) : base(other)
        {
            _arg = Clone(other._arg);
            _ftype = other._ftype;
        }
 
        public override void SetXsltContext(XsltContext context)
        {
            if (_arg != null)
            {
                _arg.SetXsltContext(context);
            }
        }
 
        internal static double Number(bool arg)
        {
            return arg ? 1.0 : 0.0;
        }
        internal static double Number(string arg)
        {
            return XmlConvert.ToXPathDouble(arg);
        }
 
        public override object Evaluate(XPathNodeIterator nodeIterator)
        {
            switch (_ftype)
            {
                case FT.FuncNumber: return Number(nodeIterator);
                case FT.FuncSum: return Sum(nodeIterator);
                case FT.FuncFloor: return Floor(nodeIterator);
                case FT.FuncCeiling: return Ceiling(nodeIterator);
                case FT.FuncRound: return Round(nodeIterator);
            }
            return null;
        }
 
        private double Number(XPathNodeIterator nodeIterator)
        {
            if (_arg == null)
            {
                return XmlConvert.ToXPathDouble(nodeIterator.Current.Value);
            }
            object argVal = _arg.Evaluate(nodeIterator);
            switch (GetXPathType(argVal))
            {
                case XPathResultType.NodeSet:
                    XPathNavigator value = _arg.Advance();
                    if (value != null)
                    {
                        return Number(value.Value);
                    }
                    break;
                case XPathResultType.String:
                    return Number((string)argVal);
                case XPathResultType.Boolean:
                    return Number((bool)argVal);
                case XPathResultType.Number:
                    return (double)argVal;
                case XPathResultType_Navigator:
                    return Number(((XPathNavigator)argVal).Value);
            }
            return double.NaN;
        }
 
        private double Sum(XPathNodeIterator nodeIterator)
        {
            double sum = 0;
            _arg.Evaluate(nodeIterator);
            XPathNavigator nav;
            while ((nav = _arg.Advance()) != null)
            {
                sum += Number(nav.Value);
            }
            return sum;
        }
 
        private double Floor(XPathNodeIterator nodeIterator)
        {
            return Math.Floor((double)_arg.Evaluate(nodeIterator));
        }
 
        private double Ceiling(XPathNodeIterator nodeIterator)
        {
            return Math.Ceiling((double)_arg.Evaluate(nodeIterator));
        }
 
        private double Round(XPathNodeIterator nodeIterator)
        {
            double n = XmlConvert.ToXPathDouble(_arg.Evaluate(nodeIterator));
            return XmlConvert.XPathRound(n);
        }
 
        public override XPathResultType StaticType { get { return XPathResultType.Number; } }
 
        public override XPathNodeIterator Clone() { return new NumberFunctions(this); }
 
        public override void PrintQuery(XmlWriter w)
        {
            w.WriteStartElement(this.GetType().Name);
            w.WriteAttributeString("name", _ftype.ToString());
            if (_arg != null)
            {
                _arg.PrintQuery(w);
            }
            w.WriteEndElement();
        }
    }
}