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