2 // System.Xml.XPath.BaseIterator
5 // Piers Haken (piersh@friskit.com)
6 // Atsushi Enomoto (atsushi@ximian.com)
8 // (C) 2002 Piers Haken
9 // (C) 2003 Atsushi Enomoto
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System.Collections;
36 using System.Xml.XPath;
39 namespace System.Xml.XPath
41 internal abstract class BaseIterator : XPathNodeIterator
43 private XmlNamespaceManager _nsm;
44 protected bool _needClone = true; // TODO: use this field in practice.
46 internal BaseIterator (BaseIterator other)
50 internal BaseIterator (XmlNamespaceManager nsm)
55 public XmlNamespaceManager NamespaceManager
61 public virtual bool ReverseAxis {
65 public abstract bool RequireSorting { get; }
67 public virtual int ComparablePosition {
70 int diff = Count - CurrentPosition + 1;
71 return diff < 1 ? 1 : diff;
74 return CurrentPosition;
78 public override string ToString ()
81 return Current.NodeType.ToString () + "[" + CurrentPosition + "] : " + Current.Name + " = " + Current.Value;
83 return this.GetType().ToString () + "[" + CurrentPosition + "]";
87 internal class WrapperIterator : BaseIterator
89 XPathNodeIterator iter;
91 public WrapperIterator (XPathNodeIterator iter, XmlNamespaceManager nsm)
97 public override XPathNodeIterator Clone ()
99 return new WrapperIterator (iter.Clone (), NamespaceManager);
102 public override bool MoveNext ()
104 return iter.MoveNext ();
107 public override XPathNavigator Current {
108 get { return iter.Current; }
111 public override int CurrentPosition {
112 get { return iter.CurrentPosition; }
115 public override bool RequireSorting {
120 internal abstract class SimpleIterator : BaseIterator
122 protected readonly BaseIterator _iter;
123 protected readonly XPathNavigator _nav;
124 protected XPathNavigator _current;
127 public SimpleIterator (BaseIterator iter) : base (iter)
130 _nav = iter.Current.Clone ();
131 _current = _nav.Clone ();
133 protected SimpleIterator (SimpleIterator other) : base (other)
135 if (other._nav == null)
136 _iter = (BaseIterator) other._iter.Clone ();
138 _nav = other._nav.Clone ();
140 _current = other._current.Clone ();
142 public SimpleIterator (XPathNavigator nav, XmlNamespaceManager nsm) : base (nsm)
145 _current = nav.Clone ();
148 public override XPathNavigator Current { get { return _current; }}
149 public override int CurrentPosition { get { return _pos; }}
152 internal class SelfIterator : SimpleIterator
154 public SelfIterator (BaseIterator iter) : base (iter) {}
155 public SelfIterator (XPathNavigator nav, XmlNamespaceManager nsm) : base (nav, nsm) {}
156 protected SelfIterator (SelfIterator other) : base (other) {}
157 public override XPathNodeIterator Clone () { return new SelfIterator (this); }
158 public override bool MoveNext ()
163 _current = _needClone ? _nav.Clone () : _nav;
169 public override bool RequireSorting { get { return false; } }
172 internal class NullIterator : SelfIterator
174 public NullIterator (BaseIterator iter) : base (iter) {}
175 public NullIterator (XPathNavigator nav) : this (nav, null) {}
176 public NullIterator (XPathNavigator nav, XmlNamespaceManager nsm) : base (nav, nsm) {}
177 protected NullIterator (NullIterator other) : base (other) {}
178 public override XPathNodeIterator Clone () { return new NullIterator (this); }
179 public override bool MoveNext ()
185 internal class ParensIterator : BaseIterator
188 public ParensIterator (BaseIterator iter) : base (iter)
192 protected ParensIterator (ParensIterator other) : base (other)
194 _iter = (BaseIterator) other._iter.Clone ();
196 public override XPathNodeIterator Clone () { return new ParensIterator (this); }
197 public override bool MoveNext ()
199 return _iter.MoveNext ();
202 public override XPathNavigator Current { get { return _iter.Current; }}
203 public override int CurrentPosition { get { return _iter.CurrentPosition; } }
205 public override bool RequireSorting { get { return _iter.RequireSorting; } }
207 public override int Count { get { return _iter.Count; } }
210 internal class ParentIterator : SimpleIterator
212 public ParentIterator (BaseIterator iter) : base (iter) {}
213 protected ParentIterator (ParentIterator other) : base (other) {}
214 public ParentIterator (XPathNavigator nav, XmlNamespaceManager nsm) : base (nav, nsm) {}
215 public override XPathNodeIterator Clone () { return new ParentIterator (this); }
216 public override bool MoveNext ()
218 if (_pos == 0 && _nav.MoveToParent ())
221 _current = _needClone ? _nav.Clone () : _nav;
227 public override bool ReverseAxis { get { return true; } }
229 public override bool RequireSorting { get { return true; } }
232 internal class ChildIterator : SimpleIterator
234 public ChildIterator (BaseIterator iter) : base (iter) {}
235 protected ChildIterator (ChildIterator other) : base (other) {}
236 public override XPathNodeIterator Clone () { return new ChildIterator (this); }
237 public override bool MoveNext ()
239 bool fSuccess = (_pos == 0) ? _nav.MoveToFirstChild () : _nav.MoveToNext ();
242 // This clone cannot be omitted
243 _current = _nav.Clone ();
248 public override bool RequireSorting { get { return false; } }
251 internal class FollowingSiblingIterator : SimpleIterator
253 public FollowingSiblingIterator (BaseIterator iter) : base (iter) {}
254 protected FollowingSiblingIterator (FollowingSiblingIterator other) : base (other) {}
255 public override XPathNodeIterator Clone () { return new FollowingSiblingIterator (this); }
256 public override bool MoveNext ()
258 switch (_nav.NodeType) {
259 case XPathNodeType.Attribute:
260 case XPathNodeType.Namespace:
261 // They have no siblings.
264 if (_nav.MoveToNext ())
267 // This clone cannot be omitted
268 _current = _nav.Clone ();
274 public override bool RequireSorting { get { return false; } }
277 internal class PrecedingSiblingIterator : SimpleIterator
281 XPathNavigator startPosition;
283 public PrecedingSiblingIterator (BaseIterator iter) : base (iter)
285 startPosition = iter.Current.Clone ();
286 _current = startPosition.Clone ();
288 protected PrecedingSiblingIterator (PrecedingSiblingIterator other) : base (other)
290 startPosition = other.startPosition;
291 started = other.started;
292 finished = other.finished;
293 _current = other._current.Clone ();
296 public override XPathNodeIterator Clone () { return new PrecedingSiblingIterator (this); }
297 public override bool MoveNext ()
303 switch (_nav.NodeType) {
304 case XPathNodeType.Attribute:
305 case XPathNodeType.Namespace:
306 // They have no siblings.
312 if (_nav.ComparePosition (startPosition) != XmlNodeOrder.Same) {
314 // This clone cannot be omitted
315 _current = _nav.Clone ();
319 if (!_nav.MoveToNext ()) {
324 if (_nav.ComparePosition (startPosition) != XmlNodeOrder.Before) {
325 // Note that if _nav contains only 1 node, it won't be Same.
330 // This clone cannot be omitted
331 _current = _nav.Clone ();
335 public override bool ReverseAxis {
339 public override bool RequireSorting { get { return true; } }
342 internal class AncestorIterator : SimpleIterator
346 ArrayList positions = new ArrayList ();
347 XPathNavigator startPosition;
349 public AncestorIterator (BaseIterator iter) : base (iter)
351 startPosition = iter.Current.Clone ();
352 _current = startPosition.Clone ();
354 protected AncestorIterator (AncestorIterator other) : base (other)
356 startPosition = other.startPosition;
357 started = other.started;
358 finished = other.finished;
359 positions = (ArrayList) other.positions.Clone ();
360 nextDepth = other.nextDepth;
361 _current = other._current.Clone ();
363 public override XPathNodeIterator Clone () { return new AncestorIterator (this); }
364 public override bool MoveNext ()
370 // This clone cannot be omitted
371 XPathNavigator ancestors = startPosition.Clone ();
372 ancestors.MoveToParent ();
373 _nav.MoveToParent ();
374 while (ancestors.NodeType != XPathNodeType.Root) {
377 while (_nav.ComparePosition (ancestors) == XmlNodeOrder.Before) {
382 if (!ancestors.MoveToParent ())
383 break; // It is for detached nodes under XmlDocumentNavigator
384 _nav.MoveToParent ();
388 positions.Reverse ();
390 if (startPosition.NodeType != XPathNodeType.Root) {
391 // First time it returns Root
393 // This clone cannot be omitted
394 _current = _nav.Clone ();
398 // Don't worry about node type of start position, like AncestorOrSelf.
399 // It should be Element or Root.
400 if (nextDepth < positions.Count) {
401 int thisTimePos = (int) positions [nextDepth];
402 _nav.MoveToFirstChild ();
403 for (int i = 0; i < thisTimePos; i++)
407 // This clone cannot be omitted
408 _current = _nav.Clone ();
415 public override bool ReverseAxis {
419 public override bool RequireSorting { get { return true; } }
421 public override int Count { get { return positions.Count; } }
424 internal class AncestorOrSelfIterator : SimpleIterator
428 ArrayList positions = new ArrayList ();
429 XPathNavigator startPosition;
432 public AncestorOrSelfIterator (BaseIterator iter) : base (iter)
434 startPosition = iter.Current.Clone ();
435 _current = startPosition.Clone ();
437 protected AncestorOrSelfIterator (AncestorOrSelfIterator other) : base (other)
439 startPosition = other.startPosition;
440 started = other.started;
441 finished = other.finished;
442 positions = (ArrayList) other.positions.Clone ();
443 nextDepth = other.nextDepth;
444 _current = other._current.Clone ();
446 public override XPathNodeIterator Clone () { return new AncestorOrSelfIterator (this); }
447 public override bool MoveNext ()
449 bool initialIteration = false;
453 initialIteration = true;
455 // This clone cannot be omitted
456 XPathNavigator ancestors = startPosition.Clone ();
460 while (_nav.ComparePosition (ancestors) == XmlNodeOrder.Before) {
465 if (!ancestors.MoveToParent ())
466 break; // for detached nodes under XmlDocumentNavigator.
467 _nav.MoveToParent ();
468 } while (ancestors.NodeType != XPathNodeType.Root);
469 positions.Reverse ();
471 if (initialIteration && startPosition.NodeType != XPathNodeType.Root) {
472 // This clone cannot be omitted
473 _current = _nav.Clone ();
475 } else if (nextDepth + 1 == positions.Count) {
478 _nav.MoveTo (startPosition);
479 // This clone cannot be omitted
480 _current = _nav.Clone ();
483 else if (nextDepth < positions.Count) {
484 int thisTimePos = (int) positions [nextDepth];
485 _nav.MoveToFirstChild ();
486 for (int i = 0; i < thisTimePos; i++)
490 // This clone cannot be omitted
491 _current = _nav.Clone ();
498 public override bool ReverseAxis {
502 public override bool RequireSorting { get { return true; } }
504 public override int Count { get { return positions.Count; } }
507 internal class DescendantIterator : SimpleIterator
509 protected int _depth;
510 private bool _finished;
512 public DescendantIterator (BaseIterator iter) : base (iter) {}
514 protected DescendantIterator (DescendantIterator other) : base (other)
516 _depth = other._depth;
517 _finished = other._finished;
518 _current = other._current.Clone ();
521 public override XPathNodeIterator Clone () { return new DescendantIterator (this); }
523 public override bool MoveNext ()
528 if (_nav.MoveToFirstChild ())
532 // This clone cannot be omitted
533 _current = _nav.Clone ();
538 if (_nav.MoveToNext ())
541 // This clone cannot be omitted
542 _current = _nav.Clone ();
545 if (!_nav.MoveToParent ()) // should NEVER fail!
546 throw new XPathException ("There seems some bugs on the XPathNavigator implementation class.");
553 public override bool RequireSorting { get { return false; } }
556 internal class DescendantOrSelfIterator : SimpleIterator
558 protected int _depth;
559 private bool _finished;
561 public DescendantOrSelfIterator (BaseIterator iter) : base (iter) {}
563 protected DescendantOrSelfIterator (DescendantOrSelfIterator other) : base (other)
565 _depth = other._depth;
566 _current = other._current.Clone ();
569 public override XPathNodeIterator Clone () { return new DescendantOrSelfIterator (this); }
571 public override bool MoveNext ()
580 // This clone cannot be omitted
581 _current = _nav.Clone ();
584 if (_nav.MoveToFirstChild ())
588 // This clone cannot be omitted
589 _current = _nav.Clone ();
594 if (_nav.MoveToNext ())
597 // This clone cannot be omitted
598 _current = _nav.Clone ();
601 if (!_nav.MoveToParent ()) // should NEVER fail!
602 throw new XPathException ("There seems some bugs on the XPathNavigator implementation class.");
609 public override bool RequireSorting { get { return false; } }
612 internal class FollowingIterator : SimpleIterator
614 private bool _finished = false;
615 public FollowingIterator (BaseIterator iter) : base (iter) {}
616 protected FollowingIterator (FollowingIterator other) : base (other) {}
617 public override XPathNodeIterator Clone () { return new FollowingIterator (this); }
618 public override bool MoveNext ()
624 if (_nav.MoveToNext ())
627 // This clone cannot be omitted
628 _current = _nav.Clone ();
631 while (_nav.MoveToParent ()) {
632 if (_nav.MoveToNext ()) {
634 // This clone cannot be omitted
635 _current = _nav.Clone ();
643 if (_nav.MoveToFirstChild ())
646 // This clone cannot be omitted
647 _current = _nav.Clone ();
652 if (_nav.MoveToNext ())
655 // This clone cannot be omitted
656 _current = _nav.Clone ();
660 while (_nav.MoveToParent ());
666 public override bool RequireSorting { get { return false; } }
669 internal class PrecedingIterator : SimpleIterator
673 XPathNavigator startPosition;
675 public PrecedingIterator (BaseIterator iter) : base (iter)
677 startPosition = iter.Current.Clone ();
678 _current = startPosition.Clone ();
680 protected PrecedingIterator (PrecedingIterator other) : base (other)
682 startPosition = other.startPosition;
683 started = other.started;
684 finished = other.finished;
685 _current = other._current.Clone ();
687 public override XPathNodeIterator Clone () { return new PrecedingIterator (this); }
688 public override bool MoveNext ()
698 while (!_nav.MoveToFirstChild ()) {
699 while (!_nav.MoveToNext ()) {
700 if (!_nav.MoveToParent ()) { // Should not finish, at least before startPosition.
707 if (_nav.IsDescendant (startPosition))
712 if (_nav.ComparePosition (startPosition) != XmlNodeOrder.Before) {
713 // Note that if _nav contains only 1 node, it won't be Same.
718 // This cannot be omitted
719 _current = _nav.Clone ();
723 public override bool ReverseAxis {
727 public override bool RequireSorting { get { return true; } }
730 internal class NamespaceIterator : SimpleIterator
732 public NamespaceIterator (BaseIterator iter) : base (iter) {}
733 protected NamespaceIterator (NamespaceIterator other) : base (other) {}
734 public override XPathNodeIterator Clone () { return new NamespaceIterator (this); }
735 public override bool MoveNext ()
739 if (_nav.MoveToFirstNamespace ())
742 // This clone cannot be omitted
743 _current = _nav.Clone ();
747 else if (_nav.MoveToNextNamespace ())
750 // This clone cannot be omitted
751 _current = _nav.Clone ();
757 public override bool ReverseAxis { get { return true; } }
758 public override bool RequireSorting { get { return false; } }
761 internal class AttributeIterator : SimpleIterator
763 public AttributeIterator (BaseIterator iter) : base (iter) {}
764 protected AttributeIterator (AttributeIterator other) : base (other) {}
765 public override XPathNodeIterator Clone () { return new AttributeIterator (this); }
766 public override bool MoveNext ()
770 if (_nav.MoveToFirstAttribute ())
773 // This clone cannot be omitted
774 _current = _nav.Clone ();
778 else if (_nav.MoveToNextAttribute ())
781 // This clone cannot be omitted
782 _current = _nav.Clone ();
788 public override bool RequireSorting { get { return false; } }
791 internal class AxisIterator : BaseIterator
793 protected SimpleIterator _iter;
794 protected NodeTest _test;
798 XPathNodeType matchType;
800 public AxisIterator (SimpleIterator iter, NodeTest test) : base (iter)
804 test.GetInfo (out name, out ns, out matchType, NamespaceManager);
806 // name = Current.NameTable.Add (name);
809 // ns = Current.NameTable.Add (ns);
812 protected AxisIterator (AxisIterator other) : base (other)
814 _iter = (SimpleIterator) other._iter.Clone ();
819 matchType = other.matchType;
821 public override XPathNodeIterator Clone () { return new AxisIterator (this); }
823 public override bool MoveNext ()
825 while (_iter.MoveNext ())
827 if (_test.Match (NamespaceManager, Current))
835 public override XPathNavigator Current { get { return _iter.Current; }}
836 public override int CurrentPosition { get { return _pos; }}
840 if (Current.NodeType != matchType && matchType != XPathNodeType.All)
844 return name == null || (object)name == (object)Current.LocalName;
846 return (object)ns == (object)Current.NamespaceURI &&
847 (name == null || (object)name == (object)Current.LocalName);
849 public override bool ReverseAxis {
850 get { return _iter.ReverseAxis; }
853 public override bool RequireSorting { get { return _iter.RequireSorting; } }
856 internal class SlashIterator : BaseIterator
858 protected BaseIterator _iterLeft;
859 protected BaseIterator _iterRight;
860 protected NodeSet _expr;
863 SortedList _iterList;
865 BaseIterator _nextIterRight;
867 public SlashIterator (BaseIterator iter, NodeSet expr) : base (iter)
873 protected SlashIterator (SlashIterator other) : base (other)
875 _iterLeft = (BaseIterator) other._iterLeft.Clone ();
876 if (other._iterRight != null)
877 _iterRight = (BaseIterator) other._iterRight.Clone ();
880 if (other._iterList != null)
881 _iterList = (SortedList) other._iterList.Clone ();
882 if (other._navStore != null)
883 _navStore = (ArrayList) other._navStore.Clone ();
884 _finished = other._finished;
885 if (other._nextIterRight != null)
886 _nextIterRight = (BaseIterator) other._nextIterRight.Clone ();
888 public override XPathNodeIterator Clone () { return new SlashIterator (this); }
890 public override bool MoveNext ()
894 if (RequireSorting) {
895 if (_navStore == null) {
897 if (_navStore.Count == 0) {
903 if (_navStore.Count < _pos) {
908 while (_navStore.Count > _pos) {
909 if (((XPathNavigator) _navStore [_pos]).ComparePosition (
910 (XPathNavigator) _navStore [_pos - 1]) == XmlNodeOrder.Same)
911 _navStore.RemoveAt (_pos);
918 if (_iterRight == null) { // First time
919 if (!_iterLeft.MoveNext ())
921 _iterRight = _expr.EvaluateNodeSet (_iterLeft);
922 _iterList = new SortedList (XPathIteratorComparer.Instance);
926 while (!_iterRight.MoveNext ()) {
927 if (_iterList.Count > 0) {
928 int last = _iterList.Count - 1;
929 BaseIterator tmpIter = (BaseIterator) _iterList.GetByIndex (last);
930 _iterList.RemoveAt (last);
931 switch (tmpIter.Current.ComparePosition (_iterRight.Current)) {
932 case XmlNodeOrder.Same:
933 case XmlNodeOrder.Before:
934 _iterRight = tmpIter;
937 _iterRight = tmpIter;
941 } else if (_nextIterRight != null) {
942 _iterRight = _nextIterRight;
943 _nextIterRight = null;
945 } else if (!_iterLeft.MoveNext ()) {
950 _iterRight = _expr.EvaluateNodeSet (_iterLeft);
955 if (_nextIterRight == null) {
956 bool noMoreNext = false;
957 while (_nextIterRight == null || !_nextIterRight.MoveNext ()) {
958 if(_iterLeft.MoveNext ())
959 _nextIterRight = _expr.EvaluateNodeSet (_iterLeft);
966 _nextIterRight = null; // FIXME: More efficient code. Maybe making noMoreNext class scope would be better.
968 if (_nextIterRight != null) {
969 switch (_iterRight.Current.ComparePosition (_nextIterRight.Current)) {
970 case XmlNodeOrder.After:
971 _iterList.Add (_iterList.Count, _iterRight);
972 _iterRight = _nextIterRight;
973 _nextIterRight = null;
976 case XmlNodeOrder.Same:
977 if (!_nextIterRight.MoveNext ())
978 _nextIterRight = null;
981 int last = _iterList.Count;
983 _iterList.Add (last, _nextIterRight);
984 _nextIterRight = (BaseIterator) _iterList.GetByIndex (last);
985 _iterList.RemoveAt (last);
999 private void CollectResults ()
1001 if (_navStore != null)
1003 _navStore = new ArrayList ();
1005 while (_iterRight == null || !_iterRight.MoveNext ()) {
1006 if (!_iterLeft.MoveNext ()) {
1007 _navStore.Sort (XPathNavigatorComparer.Instance);
1010 _iterRight = _expr.EvaluateNodeSet (_iterLeft);
1012 XPathNavigator nav = _iterRight.Current;
1013 _navStore.Add (_needClone ? nav.Clone () : nav);
1017 public override XPathNavigator Current {
1019 if (_pos <= 0) return null;
1020 if (RequireSorting) {
1021 return (XPathNavigator) _navStore [_pos - 1];
1023 return _iterRight.Current;
1027 public override int CurrentPosition { get { return _pos; }}
1029 public override bool RequireSorting {
1031 return _iterLeft.RequireSorting || _expr.RequireSorting;
1035 public override int Count { get { return _navStore == null ? base.Count : _navStore.Count; } }
1038 internal class PredicateIterator : BaseIterator
1040 protected BaseIterator _iter;
1041 protected Expression _pred;
1043 protected XPathResultType resType;
1045 public PredicateIterator (BaseIterator iter, Expression pred) : base (iter)
1049 resType = pred.GetReturnType (iter);
1052 protected PredicateIterator (PredicateIterator other) : base (other)
1054 _iter = (BaseIterator) other._iter.Clone ();
1055 _pred = other._pred;
1057 resType = other.resType;
1059 public override XPathNodeIterator Clone () { return new PredicateIterator (this); }
1061 public override bool MoveNext ()
1063 while (_iter.MoveNext ())
1066 case XPathResultType.Number:
1067 if (_pred.EvaluateNumber (_iter) != _iter.ComparablePosition)
1070 case XPathResultType.Any: {
1071 object result = _pred.Evaluate (_iter);
1072 if (result is double)
1074 if ((double) result != _iter.ComparablePosition)
1077 else if (!XPathFunctions.ToBoolean (result))
1082 if (!_pred.EvaluateBoolean (_iter))
1092 public override XPathNavigator Current { get { return _iter.Current; }}
1093 public override int CurrentPosition { get { return _pos; }}
1094 public override bool ReverseAxis {
1095 get { return _iter.ReverseAxis; }
1098 public override bool RequireSorting { get { return true; } }
1102 internal class EnumeratorIterator : BaseIterator
1104 protected IEnumerator _enum;
1106 bool _requireSorting;
1108 public EnumeratorIterator (BaseIterator iter, IEnumerator enumerator, bool requireSorting) : base (iter)
1110 if (!(enumerator is ICloneable))
1111 throw new ArgumentException ("Target enumerator must be cloneable.");
1113 _requireSorting = requireSorting;
1116 public EnumeratorIterator (IEnumerator enumerator, XmlNamespaceManager nsm, bool requireSorting) : base (nsm)
1118 if (!(enumerator is ICloneable))
1119 throw new ArgumentException ("Target enumerator must be cloneable.");
1121 _requireSorting = requireSorting;
1124 protected EnumeratorIterator (EnumeratorIterator other) : base (other)
1126 ICloneable enumClone = other._enum as ICloneable;
1127 _enum = (IEnumerator) enumClone.Clone ();
1129 _requireSorting = other._requireSorting;
1131 public override XPathNodeIterator Clone () { return new EnumeratorIterator (this); }
1133 public override bool MoveNext ()
1135 if (!_enum.MoveNext ())
1140 public override XPathNavigator Current { get { return (XPathNavigator) _enum.Current; }}
1141 public override int CurrentPosition { get { return _pos; }}
1143 public override bool RequireSorting { get { return _requireSorting; } }
1147 internal class ListIterator : BaseIterator
1149 protected IList _list;
1151 bool _requireSorting;
1153 public ListIterator (BaseIterator iter, IList list, bool requireSorting) : base (iter)
1155 if (!(list is ICloneable))
1156 throw new ArgumentException ("Target enumerator must be cloneable.");
1158 _requireSorting = requireSorting;
1161 public ListIterator (IList list, XmlNamespaceManager nsm, bool requireSorting) : base (nsm)
1163 if (!(list is ICloneable))
1164 throw new ArgumentException ("Target enumerator must be cloneable.");
1166 _requireSorting = requireSorting;
1169 protected ListIterator (ListIterator other) : base (other)
1171 ICloneable listClone = other._list as ICloneable;
1172 _list = (IList) listClone.Clone ();
1174 _requireSorting = other._requireSorting;
1176 public override XPathNodeIterator Clone () { return new ListIterator (this); }
1178 public override bool MoveNext ()
1180 if (_pos >= _list.Count)
1185 public override XPathNavigator Current {
1187 if (_list.Count == 0)
1189 return (XPathNavigator) _list [_pos - 1];
1192 public override int CurrentPosition { get { return _pos; }}
1194 public override bool RequireSorting { get { return _requireSorting; } }
1196 public override int Count { get { return _list.Count; } }
1200 internal class UnionIterator : BaseIterator
1202 protected BaseIterator _left, _right;
1204 private bool keepLeft;
1205 private bool keepRight;
1206 private bool useRight;
1208 public UnionIterator (BaseIterator iter, BaseIterator left, BaseIterator right) : base (iter)
1214 protected UnionIterator (UnionIterator other) : base (other)
1216 _left = (BaseIterator) other._left.Clone ();
1217 _right = (BaseIterator) other._right.Clone ();
1219 keepLeft = other.keepLeft;
1220 keepRight = other.keepRight;
1221 useRight = other.useRight;
1223 public override XPathNodeIterator Clone () { return new UnionIterator (this); }
1225 public override bool MoveNext ()
1228 keepLeft = _left.MoveNext ();
1230 keepRight = _right.MoveNext ();
1232 if (!keepLeft && !keepRight)
1237 keepLeft = useRight = false;
1239 } else if (!keepLeft) {
1245 switch (_left.Current.ComparePosition (_right.Current)) {
1246 case XmlNodeOrder.Same:
1247 // consume both. i.e. don't output duplicate result.
1248 keepLeft = keepRight = false;
1251 case XmlNodeOrder.Before:
1252 case XmlNodeOrder.Unknown: // Maybe happen because of "document(a) | document(b)"
1253 keepLeft = useRight = false;
1255 case XmlNodeOrder.After:
1260 throw new InvalidOperationException ("Should not happen.");
1263 public override XPathNavigator Current
1270 return _right.Current;
1272 return _left.Current;
1275 public override int CurrentPosition { get { return _pos; }}
1277 public override bool RequireSorting { get { return _left.RequireSorting || _right.RequireSorting; } }