QueryNode.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Dispatcher / QueryNode.cs / 1 / QueryNode.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------
namespace System.ServiceModel.Dispatcher
{ 
    using System;
    using System.Collections; 
    using System.Collections.Generic; 
    using System.Diagnostics;
    using System.Xml; 
    using System.Xml.XPath;
    using System.Threading;

    ///  
    /// A navigator is a cursor over the nodes in a DOM, where each node is assigned a unique position.
    /// A node is a (navigator, position) pair. 
    ///  
    internal struct QueryNode
    { 
        SeekableXPathNavigator node;
        long nodePosition;

        ///  
        /// Create a query node from the given navigator and its current position
        ///  
        ///  
        internal QueryNode(SeekableXPathNavigator node)
        { 
            this.node = node;
            this.nodePosition = node.CurrentPosition;
        }
 
        /// 
        /// Initialize using the given (node, position) pair 
        ///  
#if NO
        internal QueryNode(SeekableXPathNavigator node, long nodePosition) 
        {
            this.node = node;
            this.nodePosition = nodePosition;
        } 
#endif
        internal string LocalName 
        { 
            get
            { 
                return this.node.GetLocalName(this.nodePosition);
            }
        }
 
        /// 
        /// Return the node's name 
        ///  
        internal string Name
        { 
            get
            {
                return this.node.GetName(this.nodePosition);
            } 
        }
        ///  
        /// Return the node's namespace 
        /// 
        internal string Namespace 
        {
            get
            {
                return this.node.GetNamespace(this.nodePosition); 
            }
        } 
        ///  
        /// Return this query node's underlying Node
        ///  
        internal SeekableXPathNavigator Node
        {
            get
            { 
                return this.node;
            } 
        } 
        /// 
        /// 
        /// 
        internal long Position
        {
            get 
            {
 
                return this.nodePosition; 
            }
        } 
        /// 
        /// This node's type
        /// 
#if NO 
        internal QueryNodeType Type
        { 
            get 
            {
                return QueryDataModel.GetNodeType(this.node.GetNodeType(this.nodePosition)); 
            }
        }
#endif
        ///  
        /// This node's string value
        ///  
        internal string Value 
        {
            get 
            {
                return this.node.GetValue(this.nodePosition);
            }
        } 
        /// 
        /// Raw xpath node type 
        ///  
#if NO
        internal XPathNodeType XPathNodeType 
        {
            get
            {
                return this.node.GetNodeType(this.nodePosition); 
            }
        } 
#endif 
        /// 
        /// Move this node's navigator to its position 
        /// 
        /// 
        internal SeekableXPathNavigator MoveTo()
        { 
            this.node.CurrentPosition = this.nodePosition;
            return this.node; 
        } 
    }
 
    internal enum NodeSequenceItemFlags : byte
    {
        None = 0x00,
        NodesetLast = 0x01, 
    }
 
    // PERF, [....], Remove when generic sort works 
    // Used to sort in document order
#if NO 
    internal class NodeSequenceItemObjectComparer : IComparer
    {
        internal NodeSequenceItemObjectComparer()
        { 
        }
 
        public int Compare(object obj1, object obj2) 
        {
            NodeSequenceItem item1 = (NodeSequenceItem)obj1; 
            NodeSequenceItem item2 = (NodeSequenceItem)obj2;

            XmlNodeOrder order = item1.Node.Node.ComparePosition(item1.Node.Position, item2.Node.Position);
            int ret; 
            switch(order)
            { 
                case XmlNodeOrder.Before: 
                    ret = -1;
                    break; 

                case XmlNodeOrder.Same:
                    ret = 0;
                    break; 

                case XmlNodeOrder.After: 
                    ret = 1; 
                    break;
 
                case XmlNodeOrder.Unknown:
                default:
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XPathException(SR.GetString(SR.QueryNotSortable)), TraceEventType.Critical);
            } 

            return ret; 
        } 
    }
 
    // Used to sort in document order
    internal class NodeSequenceItemComparer : IComparer
    {
        internal NodeSequenceItemComparer() 
        {
        } 
 
        public int Compare(NodeSequenceItem item1, NodeSequenceItem item2)
        { 
            XmlNodeOrder order = item1.Node.Node.ComparePosition(item1.Node.Position, item2.Node.Position);
            int ret;
            switch(order)
            { 
                case XmlNodeOrder.Before:
                    ret = -1; 
                    break; 

                case XmlNodeOrder.Same: 
                    ret = 0;
                    break;

                case XmlNodeOrder.After: 
                    ret = 1;
                    break; 
 
                case XmlNodeOrder.Unknown:
                default: 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XPathException(SR.GetString(SR.QueryNotSortable)), TraceEventType.Critical);
            }

            return ret; 
        }
 
        public bool Equals(NodeSequenceItem item1, NodeSequenceItem item2) 
        {
            return Compare(item1, item2) == 0; 
        }

        public int GetHashCode(NodeSequenceItem item)
        { 
            return item.GetHashCode();
        } 
    } 
#endif
    // Used to sort in document order 
    internal class QueryNodeComparer : IComparer
    {
        public QueryNodeComparer()
        { 
        }
 
        public int Compare(QueryNode item1, QueryNode item2) 
        {
            XmlNodeOrder order = item1.Node.ComparePosition(item1.Position, item2.Position); 
            int ret;
            switch(order)
            {
                case XmlNodeOrder.Before: 
                    ret = -1;
                    break; 
 
                case XmlNodeOrder.Same:
                    ret = 0; 
                    break;

                case XmlNodeOrder.After:
                    ret = 1; 
                    break;
 
                case XmlNodeOrder.Unknown: 
                default:
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new XPathException(SR.GetString(SR.QueryNotSortable))); 
            }

            return ret;
        } 

        public bool Equals(QueryNode item1, QueryNode item2) 
        { 
            return Compare(item1, item2) == 0;
        } 

        public int GetHashCode(QueryNode item)
        {
            return item.GetHashCode(); 
        }
    } 
 
    internal struct NodeSequenceItem
    { 
        NodeSequenceItemFlags flags;
        QueryNode node;
        int position;
        int size; 

        internal NodeSequenceItemFlags Flags 
        { 
            get
            { 
                return this.flags;
            }
            set
            { 
                this.flags = value;
            } 
        } 

        internal bool Last 
        {
            get
            {
                return (0 != (NodeSequenceItemFlags.NodesetLast & this.flags)); 
            }
            set 
            { 
                if (value)
                { 
                    this.flags |= NodeSequenceItemFlags.NodesetLast;
                }
                else
                { 
                    this.flags &= ~(NodeSequenceItemFlags.NodesetLast);
                } 
            } 
        }
 
        internal string LocalName
        {
            get
            { 
                return this.node.LocalName;
            } 
        } 

        internal string Name 
        {
            get
            {
                return this.node.Name; 
            }
        } 
 
        internal string Namespace
        { 
            get
            {
                return this.node.Namespace;
            } 
        }
 
        internal QueryNode Node 
        {
            get 
            {
                return this.node;
            }
#if NO 
            set
            { 
                this.node = value; 
            }
#endif 
        }

        internal int Position
        { 
            get
            { 
                return this.position; 
            }
#if NO 
            set
            {
                this.position = value;
            } 
#endif
        } 
 
        internal int Size
        { 
            get
            {
                return this.size;
            } 
            set
            { 
                this.size = value; 
            }
        } 

        internal bool Compare(double dblVal, RelationOperator op)
        {
            return QueryValueModel.Compare(this.NumberValue(), dblVal, op); 
        }
 
        internal bool Compare(string strVal, RelationOperator op) 
        {
            return QueryValueModel.Compare(this.StringValue(), strVal, op); 
        }

        internal bool Compare(ref NodeSequenceItem item, RelationOperator op)
        { 
            return QueryValueModel.Compare(this.StringValue(), item.StringValue(), op);
        } 
 
        internal bool Equals(string literal)
        { 
            return QueryValueModel.Equals(this.StringValue(), literal);
        }

        internal bool Equals(double literal) 
        {
            return (this.NumberValue() == literal); 
        } 

        internal SeekableXPathNavigator GetNavigator() 
        {
            return this.node.MoveTo();
        }
 
        internal long GetNavigatorPosition()
        { 
            return this.node.Position; 
        }
 
        internal double NumberValue()
        {
            return QueryValueModel.Double(this.StringValue());
        } 

        internal void Set(SeekableXPathNavigator node, int position, int size) 
        { 
            DiagnosticUtility.DebugAssert(position > 0, "");
            DiagnosticUtility.DebugAssert(null != node, ""); 

            this.node = new QueryNode(node);
            this.position = position;
            this.size = size; 
            this.flags = NodeSequenceItemFlags.None;
        } 
 
        internal void Set(QueryNode node, int position, int size)
        { 
            DiagnosticUtility.DebugAssert(position > 0, "");

            this.node = node;
            this.position = position; 
            this.size = size;
            this.flags = NodeSequenceItemFlags.None; 
        } 

        internal void Set(ref NodeSequenceItem item, int position, int size) 
        {
            DiagnosticUtility.DebugAssert(position > 0, "");

            this.node = item.node; 
            this.position = position;
            this.size = size; 
            this.flags = item.flags; 
        }
 
        internal void SetPositionAndSize(int position, int size)
        {
            this.position = position;
            this.size = size; 
            this.flags &= ~NodeSequenceItemFlags.NodesetLast;
        } 
 
        internal void SetSizeAndLast()
        { 
            this.size = 1;
            this.flags |= NodeSequenceItemFlags.NodesetLast;
        }
 
        // This is not optimized right now
        // We may want to CACHE string values once they are computed 
        internal string StringValue() 
        {
            return this.node.Value; 
        }
    }

    internal class NodeSequence 
    {
#if DEBUG 
        // debugging aid. Because C# references do not have displayble numeric values, hard to deduce the 
        // graph structure to see what opcode is connected to what
        static long nextUniqueId = 0; 
        internal long uniqueID;
#endif
        int count;
        internal static NodeSequence Empty = new NodeSequence(0); 
        NodeSequenceItem[] items;
        NodeSequence next; 
        ProcessingContext ownerContext; 
        int position;
        internal int refCount; 
        int sizePosition;

        internal NodeSequence()
            : this(8, null) 
        {
        } 
 
        internal NodeSequence(int capacity)
            : this(capacity, null) 
        {
        }

        internal NodeSequence(int capacity, ProcessingContext ownerContext) 
        {
            this.items = new NodeSequenceItem[capacity]; 
            this.ownerContext = ownerContext; 
#if DEBUG
            this.uniqueID = Interlocked.Increment(ref NodeSequence.nextUniqueId); 
#endif
        }

#if NO 
        internal NodeSequence(int capacity, ProcessingContext ownerContext, XPathNodeIterator iter)
            : this(capacity, ownerContext) 
        { 
            while(iter.MoveNext())
            { 
                SeekableXPathNavigator nav = iter.Current as SeekableXPathNavigator;
                if(nav != null)
                {
                    Add(nav); 
                }
                else 
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QueryProcessingException(QueryProcessingError.Unexpected, SR.GetString(SR.QueryMustBeSeekable)), TraceEventType.Critical);
                } 
            }
        }
#endif
        internal int Count 
        {
            get 
            { 
                return this.count;
            } 
#if NO
            set
            {
                DiagnosticUtility.DebugAssert(value >= 0 && value <= this.count, ""); 
                this.count = value;
            } 
#endif 
        }
 
        internal NodeSequenceItem this[int index]
        {
            get
            { 
                return this.items[index];
            } 
        } 

        internal NodeSequenceItem[] Items 
        {
            get
            {
                return this.items; 
            }
        } 
 
        internal bool IsNotEmpty
        { 
            get
            {
                return (this.count > 0);
            } 
        }
 
        internal string LocalName 
        {
            get 
            {
                if (this.count > 0)
                {
                    return this.items[0].LocalName; 
                }
 
                return string.Empty; 
            }
        } 

        internal string Name
        {
            get 
            {
                if (this.count > 0) 
                { 
                    return this.items[0].Name;
                } 

                return string.Empty;
            }
        } 

        internal string Namespace 
        { 
            get
            { 
                if (this.count > 0)
                {
                    return this.items[0].Namespace;
                } 

                return string.Empty; 
            } 
        }
 
        internal NodeSequence Next
        {
            get
            { 
                return this.next;
            } 
            set 
            {
                this.next = value; 
            }
        }

        internal ProcessingContext OwnerContext 
        {
            get 
            { 
                return this.ownerContext;
            } 
            set
            {
                this.ownerContext = value;
            } 
        }
#if NO 
        internal int NodesetStartAt 
        {
            get 
            {
                return -this.sizePosition;
            }
        } 
#endif
        internal void Add(XPathNodeIterator iter) 
        { 
            while(iter.MoveNext())
            { 
                SeekableXPathNavigator nav = iter.Current as SeekableXPathNavigator;
                if(nav != null)
                {
                    this.Add(nav); 
                }
                else 
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new QueryProcessingException(QueryProcessingError.Unexpected, SR.GetString(SR.QueryMustBeSeekable)));
                } 
            }
        }

        internal void Add(SeekableXPathNavigator node) 
        {
            DiagnosticUtility.DebugAssert(this.items.Length > 0, ""); 
            if (this.count == this.items.Length) 
            {
                this.Grow(this.items.Length * 2); 
            }
            this.position++;
            this.items[this.count++].Set(node, this.position, this.sizePosition);
        } 

        internal void Add(QueryNode node) 
        { 
            DiagnosticUtility.DebugAssert(this.items.Length > 0, "");
            if (this.count == this.items.Length) 
            {
                this.Grow(this.items.Length * 2);
            }
 
            this.position++;
            this.items[this.count++].Set(node, this.position, this.sizePosition); 
        } 

        internal void Add(ref NodeSequenceItem item) 
        {
            DiagnosticUtility.DebugAssert(this.items.Length > 0, "");
            if (this.count == this.items.Length)
            { 
                this.Grow(this.items.Length * 2);
            } 
 
            this.position++;
            this.items[this.count++].Set(ref item, this.position, this.sizePosition); 
        }

        internal void AddCopy(ref NodeSequenceItem item, int size)
        { 
            DiagnosticUtility.DebugAssert(this.items.Length > 0, "");
            if (this.count == this.items.Length) 
            { 
                this.Grow(this.items.Length * 2);
            } 

            this.items[this.count] = item;
            this.items[this.count++].Size = size;
        } 

        internal void AddCopy(ref NodeSequenceItem item) 
        { 
            DiagnosticUtility.DebugAssert(this.items.Length > 0, "");
            if (this.count == this.items.Length) 
            {
                this.Grow(this.items.Length * 2);
            }
 
            this.items[this.count++] = item;
        } 
#if NO 
        internal void Add(NodeSequence seq)
        { 
            int newCount = this.count + seq.count;
            if (newCount > this.items.Length)
            {
                // We are going to need room. Grow the array 
                int growTo = this.items.Length * 2;
                this.Grow(newCount > growTo ? newCount : growTo); 
            } 
            Array.Copy(seq.items, 0, this.items, this.count, seq.count);
            this.count += seq.count; 
        }
#endif
        internal bool CanReuse(ProcessingContext context)
        { 
            return (this.count == 1 && this.ownerContext == context && this.refCount == 1);
        } 
 
        internal void Clear()
        { 
            this.count = 0;
        }

        internal void Reset(NodeSequence nextSeq) 
        {
            this.count = 0; 
            this.refCount = 0; 
            this.next = nextSeq;
        } 

        internal bool Compare(double val, RelationOperator op)
        {
            for (int i = 0; i < this.count; ++i) 
            {
                if (this.items[i].Compare(val, op)) 
                { 
                    return true;
                } 
            }
            return false;
        }
 
        internal bool Compare(string val, RelationOperator op)
        { 
            DiagnosticUtility.DebugAssert(null != val, ""); 
            for (int i = 0; i < this.count; ++i)
            { 
                if (this.items[i].Compare(val, op))
                {
                    return true;
                } 
            }
            return false; 
        } 

        internal bool Compare(ref NodeSequenceItem item, RelationOperator op) 
        {
            for (int i = 0; i < this.count; ++i)
            {
                if (this.items[i].Compare(ref item, op)) 
                {
                    return true; 
                } 
            }
            return false; 
        }

        internal bool Compare(NodeSequence sequence, RelationOperator op)
        { 
            DiagnosticUtility.DebugAssert(null != sequence, "");
            for (int i = 0; i < sequence.count; ++i) 
            { 
                if (this.Compare(ref sequence.items[i], op))
                { 
                    return true;
                }
            }
            return false; 
        }
#if NO 
        void EnsureCapacity() 
        {
            if (this.count == this.items.Length) 
            {
                this.Grow(this.items.Length * 2);
            }
        } 

        void EnsureCapacity(int capacity) 
        { 
            if (capacity > this.items.Length)
            { 
                int newSize = this.items.Length * 2;
                this.Grow(newSize > capacity ? newSize : capacity);
            }
        } 
#endif
        internal bool Equals(string val) 
        { 
            DiagnosticUtility.DebugAssert(null != val, "");
            for (int i = 0; i < this.count; ++i) 
            {
                if (this.items[i].Equals(val))
                {
                    return true; 
                }
            } 
            return false; 
        }
 
        internal bool Equals(double val)
        {
            for (int i = 0; i < this.count; ++i)
            { 
                if (this.items[i].Equals(val))
                { 
                    return true; 
                }
            } 
            return false;
        }

        internal static int GetContextSize(NodeSequence sequence, int itemIndex) 
        {
            DiagnosticUtility.DebugAssert(null != sequence, ""); 
            int size = sequence.items[itemIndex].Size; 
            if (size <= 0)
            { 
                return sequence.items[-size].Size;
            }
            return size;
        } 

        void Grow(int newSize) 
        { 
            NodeSequenceItem[] newItems = new NodeSequenceItem[newSize];
            if(this.items != null) 
            {
                Array.Copy(this.items, newItems, this.items.Length);
            }
            this.items = newItems; 
        }
 
        ///  
        /// Merge all nodesets in this sequence... turning it into a sequence with a single nodeset
        /// This is done by simply renumbering all positions.. and clearing the nodeset flag 
        /// 
        internal void Merge()
        {
            Merge(true); 
        }
 
        internal void Merge(bool renumber) 
        {
            if (this.count == 0) 
            {
                return;
            }
 
            if(renumber)
            { 
                RenumberItems(); 
            }
        } 
#if NO
        // Assumes list is flat and sorted
        internal void RemoveDuplicates()
        { 
            if(this.count < 2)
            { 
                return; 
            }
 
            int last = 0;
            for(int next = 1; next < this.count; ++next)
            {
                if(Comparer.Compare(this.items[last], this.items[next]) != 0) 
                {
                    ++last; 
                    if(last != next) 
                    {
                        this.items[last] = this.items[next]; 
                    }
                }
            }
 
            this.count = last + 1;
 
            RenumberItems(); 
        }
#endif 
        void RenumberItems()
        {
            if (this.count > 0)
            { 
                for (int i = 0; i < this.count; ++i)
                { 
                    this.items[i].SetPositionAndSize(i + 1, this.count); 
                }
                this.items[this.count - 1].Flags |= NodeSequenceItemFlags.NodesetLast; 
            }
        }
#if NO
        internal void SortNodes() 
        {
            this.Merge(false); 
 
            // PERF, [....], make this work
            //Array.Sort(this.items, 0, this.count, NodeSequence.Comparer); 
            Array.Sort(this.items, 0, this.count, NodeSequence.ObjectComparer);

            RenumberItems();
        } 
#endif
        internal void StartNodeset() 
        { 
            this.position = 0;
            this.sizePosition = -this.count; 
        }

        internal void StopNodeset()
        { 
            switch(this.position)
            { 
                default: 
                    int sizePos = -this.sizePosition;
                    this.items[sizePos].Size = this.position; 
                    this.items[sizePos + this.position -1].Last = true;
                    break;

                case 0: 
                    break;
 
                case 1: 
                    this.items[-this.sizePosition].SetSizeAndLast();
                    break; 
            }
        }

        internal string StringValue() 
        {
            if (this.count > 0) 
            { 
                return this.items[0].StringValue();
            } 

            return string.Empty;
        }
 
        /// 
        /// Union algorithm: 
        /// 1. Add both sequences of items to a newly created sequence 
        /// 2. Sort the items based on document position
        /// 3. Renumber positions in this new unionized sequence 
        /// 
        internal NodeSequence Union(ProcessingContext context, NodeSequence otherSeq)
        {
            NodeSequence seq = context.CreateSequence(); 

            SortedBuffer buff = new SortedBuffer(); 
            for(int i = 0; i < this.count; ++i) 
                buff.Add(this.items[i].Node);
 
            for(int i = 0; i < otherSeq.count; ++i)
                buff.Add(otherSeq.items[i].Node);

            for(int i = 0; i < buff.Count; ++i) 
                seq.Add(buff[i]);
 
            seq.RenumberItems(); 
            return seq;
 
            /*
            // PERF, [....], I think we can do the merge ourselves and avoid the sort.
            //               Need to verify that the sequences are always in document order.
            for(int i = 0; i < this.count; ++i) 
            {
                seq.AddCopy(ref this.items[i]); 
            } 

            for(int i = 0; i < otherSeq.count; ++i) 
            {
                seq.AddCopy(ref otherSeq.items[i]);
            }
 
            seq.SortNodes();
            seq.RemoveDuplicates(); 
 
            return seq;
            */ 
        }

        #region IQueryBufferPool Members
#if NO 
        public void Reset()
        { 
            this.count = 0; 
            this.Trim();
        } 

        public void Trim()
        {
            if (this.count == 0) 
            {
                this.items = null; 
            } 
            else if (this.count < this.items.Length)
            { 
                NodeSequenceItem[] newItems = new NodeSequenceItem[this.count];
                Array.Copy(this.items, newItems, this.count);
                this.items = newItems;
            } 
        }
#endif 
        #endregion 
    }
 
    internal class NodeSequenceIterator : XPathNodeIterator
    {
        // Shared
        NodeSequence seq; 

        // Instance 
        NodeSequenceIterator data; 
        int index;
        SeekableXPathNavigator nav; // the navigator that will be used by this iterator 

        internal NodeSequenceIterator(NodeSequence seq)
            : base()
        { 
            this.data = this;
            this.seq = seq; 
        } 

        internal NodeSequenceIterator(NodeSequenceIterator iter) 
        {
            this.data = iter.data;
            this.index = iter.index;
        } 

        public override int Count 
        { 
            get
            { 
                return this.data.seq.Count;
            }
        }
 
        public override XPathNavigator Current
        { 
            get 
            {
                if(this.index == 0) 
                {
#pragma warning suppress 56503 // [....], postponing the public change
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QueryProcessingException(QueryProcessingError.Unexpected, SR.GetString(SR.QueryContextNotSupportedInSequences)));
                } 

                if(this.index > this.data.seq.Count) 
                { 
#pragma warning suppress 56503 // [....], postponing the public change
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.QueryAfterNodes))); 
                }
                //
                // From MSDN - the public contract of .Current
                // You can use the properties of the XPathNavigator to return information on the current node. 
                // However, the XPathNavigator cannot be used to move away from the selected node set.
                // Doing so could invalidate the state of the navigator. Alternatively, you can clone the XPathNavigator. 
                // The cloned XPathNavigator can then be moved away from the selected node set. This is an application level decision. 
                // Providing this functionality may effect the performance of the XPath query.
                // 
                // Return the navigator as is - where it is positioned. If the user moved the navigator, then the user is
                // hosed. We will make no guarantees - and are not required to. Doing so would force cloning, which is expensive.
                //
                // NOTE: .Current can get called repeatedly, so its activity should be relative CHEAP. 
                // No cloning, copying etc. All that work should be done in MoveNext()
                return this.nav; 
            } 
        }
 
        public override int CurrentPosition
        {
            get
            { 
                return this.index;
            } 
        } 

        internal void Clear() 
        {
            this.data.seq = null;
            this.nav = null;
        } 

        public override XPathNodeIterator Clone() 
        { 
            return new NodeSequenceIterator(this);
        } 

        public override IEnumerator GetEnumerator()
        {
            return new NodeSequenceEnumerator(this); 
        }
 
        public override bool MoveNext() 
        {
            if (null == this.data.seq) 
            {
                // User is trying to use an iterator that is  out of scope.
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.QueryIteratorOutOfScope)));
            } 

            if(this.index < this.data.seq.Count) 
            { 
                if (null == this.nav)
                { 
                    // We haven't aquired the navigator we will use for this iterator yet.
                    this.nav = (SeekableXPathNavigator)this.data.seq[this.index].GetNavigator().Clone();
                }
                else 
                {
                    this.nav.CurrentPosition = this.data.seq[this.index].GetNavigatorPosition(); 
                } 
                this.index++;
                return true; 
            }

            this.index++;
            this.nav = null; 
            return false;
        } 
 
        public void Reset()
        { 
            this.nav = null;
            this.index = 0;
        }
    } 

    internal class NodeSequenceEnumerator : IEnumerator 
    { 
        NodeSequenceIterator iter;
 
        internal NodeSequenceEnumerator(NodeSequenceIterator iter)
        {
            this.iter = new NodeSequenceIterator(iter);
            Reset(); 
        }
 
        public object Current 
        {
            get 
            {
                if(this.iter.CurrentPosition == 0)
                {
#pragma warning suppress 56503 // [....], postponing the public change 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.QueryBeforeNodes)));
                } 
 
                if(this.iter.CurrentPosition > this.iter.Count)
                { 
#pragma warning suppress 56503 // [....], postponing the public change
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.QueryAfterNodes)));
                }
 
                return this.iter.Current;
            } 
        } 

        public bool MoveNext() 
        {
            return iter.MoveNext();
        }
 
        public void Reset()
        { 
            this.iter.Reset(); 
        }
    } 

    internal struct NodesetIterator
    {
        int index; 
        int indexStart;
        NodeSequence sequence; 
        NodeSequenceItem[] items; 

        internal NodesetIterator(NodeSequence sequence) 
        {
            DiagnosticUtility.DebugAssert(null != sequence, "");
            this.sequence = sequence;
            this.items = sequence.Items; 
            this.index = -1;
            this.indexStart = -1; 
        } 

        internal int Index 
        {
            get
            {
                return this.index; 
            }
        } 
 
        internal bool NextItem()
        { 
            if (-1 == this.index)
            {
                this.index = this.indexStart;
                return true; 
            }
 
            if (this.items[this.index].Last) 
            {
                return false; 
            }

            this.index++;
            return true; 
        }
 
        internal bool NextNodeset() 
        {
            this.indexStart = this.index + 1; 
            this.index = -1;
            return (this.indexStart < this.sequence.Count);
        }
    } 

    internal struct NodeSequenceBuilder 
    { 
        ProcessingContext context;
        NodeSequence sequence; 

        internal NodeSequenceBuilder(ProcessingContext context, NodeSequence sequence)
        {
            this.context = context; 
            this.sequence = sequence;
        } 
 
        internal NodeSequenceBuilder(ProcessingContext context)
            : this(context, null) 
        {
        }
#if NO
        internal NodeSequenceBuilder(NodeSequence sequence) 
            : this(sequence.OwnerContext, sequence)
        { 
        } 
#endif
        internal NodeSequence Sequence 
        {
            get
            {
                return (null != this.sequence) ? this.sequence : NodeSequence.Empty; 
            }
            set 
            { 
                this.sequence = value;
            } 
        }

        internal void Add(ref NodeSequenceItem item)
        { 
            if (null == this.sequence)
            { 
                this.sequence = this.context.CreateSequence(); 
                this.sequence.StartNodeset();
            } 

            this.sequence.Add(ref item);
        }
 
        internal void EndNodeset()
        { 
            if (null != this.sequence) 
            {
                this.sequence.StopNodeset(); 
            }
        }

        internal void StartNodeset() 
        {
            if (null != this.sequence) 
            { 
                this.sequence.StartNodeset();
            } 
        }
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK