run-W3C-tests.bat: skip nunit build if already done
[mono.git] / mcs / class / System.XML / System.Xml.XPath / Iterator.cs
1 //
2 // System.Xml.XPath.BaseIterator
3 //
4 // Author:
5 //   Piers Haken (piersh@friskit.com)
6 //   Atsushi Enomoto (atsushi@ximian.com)
7 //
8 // (C) 2002 Piers Haken
9 // (C) 2003 Atsushi Enomoto
10 //
11
12 //
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:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
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.
31 //
32
33 using System;
34 using System.Collections;
35 using System.Xml;
36 using System.Xml.XPath;
37 using System.Xml.Xsl;
38
39 #if NET_2_0
40 using NSResolver = System.Xml.IXmlNamespaceResolver;
41 #else
42 using NSResolver = System.Xml.XmlNamespaceManager;
43 #endif
44
45 namespace System.Xml.XPath
46 {
47         internal abstract class BaseIterator : XPathNodeIterator
48         {
49                 NSResolver _nsm;
50                 int position;
51
52                 internal BaseIterator (BaseIterator other)
53                 {
54                         _nsm = other._nsm;
55                         position = other.position;
56                 }
57                 internal BaseIterator (NSResolver nsm)
58                 {
59                         _nsm = nsm;
60                 }
61
62                 public NSResolver NamespaceManager
63                 {
64                         get { return _nsm; }
65                         set { _nsm = value; }
66                 }
67
68                 public virtual bool ReverseAxis {
69                         get { return false; }
70                 }
71
72                 public int ComparablePosition {
73                         get {
74                                 if (ReverseAxis) {
75                                         int diff = Count - CurrentPosition + 1;
76                                         return diff < 1 ? 1 : diff;
77                                 }
78                                 else
79                                         return CurrentPosition;
80                         }
81                 }
82
83                 public override int CurrentPosition {
84                         get { return position; }
85                 }
86
87                 public override bool MoveNext ()
88                 {
89                         if (!MoveNextCore ())
90                                 return false;
91                         position++;
92                         return true;
93                 }
94
95                 public abstract bool MoveNextCore ();
96
97                 public override string ToString ()
98                 {
99                         if (Current != null)
100                                 return Current.NodeType.ToString () + "[" + CurrentPosition + "] : " + Current.Name + " = " + Current.Value;
101                         else
102                                 return this.GetType().ToString () + "[" + CurrentPosition + "]";
103                 }
104         }
105
106         internal class WrapperIterator : BaseIterator
107         {
108                 XPathNodeIterator iter;
109
110                 public WrapperIterator (XPathNodeIterator iter, NSResolver nsm)
111                         : base (nsm)
112                 {
113                         this.iter = iter;
114                 }
115
116                 private WrapperIterator (WrapperIterator other)
117                         : base (other)
118                 {
119                         iter = other.iter.Clone ();
120                 }
121
122                 public override XPathNodeIterator Clone ()
123                 {
124                         return new WrapperIterator (this);
125                 }
126
127                 public override bool MoveNextCore ()
128                 {
129                         return iter.MoveNext ();
130                 }
131
132                 public override XPathNavigator Current {
133                         get { return iter.Current; }
134                 }
135         }
136
137         internal abstract class SimpleIterator : BaseIterator
138         {
139                 protected readonly XPathNavigator _nav;
140                 protected XPathNavigator _current;
141
142                 public SimpleIterator (BaseIterator iter) : base (iter.NamespaceManager)
143                 {
144                         _nav = iter.Current.Clone ();
145                 }
146                 protected SimpleIterator (SimpleIterator other, bool clone) : base (other)
147                 {
148                         _nav = other._nav.Clone ();
149                 }
150                 public SimpleIterator (XPathNavigator nav, NSResolver nsm) : base (nsm)
151                 {
152                         _nav = nav.Clone ();
153                 }
154
155                 public override XPathNavigator Current {
156                         get {
157                                 if (_current == null) // position == 0
158                                         _current = _nav.Clone ();
159                                 return _current;
160                         }
161                 }
162         }
163
164         internal class SelfIterator : SimpleIterator
165         {
166                 public SelfIterator (BaseIterator iter) : base (iter) {}
167                 public SelfIterator (XPathNavigator nav, NSResolver nsm) : base (nav, nsm) {}
168                 protected SelfIterator (SelfIterator other, bool clone) : base (other, true) 
169                 {
170                 }
171
172                 public override XPathNodeIterator Clone () { return new SelfIterator (this, true); }
173                 public override bool MoveNextCore ()
174                 {
175                         if (CurrentPosition == 0)
176                         {
177                                 return true;
178                         }
179                         return false;
180                 }
181
182                 public override XPathNavigator Current {
183                         get { return _nav; }
184                 }
185         }
186
187         internal class NullIterator : SelfIterator
188         {
189                 public NullIterator (BaseIterator iter) : base (iter) {}
190                 public NullIterator (XPathNavigator nav) : this (nav, null) {}
191                 public NullIterator (XPathNavigator nav, NSResolver nsm) : base (nav, nsm) {}
192                 private NullIterator (NullIterator other) : base (other, true) {}
193                 public override XPathNodeIterator Clone () { return new NullIterator (this); }
194                 public override bool MoveNextCore ()
195                 {
196                         return false;
197                 }
198         }
199
200         internal class ParensIterator : BaseIterator
201         {
202                 BaseIterator _iter;
203
204                 public ParensIterator (BaseIterator iter) : base (iter.NamespaceManager) 
205                 {
206                         _iter = iter;
207                 }
208                 private ParensIterator (ParensIterator other) : base (other) 
209                 {
210                         _iter = (BaseIterator) other._iter.Clone ();
211                 }
212                 public override XPathNodeIterator Clone () { return new ParensIterator (this); }
213                 public override bool MoveNextCore ()
214                 {
215                         return _iter.MoveNext ();
216                 }
217
218                 public override XPathNavigator Current { get { return _iter.Current; }}
219
220                 public override int Count { get { return _iter.Count; } }
221         }
222
223         internal class ParentIterator : SimpleIterator
224         {
225                 bool canMove;
226                 public ParentIterator (BaseIterator iter) : base (iter)
227                 {
228                         canMove = _nav.MoveToParent ();
229                         _current = _nav;
230                 }
231                 private ParentIterator (ParentIterator other, bool dummy) : base (other, true)
232                 {
233                         _current = _nav;
234                         canMove = other.canMove;
235                 }
236                 public ParentIterator (XPathNavigator nav, NSResolver nsm) : base (nav, nsm) {}
237                 public override XPathNodeIterator Clone () { return new ParentIterator (this, true); }
238                 public override bool MoveNextCore ()
239                 {
240                         if (!canMove)
241                                 return false;
242                         canMove = false;
243                         return true;
244                 }
245         }
246
247         internal class ChildIterator : SimpleIterator
248         {
249                 public ChildIterator (BaseIterator iter) : base (iter) {}
250                 private ChildIterator (ChildIterator other) : base (other, true) {}
251                 public override XPathNodeIterator Clone () { return new ChildIterator (this); }
252                 public override bool MoveNextCore ()
253                 {
254                         bool fSuccess = (CurrentPosition == 0) ? _nav.MoveToFirstChild () : _nav.MoveToNext ();
255                         if (fSuccess) {
256                                 Current.MoveTo (_nav);
257                         }
258                         return fSuccess;
259                 }
260         }
261
262         internal class FollowingSiblingIterator : SimpleIterator
263         {
264                 public FollowingSiblingIterator (BaseIterator iter) : base (iter) {}
265                 private FollowingSiblingIterator (FollowingSiblingIterator other) : base (other, true) {}
266                 public override XPathNodeIterator Clone () { return new FollowingSiblingIterator (this); }
267                 public override bool MoveNextCore ()
268                 {
269                         switch (_nav.NodeType) {
270                         case XPathNodeType.Attribute:
271                         case XPathNodeType.Namespace:
272                                 // They have no siblings.
273                                 return false;
274                         }
275                         if (_nav.MoveToNext ())
276                         {
277                                 Current.MoveTo (_nav);
278                                 return true;
279                         }
280                         return false;
281                 }
282         }
283
284         internal class PrecedingSiblingIterator : SimpleIterator
285         {
286                 bool finished;
287                 bool started;
288                 XPathNavigator startPosition;
289
290                 public PrecedingSiblingIterator (BaseIterator iter) : base (iter)
291                 {
292                         startPosition = iter.Current.Clone ();
293                 }
294                 private PrecedingSiblingIterator (PrecedingSiblingIterator other) : base (other, true) 
295                 {
296                         startPosition = other.startPosition;
297                         started = other.started;
298                         finished = other.finished;
299                 }
300
301                 public override XPathNodeIterator Clone () { return new PrecedingSiblingIterator (this); }
302                 public override bool MoveNextCore ()
303                 {
304                         if (finished)
305                                 return false;
306                         if (!started) {
307                                 started = true;
308                                 switch (_nav.NodeType) {
309                                 case XPathNodeType.Attribute:
310                                 case XPathNodeType.Namespace:
311                                         // They have no siblings.
312                                         finished = true;
313                                         return false;
314                                 }
315
316                                 _nav.MoveToFirst ();
317                                 if (!_nav.IsSamePosition (startPosition)) {
318                                         Current.MoveTo (_nav);
319                                         return true;
320                                 }
321                         } else {
322                                 if (!_nav.MoveToNext ()) {
323                                         finished = true;
324                                         return false;
325                                 }
326                         }
327                         if (_nav.ComparePosition (startPosition) != XmlNodeOrder.Before) {
328                                 // Note that if _nav contains only 1 node, it won't be Same.
329                                 finished = true;
330                                 return false;
331                         } else {
332                                 Current.MoveTo (_nav);
333                                 return true;
334                         }
335                 }
336                 public override bool ReverseAxis {
337                         get { return true; }
338                 }
339         }
340
341         internal class AncestorIterator : SimpleIterator
342         {
343                 int currentPosition;
344                 ArrayList navigators;
345                 XPathNavigator startPosition;
346
347                 public AncestorIterator (BaseIterator iter) : base (iter)
348                 {
349                         startPosition = iter.Current.Clone ();
350                 }
351
352                 private AncestorIterator (AncestorIterator other)
353                         : base (other, true)
354                 {
355                         startPosition = other.startPosition;
356                         if (other.navigators != null)
357                                 navigators = (ArrayList) other.navigators;
358                         currentPosition = other.currentPosition;
359                 }
360
361                 public override XPathNodeIterator Clone ()
362                 {
363                         return new AncestorIterator (this);
364                 }
365
366                 private void CollectResults ()
367                 {
368                         navigators = new ArrayList ();
369
370                         XPathNavigator ancestors = startPosition.Clone ();
371                         if (!ancestors.MoveToParent ())
372                                 return;
373                         while (ancestors.NodeType != XPathNodeType.Root) {
374                                 navigators.Add (ancestors.Clone ());
375                                 ancestors.MoveToParent ();
376                         }
377                         currentPosition = navigators.Count;
378                 }
379
380                 public override bool MoveNextCore ()
381                 {
382                         if (navigators == null) {
383                                 CollectResults ();
384                                 if (startPosition.NodeType != XPathNodeType.Root) {
385                                         // First time it returns Root
386                                         _nav.MoveToRoot ();
387                                         Current.MoveTo (_nav);
388                                         return true;
389                                 }
390                         }
391                         if (currentPosition == 0)
392                                 return false;
393                         _nav.MoveTo ((XPathNavigator) navigators [--currentPosition]);
394                         Current.MoveTo (_nav);
395                         return true;
396                 }
397
398                 public override bool ReverseAxis {
399                         get { return true; }
400                 }
401
402                 public override int Count {
403                         get {
404                                 if (navigators == null)
405                                         CollectResults ();
406                                 return navigators.Count;
407                         }
408                 }
409         }
410
411         internal class AncestorOrSelfIterator : SimpleIterator
412         {
413                 int currentPosition;
414                 ArrayList navigators;
415                 XPathNavigator startPosition;
416
417                 public AncestorOrSelfIterator (BaseIterator iter) : base (iter)
418                 {
419                         startPosition = iter.Current.Clone ();
420                 }
421
422                 private AncestorOrSelfIterator (AncestorOrSelfIterator other)
423                         : base (other, true)
424                 {
425                         startPosition = other.startPosition;
426                         if (other.navigators != null)
427                                 navigators = (ArrayList) other.navigators.Clone ();
428                         currentPosition = other.currentPosition;
429                 }
430
431                 public override XPathNodeIterator Clone ()
432                 {
433                         return new AncestorOrSelfIterator (this);
434                 }
435
436                 private void CollectResults ()
437                 {
438                         navigators = new ArrayList ();
439
440                         XPathNavigator ancestors = startPosition.Clone ();
441                         if (!ancestors.MoveToParent ())
442                                 return;
443                         while (ancestors.NodeType != XPathNodeType.Root) {
444                                 navigators.Add (ancestors.Clone ());
445                                 ancestors.MoveToParent ();
446                         }
447                         currentPosition = navigators.Count;
448                 }
449
450                 public override bool MoveNextCore ()
451                 {
452                         if (navigators == null) {
453                                 CollectResults ();
454                                 if (startPosition.NodeType != XPathNodeType.Root) {
455                                         // First time it returns Root
456                                         _nav.MoveToRoot ();
457                                         Current.MoveTo (_nav);
458                                         return true;
459                                 }
460                         }
461                         if (currentPosition == -1)
462                                 return false;
463                         if (currentPosition-- == 0) {
464                                 _nav.MoveTo (startPosition);
465                                 Current.MoveTo (_nav);
466                                 return true; // returns self.
467                         }
468                         _nav.MoveTo ((XPathNavigator) navigators [currentPosition]);
469                         Current.MoveTo (_nav);
470                         return true;
471                 }
472
473                 public override bool ReverseAxis {
474                         get { return true; }
475                 }
476
477                 public override int Count {
478                         get {
479                                 if (navigators == null)
480                                         CollectResults ();
481                                 return navigators.Count + 1;
482                         }
483                 }
484         }
485
486         internal class DescendantIterator : SimpleIterator
487         {
488                 private int _depth;
489                 private bool _finished;
490
491                 public DescendantIterator (BaseIterator iter) : base (iter) {}
492
493                 private DescendantIterator (DescendantIterator other) : base (other)
494                 {
495                         _depth = other._depth;
496                         _finished = other._finished;
497                 }
498
499                 public override XPathNodeIterator Clone () { return new DescendantIterator (this); }
500
501                 public override bool MoveNextCore ()
502                 {
503                         if (_finished)
504                                 return false;
505
506                         if (_nav.MoveToFirstChild ())
507                         {
508                                 _depth ++;
509                                 Current.MoveTo (_nav);
510                                 return true;
511                         }
512                         while (_depth != 0)
513                         {
514                                 if (_nav.MoveToNext ())
515                                 {
516                                         Current.MoveTo (_nav);
517                                         return true;
518                                 }
519                                 if (!_nav.MoveToParent ())      // should NEVER fail!
520                                         throw new XPathException ("Current node is removed while it should not be, or there are some bugs in the XPathNavigator implementation class: " + _nav.GetType ());
521                                 _depth --;
522                         }
523                         _finished = true;
524                         return false;
525                 }
526         }
527
528         internal class DescendantOrSelfIterator : SimpleIterator
529         {
530                 private int _depth;
531                 private bool _finished;
532
533                 public DescendantOrSelfIterator (BaseIterator iter) : base (iter) {}
534
535                 private DescendantOrSelfIterator (DescendantOrSelfIterator other) : base (other, true)
536                 {
537                         _depth = other._depth;
538                 }
539
540                 public override XPathNodeIterator Clone () { return new DescendantOrSelfIterator (this); }
541
542                 public override bool MoveNextCore ()
543                 {
544                         if (_finished)
545                                 return false;
546
547                         if (CurrentPosition == 0)
548                         {
549                                 // self
550                                 Current.MoveTo (_nav);
551                                 return true;
552                         }
553                         if (_nav.MoveToFirstChild ())
554                         {
555                                 _depth ++;
556                                 Current.MoveTo (_nav);
557                                 return true;
558                         }
559                         while (_depth != 0)
560                         {
561                                 if (_nav.MoveToNext ())
562                                 {
563                                         Current.MoveTo (_nav);
564                                         return true;
565                                 }
566                                 if (!_nav.MoveToParent ())      // should NEVER fail!
567                                         throw new XPathException ("Current node is removed while it should not be, or there are some bugs in the XPathNavigator implementation class: " + _nav.GetType ());
568                                 _depth --;
569                         }
570                         _finished = true;
571                         return false;
572                 }
573         }
574
575         internal class FollowingIterator : SimpleIterator
576         {
577                 private bool _finished = false;
578                 public FollowingIterator (BaseIterator iter) : base (iter) {}
579                 private FollowingIterator (FollowingIterator other) : base (other, true) {}
580                 public override XPathNodeIterator Clone () { return new FollowingIterator (this); }
581                 public override bool MoveNextCore ()
582                 {
583                         if (_finished)
584                                 return false;
585                         bool checkChildren = true;
586                         if (CurrentPosition == 0)
587                         {
588                                 checkChildren = false;
589                                 switch (_nav.NodeType) {
590                                 case XPathNodeType.Attribute:
591                                 case XPathNodeType.Namespace:
592                                         _nav.MoveToParent ();
593                                         checkChildren = true;
594                                         break;
595                                 default:
596                                         if (_nav.MoveToNext ())
597                                         {
598                                                 Current.MoveTo (_nav);
599                                                 return true;
600                                         } else {
601                                                 while (_nav.MoveToParent ()) {
602                                                         if (_nav.MoveToNext ()) {
603                                                                 Current.MoveTo (_nav);
604                                                                 return true;
605                                                         }
606                                                 }
607                                         }
608                                         break;
609                                 }
610                         }
611                         if (checkChildren)
612                         {
613                                 if (_nav.MoveToFirstChild ())
614                                 {
615                                         Current.MoveTo (_nav);
616                                         return true;
617                                 }
618                                 do
619                                 {
620                                         if (_nav.MoveToNext ())
621                                         {
622                                                 Current.MoveTo (_nav);
623                                                 return true;
624                                         }
625                                 }
626                                 while (_nav.MoveToParent ());
627                         }
628                         _finished = true;
629                         return false;
630                 }
631         }
632
633         internal class PrecedingIterator : SimpleIterator
634         {
635                 bool finished;
636                 bool started;
637                 XPathNavigator startPosition;
638
639                 public PrecedingIterator (BaseIterator iter) : base (iter) 
640                 {
641                         startPosition = iter.Current.Clone ();
642                 }
643                 private PrecedingIterator (PrecedingIterator other) : base (other, true) 
644                 {
645                         startPosition = other.startPosition;
646                         started = other.started;
647                         finished = other.finished;
648                 }
649                 public override XPathNodeIterator Clone () { return new PrecedingIterator (this); }
650                 public override bool MoveNextCore ()
651                 {
652                         if (finished)
653                                 return false;
654                         if (!started) {
655                                 started = true;
656                                 _nav.MoveToRoot ();
657                         }
658                         bool loop = true;
659                         while (loop) {
660                                 while (!_nav.MoveToFirstChild ()) {
661                                         while (!_nav.MoveToNext ()) {
662                                                 if (!_nav.MoveToParent ()) { // Should not finish, at least before startPosition.
663                                                         finished = true;
664                                                         return false;
665                                                 }
666                                         }
667                                         break;
668                                 }
669                                 if (_nav.IsDescendant (startPosition))
670                                         continue;
671                                 loop = false;
672                                 break;
673                         }
674                         if (_nav.ComparePosition (startPosition) != XmlNodeOrder.Before) {
675                                 // Note that if _nav contains only 1 node, it won't be Same.
676                                 finished = true;
677                                 return false;
678                         } else {
679                                 Current.MoveTo (_nav);
680                                 return true;
681                         }
682                 }
683                 public override bool ReverseAxis {
684                         get { return true; }
685                 }
686         }
687
688         internal class NamespaceIterator : SimpleIterator
689         {
690                 public NamespaceIterator (BaseIterator iter) : base (iter) {}
691                 private NamespaceIterator (NamespaceIterator other) : base (other, true) {}
692                 public override XPathNodeIterator Clone () { return new NamespaceIterator (this); }
693                 public override bool MoveNextCore ()
694                 {
695                         if (CurrentPosition == 0)
696                         {
697                                 if (_nav.MoveToFirstNamespace ())
698                                 {
699                                         Current.MoveTo (_nav);
700                                         return true;
701                                 }
702                         }
703                         else if (_nav.MoveToNextNamespace ())
704                         {
705                                 Current.MoveTo (_nav);
706                                 return true;
707                         }
708                         return false;
709                 }
710         }
711
712         internal class AttributeIterator : SimpleIterator
713         {
714                 public AttributeIterator (BaseIterator iter) : base (iter) {}
715                 private AttributeIterator (AttributeIterator other) : base (other, true) {}
716                 public override XPathNodeIterator Clone () { return new AttributeIterator (this); }
717                 public override bool MoveNextCore ()
718                 {
719                         if (CurrentPosition == 0)
720                         {
721                                 if (_nav.MoveToFirstAttribute ())
722                                 {
723                                         Current.MoveTo (_nav);
724                                         return true;
725                                 }
726                         }
727                         else if (_nav.MoveToNextAttribute ())
728                         {
729                                 Current.MoveTo (_nav);
730                                 return true;
731                         }
732                         return false;                   
733                 }
734         }
735
736         internal class AxisIterator : BaseIterator
737         {
738                 private SimpleIterator _iter;
739                 private NodeTest _test;
740                         
741                 //string name, ns;
742                 //XPathNodeType matchType;
743
744                 public AxisIterator (SimpleIterator iter, NodeTest test) : base (iter.NamespaceManager)
745                 {
746                         _iter = iter;
747                         _test = test;
748                         //test.GetInfo (out name, out ns, out matchType, NamespaceManager);
749 //                      if (name != null)
750 //                              name = Current.NameTable.Add (name);
751
752 //                      if (ns != null)
753 //                              ns = Current.NameTable.Add (ns);
754                 }
755
756                 private AxisIterator (AxisIterator other) : base (other)
757                 {
758                         _iter = (SimpleIterator) other._iter.Clone ();
759                         _test = other._test;
760                         //name = other.name;
761                         //ns = other.ns;
762                         //matchType = other.matchType;
763                 }
764                 public override XPathNodeIterator Clone () { return new AxisIterator (this); }
765
766                 public override bool MoveNextCore ()
767                 {
768                         while (_iter.MoveNext ())
769                         {
770                                 if (_test.Match (NamespaceManager, Current))
771                                 {
772                                         return true;
773                                 }
774                         }
775                         return false;
776                 }
777                 public override XPathNavigator Current { get { return _iter.Current; }}
778
779                 public override bool ReverseAxis {
780                         get { return _iter.ReverseAxis; }
781                 }
782         }
783
784         internal class SimpleSlashIterator : BaseIterator
785         {
786                 private NodeSet _expr;
787                 private BaseIterator _left, _right;
788                 private XPathNavigator _current;
789
790                 public SimpleSlashIterator (BaseIterator left, NodeSet expr)
791                         : base (left.NamespaceManager)
792                 {
793                         this._left = left;
794                         this._expr = expr;
795                 }
796
797                 private SimpleSlashIterator (SimpleSlashIterator other)
798                         : base (other)
799                 {
800                         _expr = other._expr;
801                         _left = (BaseIterator) other._left.Clone ();
802                         if (other._right != null)
803                                 _right = (BaseIterator) other._right.Clone ();
804                 }
805
806                 public override XPathNodeIterator Clone () { return new SimpleSlashIterator (this); }
807
808                 public override bool MoveNextCore ()
809                 {
810                         while (_right == null || !_right.MoveNext ()) {
811                                 if (!_left.MoveNext ())
812                                         return false;
813                                 _right = _expr.EvaluateNodeSet (_left);
814                         }
815                         if (_current == null)
816                                 _current = _right.Current.Clone ();
817                         else
818                                 if (! _current.MoveTo (_right.Current) )
819                                         _current = _right.Current.Clone ();
820                         return true;
821                 }
822
823                 public override XPathNavigator Current {
824                         get { return _current; }
825                 }
826         }
827
828         internal class SlashIterator : BaseIterator
829         {
830                 private BaseIterator _iterLeft;
831                 private BaseIterator _iterRight;
832                 private NodeSet _expr;
833                 ArrayList _navStore;
834                 SortedList _iterList;
835                 bool _finished;
836                 BaseIterator _nextIterRight;
837
838                 public SlashIterator (BaseIterator iter, NodeSet expr, bool requireSorting) : base (iter.NamespaceManager)
839                 {
840                         _iterLeft = iter;
841                         _expr = expr;
842
843                         if (requireSorting)
844                                 CollectResults ();
845                 }
846
847                 private SlashIterator (SlashIterator other) : base (other)
848                 {
849                         _iterLeft = (BaseIterator) other._iterLeft.Clone ();
850                         if (other._iterRight != null)
851                                 _iterRight = (BaseIterator) other._iterRight.Clone ();
852                         _expr = other._expr;
853                         if (other._iterList != null)
854                                 _iterList = (SortedList) other._iterList.Clone ();
855                         if (other._navStore != null)
856                                 _navStore = (ArrayList) other._navStore.Clone ();
857                         _finished = other._finished;
858                         if (other._nextIterRight != null)
859                                 _nextIterRight = (BaseIterator) other._nextIterRight.Clone ();
860                 }
861                 public override XPathNodeIterator Clone () { return new SlashIterator (this); }
862
863                 public override bool MoveNextCore ()
864                 {
865                         if (_finished)
866                                 return false;
867                         if (_navStore != null) {
868                                 // Which requires sorting::
869                                 if (_navStore.Count < CurrentPosition + 1) {
870                                         _finished = true;
871                                         return false;
872                                 }
873                                 while (_navStore.Count > CurrentPosition + 1) {
874                                         if (((XPathNavigator) _navStore [CurrentPosition + 1]).IsSamePosition (
875                                                 (XPathNavigator) _navStore [CurrentPosition]))
876                                                 _navStore.RemoveAt (CurrentPosition + 1);
877                                         else
878                                                 break;
879                                 }
880
881                                 return true;
882                         }
883                         // Which does not require sorting::
884                         
885                         if (_iterRight == null) { // First time
886                                 if (!_iterLeft.MoveNext ())
887                                         return false;
888                                 _iterRight = _expr.EvaluateNodeSet (_iterLeft);
889                                 _iterList = new SortedList (XPathIteratorComparer.Instance);
890                         }
891
892                         while (true) {
893                                 while (!_iterRight.MoveNext ()) {
894                                         if (_iterList.Count > 0) {
895                                                 int last = _iterList.Count - 1;
896                                                 _iterRight = (BaseIterator) _iterList.GetByIndex (last);
897                                                 _iterList.RemoveAt (last);
898                                                 break;
899                                         } else if (_nextIterRight != null) {
900                                                 _iterRight = _nextIterRight;
901                                                 _nextIterRight = null;
902                                                 break;
903                                         } else if (!_iterLeft.MoveNext ()) {
904                                                 _finished = true;
905                                                 return false;
906                                         }
907                                         else
908                                                 _iterRight = _expr.EvaluateNodeSet (_iterLeft);
909                                 }
910                                 bool loop = true;
911                                 while (loop) {
912                                         loop = false;
913                                         if (_nextIterRight == null) {
914                                                 bool noMoreNext = false;
915                                                 while (_nextIterRight == null || !_nextIterRight.MoveNext ()) {
916                                                         if(_iterLeft.MoveNext ())
917                                                                 _nextIterRight = _expr.EvaluateNodeSet (_iterLeft);
918                                                         else {
919                                                                 noMoreNext = true;
920                                                                 break;
921                                                         }
922                                                 }
923                                                 if (noMoreNext)
924                                                         _nextIterRight = null; // FIXME: More efficient code. Maybe making noMoreNext class scope would be better.
925                                         }
926                                         if (_nextIterRight != null) {
927                                                 switch (_iterRight.Current.ComparePosition (_nextIterRight.Current)) {
928                                                 case XmlNodeOrder.After:
929                                                         _iterList [_iterRight] = _iterRight;
930                                                         _iterRight = _nextIterRight;
931                                                         _nextIterRight = null;
932                                                         loop = true;
933                                                         break;
934                                                 case XmlNodeOrder.Same:
935                                                         if (!_nextIterRight.MoveNext ())
936                                                                 _nextIterRight = null;
937
938                                                         else {
939                                                                 int last = _iterList.Count;
940                                                                 _iterList [_nextIterRight] = _nextIterRight;
941                                                                 if (last != _iterList.Count) {
942                                                                         _nextIterRight = (BaseIterator) _iterList.GetByIndex (last);
943                                                                         _iterList.RemoveAt (last);
944                                                                 }
945                                                         }
946
947                                                         loop = true;
948                                                         break;
949                                                 }
950                                         }
951                                 }
952                                 return true;
953                         }
954                 }
955
956                 private void CollectResults ()
957                 {
958                         _navStore = new ArrayList ();
959                         while (true) {
960                                 while (_iterRight == null || !_iterRight.MoveNext ()) {
961                                         if (!_iterLeft.MoveNext ()) {
962                                                 _navStore.Sort (XPathNavigatorComparer.Instance);
963                                                 return;
964                                         }
965                                         _iterRight = _expr.EvaluateNodeSet (_iterLeft);
966                                 }
967                                 XPathNavigator nav = _iterRight.Current;
968                                 _navStore.Add (nav.Clone ());
969                         }
970                 }
971
972                 public override XPathNavigator Current { 
973                         get {
974                                 if (CurrentPosition <= 0) return null;
975                                 if (_navStore != null) {
976                                         return (XPathNavigator) _navStore [CurrentPosition - 1];
977                                 } else {
978                                         return _iterRight.Current;
979                                 }
980                         }
981                 }
982
983                 public override int Count { get { return _navStore == null ? base.Count : _navStore.Count; } }
984         }
985
986         internal class PredicateIterator : BaseIterator
987         {
988                 private BaseIterator _iter;
989                 private Expression _pred;
990                 private XPathResultType resType;
991                 private bool finished;
992
993                 public PredicateIterator (BaseIterator iter, Expression pred) : base (iter.NamespaceManager)
994                 {
995                         _iter = iter;
996                         _pred = pred;
997                         resType = pred.GetReturnType (iter);
998                 }
999
1000                 private PredicateIterator (PredicateIterator other) : base (other)
1001                 {
1002                         _iter = (BaseIterator) other._iter.Clone ();
1003                         _pred = other._pred;
1004                         resType = other.resType;
1005                         finished = other.finished;
1006                 }
1007                 public override XPathNodeIterator Clone () { return new PredicateIterator (this); }
1008
1009                 public override bool MoveNextCore ()
1010                 {
1011                         if (finished)
1012                                 return false;
1013                         while (_iter.MoveNext ())
1014                         {
1015                                 switch (resType) {
1016                                         case XPathResultType.Number:
1017                                                 if (_pred.EvaluateNumber (_iter) != _iter.ComparablePosition)
1018                                                         continue;
1019                                                 finished = true;
1020                                                 break;
1021                                         case XPathResultType.Any: {
1022                                                 object result = _pred.Evaluate (_iter);
1023                                                 if (result is double)
1024                                                 {
1025                                                         if ((double) result != _iter.ComparablePosition)
1026                                                                 continue;
1027                                                         finished = true;
1028                                                 }
1029                                                 else if (!XPathFunctions.ToBoolean (result))
1030                                                         continue;
1031                                         }
1032                                                 break;
1033                                         default:
1034                                                 if (!_pred.EvaluateBoolean (_iter))
1035                                                         continue;
1036                                                 break;
1037                                 }
1038
1039                                 return true;
1040                         }
1041                         return false;
1042                 }
1043                 public override XPathNavigator Current { get { return _iter.Current; }}
1044                 public override bool ReverseAxis {
1045                         get { return _iter.ReverseAxis; }
1046                 }
1047         }
1048
1049         internal class ListIterator : BaseIterator
1050         {
1051                 private IList _list;
1052
1053                 public ListIterator (BaseIterator iter, IList list) : base (iter.NamespaceManager)
1054                 {
1055                         _list = list;
1056                 }
1057                 
1058                 public ListIterator (IList list, NSResolver nsm) : base (nsm)
1059                 {
1060                         _list = list;
1061                 }
1062
1063                 private ListIterator (ListIterator other) : base (other)
1064                 {
1065                         _list = other._list;
1066                 }
1067                 public override XPathNodeIterator Clone () { return new ListIterator (this); }
1068
1069                 public override bool MoveNextCore ()
1070                 {
1071                         if (CurrentPosition >= _list.Count)
1072                                 return false;
1073                         return true;
1074                 }
1075                 public override XPathNavigator Current {
1076                         get {
1077                                 if (_list.Count == 0)
1078                                         return null;
1079                                 return (XPathNavigator) _list [CurrentPosition - 1]; 
1080                         }
1081                 }
1082
1083                 public override int Count { get { return _list.Count; } }
1084         }
1085
1086         
1087         internal class UnionIterator : BaseIterator
1088         {
1089                 private BaseIterator _left, _right;
1090                 private bool keepLeft;
1091                 private bool keepRight;
1092                 XPathNavigator _current;
1093
1094                 public UnionIterator (BaseIterator iter, BaseIterator left, BaseIterator right) : base (iter.NamespaceManager)
1095                 {
1096                         _left = left;
1097                         _right = right;
1098                 }
1099
1100                 private UnionIterator (UnionIterator other) : base (other)
1101                 {
1102                         _left = (BaseIterator) other._left.Clone ();
1103                         _right = (BaseIterator) other._right.Clone ();
1104                         keepLeft = other.keepLeft;
1105                         keepRight = other.keepRight;
1106                         if (other._current != null)
1107                                 _current = other._current.Clone ();
1108                 }
1109                 public override XPathNodeIterator Clone () { return new UnionIterator (this); }
1110
1111                 public override bool MoveNextCore ()
1112                 {
1113                         if (!keepLeft)
1114                                 keepLeft = _left.MoveNext ();
1115                         if (!keepRight)
1116                                 keepRight = _right.MoveNext ();
1117
1118                         if (!keepLeft && !keepRight)
1119                                 return false;
1120
1121                         if (!keepRight) {
1122                                 keepLeft = false;
1123                                 SetCurrent (_left);
1124                                 return true;
1125                         } else if (!keepLeft) {
1126                                 keepRight = false;
1127                                 SetCurrent (_right);
1128                                 return true;
1129                         }
1130
1131                         switch (_left.Current.ComparePosition (_right.Current)) {
1132                         case XmlNodeOrder.Same:
1133                                 // consume both. i.e. don't output duplicate result.
1134                                 keepLeft = keepRight = false;
1135                                 SetCurrent (_right);
1136                                 return true;
1137                         case XmlNodeOrder.Before:
1138                         case XmlNodeOrder.Unknown: // Maybe happen because of "document(a) | document(b)"
1139                                 keepLeft = false;
1140                                 SetCurrent (_left);
1141                                 return true;
1142                         case XmlNodeOrder.After:
1143                                 keepRight = false;
1144                                 SetCurrent (_right);
1145                                 return true;
1146                         default:
1147                                 throw new InvalidOperationException ("Should not happen.");
1148                         }
1149                 }
1150
1151                 private void SetCurrent (XPathNodeIterator iter)
1152                 {
1153                         if (_current == null)
1154                                 _current = iter.Current.Clone ();
1155                         else
1156                                 if (! _current.MoveTo (iter.Current) )
1157                                         _current = iter.Current.Clone ();
1158                 }
1159
1160                 public override XPathNavigator Current
1161                 {
1162                         get { return _current; }
1163                 }
1164         }
1165
1166         internal class OrderedIterator : BaseIterator
1167         {
1168                 BaseIterator iter;
1169                 ArrayList list;
1170                 int index = -1;
1171
1172                 public OrderedIterator (BaseIterator iter)
1173                         : base (iter.NamespaceManager)
1174                 {
1175 //                      if (iter.Ordered)
1176                         if (false)
1177                                 this.iter = iter;
1178                         else {
1179                                 list = new ArrayList ();
1180                                 while (iter.MoveNext ())
1181                                         list.Add (iter.Current);
1182                                 list.Sort (XPathNavigatorComparer.Instance);
1183                         }
1184                 }
1185
1186                 private OrderedIterator (OrderedIterator other, bool dummy)
1187                         : base (other)
1188                 {
1189                         if (other.iter != null)
1190                                 iter = (BaseIterator) other.iter.Clone ();
1191                         list = other.list;
1192                         index = other.index;
1193                 }
1194
1195                 public override XPathNodeIterator Clone ()
1196                 {
1197                         return new OrderedIterator (this);
1198                 }
1199
1200                 public override bool MoveNextCore ()
1201                 {
1202                         if (iter != null)
1203                                 return iter.MoveNext ();
1204                         else if (index++ < list.Count)
1205                                 return true;
1206                         index--;
1207                         return false;
1208                 }
1209
1210                 public override XPathNavigator Current {
1211                         get { return iter != null ? iter.Current : index < 0 ? null : (XPathNavigator) list [index]; }
1212                 }
1213         }
1214 }