/// <summary>
/// Position this iterator to the next content or sibling node. Return IteratorResult.NoMoreNodes if there are
/// no more content or sibling nodes. Return IteratorResult.NeedInputNode if the next input node needs to be
/// fetched first. Return IteratorResult.HaveCurrent if the Current property is set to the next node in the
/// iteration.
/// </summary>
internal IteratorResult MoveNext(XPathNavigator input, bool isContent)
{
switch (_state)
{
case IteratorState.NeedCurrent:
// If there are no more input nodes, then iteration is complete
if (input == null)
{
return(IteratorResult.NoMoreNodes);
}
// Save the input node as the current node
_navCurrent = XmlQueryRuntime.SyncToNavigator(_navCurrent, input);
// If matching child or sibling is found, then we have a current node
if (isContent ? _filter.MoveToContent(_navCurrent) :
_filter.MoveToFollowingSibling(_navCurrent))
{
_state = IteratorState.HaveCurrentNeedNext;
}
return(IteratorResult.NeedInputNode);
case IteratorState.HaveCurrentNeedNext:
if (input == null)
{
// There are no more input nodes, so enter HaveCurrentNoNext state and return Current
_state = IteratorState.HaveCurrentNoNext;
return(IteratorResult.HaveCurrentNode);
}
// Save the input node as the next node
_navNext = XmlQueryRuntime.SyncToNavigator(_navNext, input);
// If matching child or sibling is found,
if (isContent ? _filter.MoveToContent(_navNext) :
_filter.MoveToFollowingSibling(_navNext))
{
// Then compare position of current and next nodes
_state = IteratorState.HaveCurrentHaveNext;
return(DocOrderMerge());
}
// Input node does not result in matching child or sibling, so get next input node
return(IteratorResult.NeedInputNode);
case IteratorState.HaveCurrentNoNext:
case IteratorState.HaveCurrentHaveNext:
// If the current node has no more matching siblings,
if (isContent ? !_filter.MoveToNextContent(_navCurrent) :
!_filter.MoveToFollowingSibling(_navCurrent))
{
if (_navStack.IsEmpty)
{
if (_state == IteratorState.HaveCurrentNoNext)
{
// No more input nodes, so iteration is complete
return(IteratorResult.NoMoreNodes);
}
// Make navNext the new current node and fetch a new navNext
_navCurrent = XmlQueryRuntime.SyncToNavigator(_navCurrent, _navNext);
_state = IteratorState.HaveCurrentNeedNext;
return(IteratorResult.NeedInputNode);
}
// Pop new current node from the stack
_navCurrent = _navStack.Pop();
}
// If there is no next node, then no need to call DocOrderMerge; just return the current node
if (_state == IteratorState.HaveCurrentNoNext)
{
return(IteratorResult.HaveCurrentNode);
}
// Compare positions of current and next nodes
return(DocOrderMerge());
}
Debug.Assert(false, "Invalid IteratorState " + _state);
return(IteratorResult.NoMoreNodes);
}