1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 
5 using System.Xml.XPath;
6 
7 namespace MS.Internal.Xml.XPath
8 {
9     internal sealed class FollowingQuery : BaseAxisQuery
10     {
11         private XPathNavigator _input;
12         private XPathNodeIterator _iterator;
13 
FollowingQuery(Query qyInput, string name, string prefix, XPathNodeType typeTest)14         public FollowingQuery(Query qyInput, string name, string prefix, XPathNodeType typeTest) : base(qyInput, name, prefix, typeTest) { }
FollowingQuery(FollowingQuery other)15         private FollowingQuery(FollowingQuery other) : base(other)
16         {
17             _input = Clone(other._input);
18             _iterator = Clone(other._iterator);
19         }
20 
Reset()21         public override void Reset()
22         {
23             _iterator = null;
24             base.Reset();
25         }
26 
Advance()27         public override XPathNavigator Advance()
28         {
29             if (_iterator == null)
30             {
31                 _input = qyInput.Advance();
32                 if (_input == null)
33                 {
34                     return null;
35                 }
36 
37                 XPathNavigator prev;
38                 do
39                 {
40                     prev = _input.Clone();
41                     _input = qyInput.Advance();
42                 } while (prev.IsDescendant(_input));
43                 _input = prev;
44 
45                 _iterator = XPathEmptyIterator.Instance;
46             }
47 
48             while (!_iterator.MoveNext())
49             {
50                 bool matchSelf;
51                 if (_input.NodeType == XPathNodeType.Attribute || _input.NodeType == XPathNodeType.Namespace)
52                 {
53                     _input.MoveToParent();
54                     matchSelf = false;
55                 }
56                 else
57                 {
58                     while (!_input.MoveToNext())
59                     {
60                         if (!_input.MoveToParent())
61                         {
62                             return null;
63                         }
64                     }
65                     matchSelf = true;
66                 }
67                 if (NameTest)
68                 {
69                     _iterator = _input.SelectDescendants(Name, Namespace, matchSelf);
70                 }
71                 else
72                 {
73                     _iterator = _input.SelectDescendants(TypeTest, matchSelf);
74                 }
75             }
76             position++;
77             currentNode = _iterator.Current;
78             return currentNode;
79         }
80 
Clone()81         public override XPathNodeIterator Clone() { return new FollowingQuery(this); }
82     }
83 }
84