hack SettingValueElement.Unmerge().
[mono.git] / mcs / class / System.XML / System.Xml.XPath / Iterator.cs
index 9695aaadb8ef2905031ccd75b27595c490060b68..26eebc50b724b13fe012abdf7d6de2b6ffc929d3 100644 (file)
@@ -35,12 +35,7 @@ using System.Collections;
 using System.Xml;
 using System.Xml.XPath;
 using System.Xml.Xsl;
-
-#if NET_2_0
 using NSResolver = System.Xml.IXmlNamespaceResolver;
-#else
-using NSResolver = System.Xml.XmlNamespaceManager;
-#endif
 
 namespace System.Xml.XPath
 {
@@ -101,6 +96,12 @@ namespace System.Xml.XPath
 
                public abstract bool MoveNextCore ();
 
+               internal XPathNavigator PeekNext ()
+               {
+                       XPathNodeIterator i = Clone ();
+                       return i.MoveNext () ? i.Current : null;
+               }
+
                public override string ToString ()
                {
                        if (Current != null)
@@ -184,9 +185,7 @@ namespace System.Xml.XPath
                        get {
                                if (CurrentPosition == 0)
                                        return null;
-                               if (_current == null)
-                                       _current = _nav.Clone ();
-                               _current.MoveTo (_nav);
+                               _current = _nav;
                                return _current;
                        }
                }
@@ -230,6 +229,10 @@ namespace System.Xml.XPath
                public override int CurrentPosition {
                        get { return 1; }
                }
+
+               public override XPathNavigator Current {
+                       get { return _nav; }
+               }
        }
 
        internal class ParensIterator : BaseIterator
@@ -279,25 +282,38 @@ namespace System.Xml.XPath
                }
        }
 
-       internal class ChildIterator : SimpleIterator
+       internal class ChildIterator : BaseIterator
        {
-               public ChildIterator (BaseIterator iter) : base (iter) {}
-               private ChildIterator (ChildIterator other) : base (other, true) {}
+               XPathNavigator _nav;
+
+               public ChildIterator (BaseIterator iter) : base (iter.NamespaceManager) 
+               {
+                       _nav = iter.CurrentPosition == 0 ? iter.PeekNext () : iter.Current;
+                       if (_nav != null && _nav.HasChildren)
+                               _nav = _nav.Clone ();
+                       else
+                               _nav = null;
+               }
+               private ChildIterator (ChildIterator other) : base (other)
+               {
+                       _nav = other._nav == null ? null : other._nav.Clone ();
+               }
+
                public override XPathNodeIterator Clone () { return new ChildIterator (this); }
+
                public override bool MoveNextCore ()
                {
-                       bool fSuccess = (CurrentPosition == 0) ? _nav.MoveToFirstChild () : _nav.MoveToNext ();
-//                     if (fSuccess) {
-//                             Current.MoveTo (_nav);
-//                     }
-                       return fSuccess;
+                       if (_nav == null)
+                               return false;
+
+                       return (CurrentPosition == 0) ? _nav.MoveToFirstChild () : _nav.MoveToNext ();
                }
 
                public override XPathNavigator Current {
                        get {
-                               if (CurrentPosition > 0)
-                                       base.Current.MoveTo (_nav);
-                               return base.Current;
+                               if (CurrentPosition == 0)
+                                       return null;
+                               return _nav;
                        }
                }
        }
@@ -470,26 +486,15 @@ namespace System.Xml.XPath
                        navigators = new ArrayList ();
 
                        XPathNavigator ancestors = startPosition.Clone ();
-                       if (!ancestors.MoveToParent ())
-                               return;
-                       while (ancestors.NodeType != XPathNodeType.Root) {
+                       while (ancestors.NodeType != XPathNodeType.Root && ancestors.MoveToParent ())
                                navigators.Add (ancestors.Clone ());
-                               ancestors.MoveToParent ();
-                       }
                        currentPosition = navigators.Count;
                }
 
                public override bool MoveNextCore ()
                {
-                       if (navigators == null) {
+                       if (navigators == null)
                                CollectResults ();
-                               if (startPosition.NodeType != XPathNodeType.Root) {
-                                       // First time it returns Root
-                                       _nav.MoveToRoot ();
-//                                     Current.MoveTo (_nav);
-                                       return true;
-                               }
-                       }
                        if (currentPosition == -1)
                                return false;
                        if (currentPosition-- == 0) {
@@ -522,7 +527,7 @@ namespace System.Xml.XPath
 
                public DescendantIterator (BaseIterator iter) : base (iter) {}
 
-               private DescendantIterator (DescendantIterator other) : base (other)
+               private DescendantIterator (DescendantIterator other) : base (other, true)
                {
                        _depth = other._depth;
                        _finished = other._finished;
@@ -767,13 +772,13 @@ namespace System.Xml.XPath
 
        internal class AxisIterator : BaseIterator
        {
-               private SimpleIterator _iter;
+               private BaseIterator _iter;
                private NodeTest _test;
                        
                //string name, ns;
                //XPathNodeType matchType;
 
-               public AxisIterator (SimpleIterator iter, NodeTest test) : base (iter.NamespaceManager)
+               public AxisIterator (BaseIterator iter, NodeTest test) : base (iter.NamespaceManager)
                {
                        _iter = iter;
                        _test = test;
@@ -787,7 +792,7 @@ namespace System.Xml.XPath
 
                private AxisIterator (AxisIterator other) : base (other)
                {
-                       _iter = (SimpleIterator) other._iter.Clone ();
+                       _iter = (BaseIterator) other._iter.Clone ();
                        _test = other._test;
                        //name = other.name;
                        //ns = other.ns;
@@ -857,23 +862,68 @@ namespace System.Xml.XPath
                }
        }
 
+       internal class SortedIterator : BaseIterator
+       {
+               ArrayList list;
+
+               public SortedIterator (BaseIterator iter) : base (iter.NamespaceManager)
+               {
+                       list = new ArrayList ();
+                       while (iter.MoveNext ())
+                               list.Add (iter.Current.Clone ());
+
+                       // sort
+                       if (list.Count == 0)
+                               return;
+                       XPathNavigator prev = (XPathNavigator) list [0];
+                       list.Sort (XPathNavigatorComparer.Instance);
+                       for (int i = 1; i < list.Count; i++) {
+                               XPathNavigator n = (XPathNavigator) list [i];
+                               if (prev.IsSamePosition (n)) {
+                                       list.RemoveAt (i);
+                                       i--;
+                               }
+                               else
+                                       prev = n;
+                       }
+               }
+
+               public SortedIterator (SortedIterator other) : base (other)
+               {
+                       this.list = other.list;
+                       SetPosition (other.CurrentPosition);
+               }
+
+               public override XPathNodeIterator Clone () { return new SortedIterator (this); }
+
+               public override bool MoveNextCore ()
+               {
+                       return CurrentPosition < list.Count;
+               }
+
+               public override XPathNavigator Current {
+                       get { return CurrentPosition == 0 ? null : (XPathNavigator) list [CurrentPosition - 1]; }
+               }
+
+               public override int Count {
+                       get { return list.Count; }
+               }
+       }
+
+       // NOTE: it is *not* sorted. Do not directly use it without checking sorting requirement.
        internal class SlashIterator : BaseIterator
        {
                private BaseIterator _iterLeft;
                private BaseIterator _iterRight;
                private NodeSet _expr;
-               ArrayList _navStore;
                SortedList _iterList;
                bool _finished;
                BaseIterator _nextIterRight;
 
-               public SlashIterator (BaseIterator iter, NodeSet expr, bool requireSorting) : base (iter.NamespaceManager)
+               public SlashIterator (BaseIterator iter, NodeSet expr) : base (iter.NamespaceManager)
                {
                        _iterLeft = iter;
                        _expr = expr;
-
-                       if (requireSorting)
-                               CollectResults ();
                }
 
                private SlashIterator (SlashIterator other) : base (other)
@@ -884,8 +934,6 @@ namespace System.Xml.XPath
                        _expr = other._expr;
                        if (other._iterList != null)
                                _iterList = (SortedList) other._iterList.Clone ();
-                       if (other._navStore != null)
-                               _navStore = (ArrayList) other._navStore.Clone ();
                        _finished = other._finished;
                        if (other._nextIterRight != null)
                                _nextIterRight = (BaseIterator) other._nextIterRight.Clone ();
@@ -896,24 +944,7 @@ namespace System.Xml.XPath
                {
                        if (_finished)
                                return false;
-                       if (_navStore != null) {
-                               // Which requires sorting::
-                               if (_navStore.Count < CurrentPosition + 1) {
-                                       _finished = true;
-                                       return false;
-                               }
-                               while (_navStore.Count > CurrentPosition + 1) {
-                                       if (((XPathNavigator) _navStore [CurrentPosition + 1]).IsSamePosition (
-                                               (XPathNavigator) _navStore [CurrentPosition]))
-                                               _navStore.RemoveAt (CurrentPosition + 1);
-                                       else
-                                               break;
-                               }
 
-                               return true;
-                       }
-                       // Which does not require sorting::
-                       
                        if (_iterRight == null) { // First time
                                if (!_iterLeft.MoveNext ())
                                        return false;
@@ -985,34 +1016,11 @@ namespace System.Xml.XPath
                        }
                }
 
-               private void CollectResults ()
-               {
-                       _navStore = new ArrayList ();
-                       while (true) {
-                               while (_iterRight == null || !_iterRight.MoveNext ()) {
-                                       if (!_iterLeft.MoveNext ()) {
-                                               _navStore.Sort (XPathNavigatorComparer.Instance);
-                                               return;
-                                       }
-                                       _iterRight = _expr.EvaluateNodeSet (_iterLeft);
-                               }
-                               XPathNavigator nav = _iterRight.Current;
-                               _navStore.Add (nav.Clone ());
-                       }
-               }
-
                public override XPathNavigator Current { 
                        get {
-                               if (CurrentPosition <= 0) return null;
-                               if (_navStore != null) {
-                                       return (XPathNavigator) _navStore [CurrentPosition - 1];
-                               } else {
-                                       return _iterRight.Current;
-                               }
+                               return (CurrentPosition == 0) ? null : _iterRight.Current;
                        }
                }
-
-               public override int Count { get { return _navStore == null ? base.Count : _navStore.Count; } }
        }
 
        internal class PredicateIterator : BaseIterator