} // IteratorState: Create. public bool MoveNext() { try { switch (this.State) { case IteratorState.Start: this.start(); this.State = IteratorState.MoveNext; // IteratorState: Start => MoveNext. goto case IteratorState.MoveNext; case IteratorState.MoveNext: if (this.moveNext()) { this.Current = this.getCurrent(); return(true); // IteratorState: MoveNext => MoveNext. } this.State = IteratorState.End; // IteratorState: MoveNext => End. this.dispose(); this.end(); return(false); default: return(false); } } catch // IteratorState: Start, MoveNext, End => End. { this.State = IteratorState.Error; this.Dispose(); throw; } }
// TODO: Ensure that the state methods work private bool moveOnOnlineState() { m_currentIndex -= 1; if (m_currentIndex < 0) { saveMessages(new List <FacebookMessage>(m_messageList)); m_saveCount += m_messageList.Count; getNextOnlineMessages(); m_currentIndex = m_messageList.Count - 1; } else if (m_cachedMessageList.Count > 0 && m_messageList[m_currentIndex] == m_cachedMessageList[m_cacheIndex]) { if (m_currentIndex != m_messageList.Count - 1) { m_messageList.RemoveRange(0, m_currentIndex + 1); saveMessages(new List <FacebookMessage>(m_messageList)); } m_state = IteratorState.CacheQuery; m_messageList = m_cachedMessageList; m_currentIndex = m_cacheIndex; } if (m_messageList == null || m_messageList.Count == 0) { return(false); } return(true); }
/// <summary> /// Position this iterator to the next node in the union. /// </summary> public SetIteratorResult MoveNext(XPathNavigator nestedNavigator) { switch (_state) { case IteratorState.InitLeft: // Fetched node from left iterator, now get initial node from right iterator _navLeft = nestedNavigator; _state = IteratorState.NeedRight; return(SetIteratorResult.InitRightIterator); case IteratorState.NeedLeft: _navLeft = nestedNavigator; break; case IteratorState.NeedRight: _navRight = nestedNavigator; break; case IteratorState.NeedLeftAndRight: // After fetching left node, still need right node _navLeft = nestedNavigator; _state = IteratorState.NeedRight; return(SetIteratorResult.NeedRightNode); case IteratorState.HaveCurrent: // Just returned left node as current, so fetch new left node Debug.Assert(nestedNavigator == null, "null is passed to MoveNext after IteratorState.HaveCurrent has been returned."); _state = IteratorState.NeedLeft; return(SetIteratorResult.NeedLeftNode); } if (_navLeft == null) { // If navLeft is null, then difference operation is complete return(SetIteratorResult.NoMoreNodes); } else if (_navRight != null) { int order = _runtime.ComparePosition(_navLeft, _navRight); // If navLeft is positioned to same node as navRight, if (order == 0) { // Skip navLeft and navRight _state = IteratorState.NeedLeftAndRight; return(SetIteratorResult.NeedLeftNode); } // If navLeft is after navRight in document order, then skip navRight if (order > 0) { _state = IteratorState.NeedRight; return(SetIteratorResult.NeedRightNode); } } // Return navLeft _state = IteratorState.HaveCurrent; return(SetIteratorResult.HaveCurrentNode); }
public bool MoveNext() { try { switch (this.State) { case IteratorState.Start: this.start?.Invoke(); this.State = IteratorState.MoveNext; // IteratorState: Start => MoveNext. goto case IteratorState.MoveNext; case IteratorState.MoveNext: if (this.moveNext?.Invoke() ?? false) { this.Current = this.getCurrent != null?this.getCurrent() : default; return(true); // IteratorState: MoveNext => MoveNext. } this.State = IteratorState.End; // IteratorState: MoveNext => End. this.dispose?.Invoke(); this.end?.Invoke(); break; } return(false); } catch { this.State = IteratorState.Error; // IteratorState: Start, MoveNext, End => Error. this.Dispose(); throw; } }
/// <summary> /// Position this iterator to the next following node. Return false if there are no more following nodes, /// or if the end node has been reached. Return true if the Current property is set to the next node in /// the iteration. /// </summary> public bool MoveNext() { switch (this.state) { case IteratorState.HaveCurrent: this.state = IteratorState.NeedCurrent; return(true); case IteratorState.NeedCurrent: // Move to next following node which matches if (!this.filter.MoveToFollowing(this.navCurrent, this.navEnd)) { // No more nodes unless ending node matches if (filter.IsFiltered(this.navEnd)) { this.state = IteratorState.NoNext; return(false); } this.navCurrent.MoveTo(this.navEnd); this.state = IteratorState.NoNext; } return(true); case IteratorState.HaveCurrentNoNext: this.state = IteratorState.NoNext; return(true); } Debug.Assert(this.state == IteratorState.NoNext, "Illegal state: " + this.state); return(false); }
private bool moveOnCacheState() { m_currentIndex--; m_cacheIndex--; if (m_currentIndex < 0) { // This should only occur if the cached messages contain all messages up to the initial messsage return(false); } if (m_queryLinks.ContainsKey(m_messageList[m_currentIndex].id)) { lock (this) { m_queryLinks = CachedMessageManager.Manager.getNextURLs(m_conversationID); if (m_queryLinks.ContainsKey(m_messageList[m_currentIndex].id)) { m_state = IteratorState.RemnantQuery; FBQueryManager.Manager.setNextURL(m_conversationID, m_queryLinks[m_messageList[m_currentIndex].id]); // TODO: Check transition correctness from using cached messages vs. online facebook servers m_cacheIndex = m_currentIndex; m_messageList = new List <FacebookMessage>(); m_messageList.Add(m_cachedMessageList[m_currentIndex]); m_currentIndex = 0; } else { FacebookMessage message = m_cachedMessageList[m_cacheIndex]; m_messageList = m_cachedMessageList = CachedMessageManager.Manager.getMessages(m_conversationID); m_currentIndex = m_cacheIndex = m_cachedMessageList.BinarySearch(message); } } } return(true); }
/// <summary> /// Position this iterator to the next node in the union. /// </summary> public SetIteratorResult MoveNext(XPathNavigator nestedNavigator) { switch (this.state) { case IteratorState.InitLeft: // Fetched node from left iterator, now get initial node from right iterator this.navOther = nestedNavigator; this.state = IteratorState.NeedRight; return SetIteratorResult.InitRightIterator; case IteratorState.NeedLeft: this.navCurr = nestedNavigator; this.state = IteratorState.LeftIsCurrent; break; case IteratorState.NeedRight: this.navCurr = nestedNavigator; this.state = IteratorState.RightIsCurrent; break; case IteratorState.LeftIsCurrent: // Just returned left node as current, so get new left this.state = IteratorState.NeedLeft; return SetIteratorResult.NeedLeftNode; case IteratorState.RightIsCurrent: // Just returned right node as current, so get new right this.state = IteratorState.NeedRight; return SetIteratorResult.NeedRightNode; } // Merge left and right nodes if (this.navCurr == null) { // If both navCurr and navOther are null, then iteration is complete if (this.navOther == null) return SetIteratorResult.NoMoreNodes; Swap(); } else if (this.navOther != null) { int order = this.runtime.ComparePosition(this.navOther, this.navCurr); // If navCurr is positioned to same node as navOther, if (order == 0) { // Skip navCurr, since it is a duplicate if (this.state == IteratorState.LeftIsCurrent) { this.state = IteratorState.NeedLeft; return SetIteratorResult.NeedLeftNode; } this.state = IteratorState.NeedRight; return SetIteratorResult.NeedRightNode; } // If navOther is before navCurr in document order, then swap navCurr with navOther if (order < 0) Swap(); } // Return navCurr return SetIteratorResult.HaveCurrentNode; }
/// <summary> /// If the context node-set returns a node that is contained in the subtree of the previous node, /// then returning children of each node in "natural" order may not correspond to document order. /// Therefore, in order to guarantee document order, keep a stack in order to push the sibling of /// ancestor nodes. These siblings will not be returned until all of the descendants' children are /// returned first. /// </summary> private IteratorResult DocOrderMerge() { XmlNodeOrder cmp; Debug.Assert(_state == IteratorState.HaveCurrentHaveNext); // Compare location of navCurrent with navNext cmp = _navCurrent.ComparePosition(_navNext); // If navCurrent is before navNext in document order, // If cmp = XmlNodeOrder.Unknown, then navCurrent is before navNext (since input is is doc order) if (cmp == XmlNodeOrder.Before || cmp == XmlNodeOrder.Unknown) { // Then navCurrent can be returned (it is guaranteed to be first in document order) return(IteratorResult.HaveCurrentNode); } // If navCurrent is after navNext in document order, then delay returning navCurrent // Otherwise, discard navNext since it is positioned to the same node as navCurrent if (cmp == XmlNodeOrder.After) { _navStack.Push(_navCurrent); _navCurrent = _navNext; _navNext = null; } // Need next input node _state = IteratorState.HaveCurrentNeedNext; return(IteratorResult.NeedInputNode); }
public bool MoveNext() { switch (_state) { case IteratorState.HaveCurrent: _state = IteratorState.NeedCurrent; return(true); case IteratorState.NeedCurrent: // Move to next following node which matches if (!_filter.MoveToFollowing(_navCurrent, _navEnd)) { // No more nodes unless ending node matches if (_filter.IsFiltered(_navEnd)) { _state = IteratorState.NoNext; return(false); } _navCurrent.MoveTo(_navEnd); _state = IteratorState.NoNext; } return(true); case IteratorState.HaveCurrentNoNext: _state = IteratorState.NoNext; return(true); } Debug.Assert(_state == IteratorState.NoNext, "Illegal state: " + _state); return(false); }
private static void Cleanup(IteratorState[] iterators) { if (iterators != null) { List <Exception> errors = null; for (int i = 0; i < iterators.Length; i++) { if (iterators[i].Active && iterators[i].Iterator != null) { try { var iterator = iterators[i].Iterator; iterators[i] = new IteratorState(); iterator.Dispose(); } catch (Exception e) { (errors ?? (errors = new List <Exception>())).Add(e); } } } if (errors != null) { throw new AggregateException(errors); } } }
private void Exclude(IteratorState state) { if (!_withThis) state.This = null; if (!_withCurrent) state.Current = null; }
/// <summary> /// Position this iterator to the next node in the union. /// </summary> public SetIteratorResult MoveNext(XPathNavigator nestedNavigator) { int order; switch (_state) { case IteratorState.InitLeft: // Fetched node from left iterator, now get initial node from right iterator _navLeft = nestedNavigator; _state = IteratorState.NeedRight; return(SetIteratorResult.InitRightIterator); case IteratorState.NeedLeft: _navLeft = nestedNavigator; break; case IteratorState.NeedRight: _navRight = nestedNavigator; break; case IteratorState.NeedLeftAndRight: // After fetching left node, still need right node _navLeft = nestedNavigator; _state = IteratorState.NeedRight; return(SetIteratorResult.NeedRightNode); case IteratorState.HaveCurrent: // Just returned left node as current, so fetch new left and right nodes Debug.Assert(nestedNavigator == null, "null is passed to MoveNext after IteratorState.HaveCurrent has been returned."); _state = IteratorState.NeedLeftAndRight; return(SetIteratorResult.NeedLeftNode); } if (_navLeft == null || _navRight == null) { // No more nodes from either left or right iterator (or both), so iteration is complete return(SetIteratorResult.NoMoreNodes); } // Intersect left and right sets order = _runtime.ComparePosition(_navLeft, _navRight); if (order < 0) { // If navLeft is positioned to a node that is before navRight, skip left node _state = IteratorState.NeedLeft; return(SetIteratorResult.NeedLeftNode); } else if (order > 0) { // If navLeft is positioned to a node that is after navRight, so skip right node _state = IteratorState.NeedRight; return(SetIteratorResult.NeedRightNode); } // Otherwise, navLeft is positioned to the same node as navRight, so found one item in the intersection _state = IteratorState.HaveCurrent; return(SetIteratorResult.HaveCurrentNode); }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { IteratorState state = _isc.ToState((IEnumerator)value); Exclude(state); serializer.Serialize(writer, state); }
/// <summary> /// 执行与释放或重置非托管资源相关的应用程序定义的任务。 /// </summary> /// <param name="disposing">是否释放托管资源。</param> protected virtual void Dispose(bool disposing) { if (this.state == IteratorState.Disposed || !disposing) { return; } this.state = IteratorState.Disposed; this.Current = default(T); }
private void Exclude(IteratorState state) { if (!_withThis) { state.This = null; } if (!_withCurrent) { state.Current = null; } }
// TODO: Consider removing this state... private bool moveOnRemnantState() { m_currentIndex -= 1; if (m_currentIndex < 0) { getNextOnlineMessages(); m_currentIndex = m_messageList.Count - 1; m_state = IteratorState.OnlineQuery; return(m_messageList.Count > 0); } return(true); }
/// <summary> /// Returns an enumerator that iterates through the collection. /// </summary> /// <returns> /// A <see cref="T:System.Collections.Generic.IEnumerator`1" /> that can be used to iterate through the collection. /// </returns> public IEnumerator <TSource> GetEnumerator( ) { if ((_threadId == Thread.CurrentThread.ManagedThreadId) && (State == IteratorState.Uninitialized)) { State = IteratorState.Initialized; return(this); } Iterator <TSource> iterator = Clone( ); iterator.State = IteratorState.Initialized; return(iterator); }
public void Dispose() { if (this.State == IteratorState.Error || this.State == IteratorState.MoveNext) { try { } finally { // Unexecuted finally blocks are executed before the thread is aborted. this.State = IteratorState.End; // IteratorState: Error => End. this.dispose?.Invoke(); } } }
/// <summary> /// 返回一个循环访问集合的枚举器。 /// </summary> /// <returns>可用于循环访问集合的 <see cref="IEnumerator{T}"/>。</returns> public IEnumerator <T> GetEnumerator() { if (this.threadId == Thread.CurrentThread.ManagedThreadId && this.state == IteratorState.Default) { this.state = IteratorState.Ready; return(this); } IteratorBase <T> iterator = Clone(); Debug.Assert(iterator != null); iterator.state = IteratorState.Ready; return(iterator); }
public void Dispose() { if (this.state == IteratorState.Error || this.state == IteratorState.MoveNext) { try { } finally { // https://msdn.microsoft.com/en-us/library/ty8d3wta.aspx // Unexecuted finally blocks are executed before the thread is aborted. this.state = IteratorState.End; // IteratorState: Error => End. this.dispose(this.data); } } }
protected override async ValueTask <bool> OnFirstAsync() { if (m_remaining != null && m_remaining.Value < 0) { // empty list ?? return(await Completed()); } // even if the caller only wants the first, we will probably need to read more than that... var mode = m_mode; if (mode == AsyncIterationHint.Head) { mode = AsyncIterationHint.Iterator; } var sources = m_sources.ToArray(); IteratorState[]? iterators = new IteratorState[sources.Length]; try { // start all the iterators for (int i = 0; i < sources.Length; i++) { var state = new IteratorState { Active = true, Iterator = sources[i] is IConfigurableAsyncEnumerable <TSource> configurable?configurable.GetAsyncEnumerator(m_ct, mode) : sources[i].GetAsyncEnumerator(m_ct) }; state.Next = state.Iterator.MoveNextAsync(); iterators[i] = state; } m_remaining = m_limit; return(iterators.Length > 0); } catch (Exception) { // dispose already opened iterators var tmp = iterators; iterators = null; try { await Cleanup(tmp); } catch { } throw; } finally { m_iterators = iterators; } }
protected override Task <bool> OnFirstAsync() { if (m_remaining != null && m_remaining.Value < 0) { // empty list ?? return(TaskHelpers.FromResult(Completed())); } // even if the caller only wants the first, we will probably need to read more than that... var mode = m_mode; if (mode == AsyncIterationHint.Head) { mode = AsyncIterationHint.Iterator; } var sources = m_sources.ToArray(); var iterators = new IteratorState[sources.Length]; try { // start all the iterators for (int i = 0; i < sources.Length; i++) { var state = new IteratorState { Active = true, Iterator = sources[i].GetEnumerator(m_ct, mode) }; state.Next = state.Iterator.MoveNextAsync(); iterators[i] = state; } m_remaining = m_limit; return(TaskHelpers.FromResult(iterators.Length > 0)); } catch (Exception e) { // dispose already opened iterators var tmp = iterators; iterators = null; try { Cleanup(tmp); } catch { } return(Task.FromException <bool>(e)); } finally { m_iterators = iterators; } }
public Iterator( IteratorState state = IteratorState.Create, Action start = null, Func <bool> moveNext = null, Func <T> getCurrent = null, Action dispose = null, Action end = null) { this.State = state; this.start = start ?? (() => { }); this.moveNext = moveNext ?? (() => false); this.getCurrent = getCurrent ?? (() => default(T)); this.dispose = dispose ?? (() => { }); this.end = end ?? (() => { }); }
/// <summary> /// Swap navCurr with navOther and invert state to reflect the change. /// </summary> private void Swap() { XPathNavigator navTemp = _navCurr; _navCurr = _navOther; _navOther = navTemp; if (_state == IteratorState.LeftIsCurrent) { _state = IteratorState.RightIsCurrent; } else { _state = IteratorState.LeftIsCurrent; } }
/// <summary> /// Swap navCurr with navOther and invert state to reflect the change. /// </summary> private void Swap() { XPathNavigator navTemp = this.navCurr; this.navCurr = this.navOther; this.navOther = navTemp; if (this.state == IteratorState.LeftIsCurrent) { this.state = IteratorState.RightIsCurrent; } else { this.state = IteratorState.LeftIsCurrent; } }
private void constructorHelper(string conversationID, bool saveMessages) { m_conversationID = conversationID; m_saveCount = 0; m_saveMessages = saveMessages; CachedMessageManager.Manager.addConversation(conversationID); m_cachedMessageList = CachedMessageManager.Manager.getMessages(conversationID); getNextOnlineMessages(); m_queryLinks = CachedMessageManager.Manager.getNextURLs(conversationID); m_currentIndex = m_messageList.Count; m_cacheIndex = m_cachedMessageList.Count - 1; m_state = IteratorState.OnlineQuery; }
public void Create(XPathNavigator start, XmlNavigatorFilter filter, XPathNavigator end) { // Save start node as current node and save ending node _navCurrent = XmlQueryRuntime.SyncToNavigator(_navCurrent, start); _navEnd = XmlQueryRuntime.SyncToNavigator(_navEnd, end); _filter = filter; if (start.IsSamePosition(end)) { // Start is end, so only return node if it is not filtered _state = !filter.IsFiltered(start) ? IteratorState.HaveCurrentNoNext : IteratorState.NoNext; } else { // Return nodes until end is reached _state = !filter.IsFiltered(start) ? IteratorState.HaveCurrent : IteratorState.NeedCurrent; } }
public void StaticYieldOnly() { var serializer = new IteratorStateConverter(); IEnumerator <int> iterator = SerializationCoroutines.StaticYieldOnly().GetEnumerator(); iterator.MoveNext(); IteratorState state1 = serializer.ToState(iterator); Assert.True((int)state1.Current == 1); iterator.MoveNext(); IteratorState state2 = serializer.ToState(iterator); Assert.True((int)state2.Current == 2); }
public IteratorResult MoveNext(XPathNavigator input) { if (_state != IteratorState.NeedDescendant) { if (input == null) { return(IteratorResult.NoMoreNodes); } // Descendants of the input node will be duplicates if the input node is in the subtree // of the previous root. if (_state != IteratorState.NoPrevious && _navRoot.IsDescendant(input)) { return(IteratorResult.NeedInputNode); } // Save input node as current node and end of input's tree in navEnd _navCurrent = XmlQueryRuntime.SyncToNavigator(_navCurrent, input); _navRoot = XmlQueryRuntime.SyncToNavigator(_navRoot, input); _navEnd = XmlQueryRuntime.SyncToNavigator(_navEnd, input); _navEnd.MoveToNonDescendant(); _state = IteratorState.NeedDescendant; // If self node matches, then return it if (_orSelf && !_filter.IsFiltered(input)) { return(IteratorResult.HaveCurrentNode); } } if (_filter.MoveToFollowing(_navCurrent, _navEnd)) { return(IteratorResult.HaveCurrentNode); } // No more descendants, so transition to NeedCurrent state and get the next input node _state = IteratorState.NeedCurrent; return(IteratorResult.NeedInputNode); }
public void StaticYieldWithVarAndArg() { var serializer = new IteratorStateConverter(); IEnumerator <int> iterator = SerializationCoroutines.StaticYieldWithVarAndArg(5).GetEnumerator(); iterator.MoveNext(); IteratorState state1 = serializer.ToState(iterator); Assert.True((int)state1.Current == 5); iterator.MoveNext(); IteratorState state2 = serializer.ToState(iterator); Assert.True((int)state2.Current == 15); var newIterator = (IEnumerator <int>)serializer.FromState(state2); Assert.True(newIterator.Current == 15); }
private IteratorResult MoveFailed() { XPathNavigator navTemp; Debug.Assert(_state == IteratorState.HaveCurrentHaveNext || _state == IteratorState.HaveCurrentNoNext); if (_state == IteratorState.HaveCurrentNoNext) { // No more nodes, so iteration is complete _state = IteratorState.NeedCandidateCurrent; return(IteratorResult.NoMoreNodes); } // Make next node the new candidate node _state = IteratorState.HaveCandidateCurrent; // Swap navigators in order to sometimes avoid creating clones navTemp = _navCurrent; _navCurrent = _navNext; _navNext = navTemp; return(IteratorResult.NeedInputNode); }
/// <summary> /// Position this iterator to the next descendant node. Return IteratorResult.NoMoreNodes if there are no more /// descendant nodes. Return IteratorResult.NeedInputNode if the next input node needs to be fetched. /// Return IteratorResult.HaveCurrent if the Current property is set to the next node in the iteration. /// </summary> public IteratorResult MoveNext(XPathNavigator input) { if (this.state != IteratorState.NeedDescendant) { if (input == null) return IteratorResult.NoMoreNodes; // Descendants of the input node will be duplicates if the input node is in the subtree // of the previous root. if (this.state != IteratorState.NoPrevious && this.navRoot.IsDescendant(input)) return IteratorResult.NeedInputNode; // Save input node as current node and end of input's tree in navEnd this.navCurrent = XmlQueryRuntime.SyncToNavigator(this.navCurrent, input); this.navRoot = XmlQueryRuntime.SyncToNavigator(this.navRoot, input); this.navEnd = XmlQueryRuntime.SyncToNavigator(this.navEnd, input); this.navEnd.MoveToNonDescendant(); this.state = IteratorState.NeedDescendant; // If self node matches, then return it if (this.orSelf && !this.filter.IsFiltered(input)) return IteratorResult.HaveCurrentNode; } if (this.filter.MoveToFollowing(this.navCurrent, this.navEnd)) return IteratorResult.HaveCurrentNode; // No more descendants, so transition to NeedCurrent state and get the next input node this.state = IteratorState.NeedCurrent; return IteratorResult.NeedInputNode; }
/// <summary> /// Position this iterator to the next following node. Return false if there are no more following nodes, /// or if the end node has been reached. Return true if the Current property is set to the next node in /// the iteration. /// </summary> public bool MoveNext() { switch (_state) { case IteratorState.HaveCurrent: _state = IteratorState.NeedCurrent; return true; case IteratorState.NeedCurrent: // Move to next following node which matches if (!_filter.MoveToFollowing(_navCurrent, _navEnd)) { // No more nodes unless ending node matches if (_filter.IsFiltered(_navEnd)) { _state = IteratorState.NoNext; return false; } _navCurrent.MoveTo(_navEnd); _state = IteratorState.NoNext; } return true; case IteratorState.HaveCurrentNoNext: _state = IteratorState.NoNext; return true; } Debug.Assert(_state == IteratorState.NoNext, "Illegal state: " + _state); return false; }
/// <summary> /// Initialize the DescendantIterator (merge multiple sets of descendant nodes in document order and remove duplicates). /// </summary> public void Create(XmlNavigatorFilter filter, bool orSelf) { _filter = filter; _state = IteratorState.NoPrevious; _orSelf = orSelf; }
/// <summary> /// Initialize the ContentMergeIterator (merge multiple sets of content nodes in document order and remove duplicates). /// </summary> public void Create(XmlNavigatorFilter filter) { this.filter = filter; this.navStack.Reset(); this.state = IteratorState.NeedCurrent; }
/// <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 (this.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 this.navCurrent = XmlQueryRuntime.SyncToNavigator(this.navCurrent, input); // If matching child or sibling is found, then we have a current node if (isContent ? this.filter.MoveToContent(this.navCurrent) : this.filter.MoveToFollowingSibling(this.navCurrent)) this.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 this.state = IteratorState.HaveCurrentNoNext; return IteratorResult.HaveCurrentNode; } // Save the input node as the next node this.navNext = XmlQueryRuntime.SyncToNavigator(this.navNext, input); // If matching child or sibling is found, if (isContent ? this.filter.MoveToContent(this.navNext) : this.filter.MoveToFollowingSibling(this.navNext)) { // Then compare position of current and next nodes this.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 ? !this.filter.MoveToNextContent(this.navCurrent) : !this.filter.MoveToFollowingSibling(this.navCurrent)) { if (this.navStack.IsEmpty) { if (this.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 this.navCurrent = XmlQueryRuntime.SyncToNavigator(this.navCurrent, this.navNext); this.state = IteratorState.HaveCurrentNeedNext; return IteratorResult.NeedInputNode; } // Pop new current node from the stack this.navCurrent = this.navStack.Pop(); } // If there is no next node, then no need to call DocOrderMerge; just return the current node if (this.state == IteratorState.HaveCurrentNoNext) return IteratorResult.HaveCurrentNode; // Compare positions of current and next nodes return DocOrderMerge(); } Debug.Assert(false, "Invalid IteratorState " + this.state); return IteratorResult.NoMoreNodes; }
/// <summary> /// Swap navCurr with navOther and invert state to reflect the change. /// </summary> private void Swap() { XPathNavigator navTemp = this.navCurr; this.navCurr = this.navOther; this.navOther = navTemp; if (this.state == IteratorState.LeftIsCurrent) this.state = IteratorState.RightIsCurrent; else this.state = IteratorState.LeftIsCurrent; }
/// <summary> /// Create SetIterator. /// </summary> public void Create(XmlQueryRuntime runtime) { this.runtime = runtime; this.state = IteratorState.InitLeft; }
/// <summary> /// Initialize the ContentMergeIterator (merge multiple sets of content nodes in document order and remove duplicates). /// </summary> public void Create(XmlNavigatorFilter filter) { _filter = filter; _navStack.Reset(); _state = IteratorState.NeedCurrent; }
public void Create(XmlNavigatorFilter filter, bool orSelf) { _filter = filter; _state = IteratorState.NoPrevious; _orSelf = orSelf; }
/// <summary> /// Called when an attempt to move to a following node failed. If a Next node exists, then make that the new /// candidate current node. Otherwise, iteration is complete. /// </summary> private IteratorResult MoveFailed() { XPathNavigator navTemp; Debug.Assert(this.state == IteratorState.HaveCurrentHaveNext || this.state == IteratorState.HaveCurrentNoNext); if (this.state == IteratorState.HaveCurrentNoNext) { // No more nodes, so iteration is complete this.state = IteratorState.NeedCandidateCurrent; return IteratorResult.NoMoreNodes; } // Make next node the new candidate node this.state = IteratorState.HaveCandidateCurrent; // Swap navigators in order to sometimes avoid creating clones navTemp = this.navCurrent; this.navCurrent = this.navNext; this.navNext = navTemp; return IteratorResult.NeedInputNode; }
/// <summary> /// If the context node-set returns a node that is contained in the subtree of the previous node, /// then returning children of each node in "natural" order may not correspond to document order. /// Therefore, in order to guarantee document order, keep a stack in order to push the sibling of /// ancestor nodes. These siblings will not be returned until all of the descendants' children are /// returned first. /// </summary> private IteratorResult DocOrderMerge() { XmlNodeOrder cmp; Debug.Assert(this.state == IteratorState.HaveCurrentHaveNext); // Compare location of navCurrent with navNext cmp = this.navCurrent.ComparePosition(this.navNext); // If navCurrent is before navNext in document order, // If cmp = XmlNodeOrder.Unknown, then navCurrent is before navNext (since input is is doc order) if (cmp == XmlNodeOrder.Before || cmp == XmlNodeOrder.Unknown) { // Then navCurrent can be returned (it is guaranteed to be first in document order) return IteratorResult.HaveCurrentNode; } // If navCurrent is after navNext in document order, then delay returning navCurrent // Otherwise, discard navNext since it is positioned to the same node as navCurrent if (cmp == XmlNodeOrder.After) { this.navStack.Push(this.navCurrent); this.navCurrent = this.navNext; this.navNext = null; } // Need next input node this.state = IteratorState.HaveCurrentNeedNext; return IteratorResult.NeedInputNode; }
/// <summary> /// Position this iterator to the next node in the union. /// </summary> public SetIteratorResult MoveNext(XPathNavigator nestedNavigator) { switch (_state) { case IteratorState.InitLeft: // Fetched node from left iterator, now get initial node from right iterator _navLeft = nestedNavigator; _state = IteratorState.NeedRight; return SetIteratorResult.InitRightIterator; case IteratorState.NeedLeft: _navLeft = nestedNavigator; break; case IteratorState.NeedRight: _navRight = nestedNavigator; break; case IteratorState.NeedLeftAndRight: // After fetching left node, still need right node _navLeft = nestedNavigator; _state = IteratorState.NeedRight; return SetIteratorResult.NeedRightNode; case IteratorState.HaveCurrent: // Just returned left node as current, so fetch new left node Debug.Assert(nestedNavigator == null, "null is passed to MoveNext after IteratorState.HaveCurrent has been returned."); _state = IteratorState.NeedLeft; return SetIteratorResult.NeedLeftNode; } if (_navLeft == null) { // If navLeft is null, then difference operation is complete return SetIteratorResult.NoMoreNodes; } else if (_navRight != null) { int order = _runtime.ComparePosition(_navLeft, _navRight); // If navLeft is positioned to same node as navRight, if (order == 0) { // Skip navLeft and navRight _state = IteratorState.NeedLeftAndRight; return SetIteratorResult.NeedLeftNode; } // If navLeft is after navRight in document order, then skip navRight if (order > 0) { _state = IteratorState.NeedRight; return SetIteratorResult.NeedRightNode; } } // Return navLeft _state = IteratorState.HaveCurrent; return SetIteratorResult.HaveCurrentNode; }
/// <summary> /// Create SetIterator. /// </summary> public void Create(XmlQueryRuntime runtime) { _runtime = runtime; _state = IteratorState.InitLeft; }
/// <summary> /// Position this iterator to the next following node. Prune by finding the first input node in /// document order that has no other input nodes in its subtree. All other input nodes should be /// discarded. 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> public IteratorResult MoveNext(XPathNavigator input) { switch (this.state) { case IteratorState.NeedCandidateCurrent: // If there are no more input nodes, then iteration is complete if (input == null) return IteratorResult.NoMoreNodes; // Save input node as current node this.navCurrent = XmlQueryRuntime.SyncToNavigator(this.navCurrent, input); // Still must check next input node to see if is a descendant of this one this.state = IteratorState.HaveCandidateCurrent; return IteratorResult.NeedInputNode; case IteratorState.HaveCandidateCurrent: // If there are no more input nodes, if (input == null) { // Then candidate node has been selected, and there are no further input nodes this.state = IteratorState.HaveCurrentNoNext; return MoveFirst(); } // If input node is in the subtree of the candidate node, then use the input node instead if (this.navCurrent.IsDescendant(input)) goto case IteratorState.NeedCandidateCurrent; // Found node on which to perform following scan. Now skip past all input nodes in the same document. this.state = IteratorState.HaveCurrentNeedNext; goto case IteratorState.HaveCurrentNeedNext; case IteratorState.HaveCurrentNeedNext: // If there are no more input nodes, if (input == null) { // Then candidate node has been selected, and there are no further input nodes this.state = IteratorState.HaveCurrentNoNext; return MoveFirst(); } // Skip input node unless it's in a different document than the node on which the following scan was performed if (this.navCurrent.ComparePosition(input) != XmlNodeOrder.Unknown) return IteratorResult.NeedInputNode; // Next node is in a different document, so save it this.navNext = XmlQueryRuntime.SyncToNavigator(this.navNext, input); this.state = IteratorState.HaveCurrentHaveNext; return MoveFirst(); } if (!this.filter.MoveToFollowing(this.navCurrent, null)) return MoveFailed(); return IteratorResult.HaveCurrentNode; }
/// <summary> /// Position this iterator to the next preceding node in document order. Discard all input nodes /// that are followed by another input node in the same document. This leaves one node per document from /// which the complete set of preceding nodes can be derived without possibility of duplicates. /// 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> public IteratorResult MoveNext(XPathNavigator input) { switch (this.state) { case IteratorState.NeedCandidateCurrent: // If there are no more input nodes, then iteration is complete if (input == null) return IteratorResult.NoMoreNodes; // Save input node as current node this.navCurrent = XmlQueryRuntime.SyncToNavigator(this.navCurrent, input); // Scan for additional input nodes within the same document (since they are after navCurrent in docorder) this.state = IteratorState.HaveCandidateCurrent; return IteratorResult.NeedInputNode; case IteratorState.HaveCandidateCurrent: // If there are no more input nodes, if (input == null) { // Then candidate node has been selected, and there are no further input nodes this.state = IteratorState.HaveCurrentNoNext; } else { // If the input node is in the same document as the current node, if (this.navCurrent.ComparePosition(input) != XmlNodeOrder.Unknown) { // Then update the current node and get the next input node this.navCurrent = XmlQueryRuntime.SyncToNavigator(this.navCurrent, input); return IteratorResult.NeedInputNode; } // Save the input node as navNext this.navNext = XmlQueryRuntime.SyncToNavigator(this.navNext, input); this.state = IteratorState.HaveCurrentHaveNext; } PushAncestors(); break; } if (!this.navStack.IsEmpty) { while (true) { // Move to the next matching node that is before the top node on the stack in document order if (this.filter.MoveToFollowing(this.navCurrent, this.navStack.Peek())) // Found match return IteratorResult.HaveCurrentNode; // Do not include ancestor nodes as part of the preceding axis this.navCurrent.MoveTo(this.navStack.Pop()); // No more preceding matches possible if (this.navStack.IsEmpty) break; } } if (this.state == IteratorState.HaveCurrentNoNext) { // No more nodes, so iteration is complete this.state = IteratorState.NeedCandidateCurrent; return IteratorResult.NoMoreNodes; } // Make next node the current node and start trying to find input node greatest in docorder this.navCurrent = XmlQueryRuntime.SyncToNavigator(this.navCurrent, this.navNext); this.state = IteratorState.HaveCandidateCurrent; return IteratorResult.HaveCurrentNode; }
/// <summary> /// Initialize the XPathPrecedingMergeIterator (merge multiple sets of preceding nodes in document order and remove duplicates). /// </summary> public void Create(XmlNavigatorFilter filter) { this.filter = filter; this.state = IteratorState.NeedCandidateCurrent; }
/// <summary> /// Position this iterator to the next following node. Return false if there are no more following nodes, /// or if the end node has been reached. Return true if the Current property is set to the next node in /// the iteration. /// </summary> public bool MoveNext() { switch (this.state) { case IteratorState.HaveCurrent: this.state = IteratorState.NeedCurrent; return true; case IteratorState.NeedCurrent: // Move to next following node which matches if (!this.filter.MoveToFollowing(this.navCurrent, this.navEnd)) { // No more nodes unless ending node matches if (filter.IsFiltered(this.navEnd)) { this.state = IteratorState.NoNext; return false; } this.navCurrent.MoveTo(this.navEnd); this.state = IteratorState.NoNext; } return true; case IteratorState.HaveCurrentNoNext: this.state = IteratorState.NoNext; return true; } Debug.Assert(this.state == IteratorState.NoNext, "Illegal state: " + this.state); return false; }
/// <summary> /// Initialize the NodeRangeIterator (no possibility of duplicates). /// </summary> public void Create(XPathNavigator start, XmlNavigatorFilter filter, XPathNavigator end) { // Save start node as current node and save ending node this.navCurrent = XmlQueryRuntime.SyncToNavigator(this.navCurrent, start); this.navEnd = XmlQueryRuntime.SyncToNavigator(this.navEnd, end); this.filter = filter; if (start.IsSamePosition(end)) { // Start is end, so only return node if it is not filtered this.state = !filter.IsFiltered(start) ? IteratorState.HaveCurrentNoNext : IteratorState.NoNext; } else { // Return nodes until end is reached this.state = !filter.IsFiltered(start) ? IteratorState.HaveCurrent : IteratorState.NeedCurrent; } }
/// <summary> /// Swap navCurr with navOther and invert state to reflect the change. /// </summary> private void Swap() { XPathNavigator navTemp = _navCurr; _navCurr = _navOther; _navOther = navTemp; if (_state == IteratorState.LeftIsCurrent) _state = IteratorState.RightIsCurrent; else _state = IteratorState.LeftIsCurrent; }
/// <summary> /// Initialize the DescendantIterator (merge multiple sets of descendant nodes in document order and remove duplicates). /// </summary> public void Create(XmlNavigatorFilter filter, bool orSelf) { this.filter = filter; this.state = IteratorState.NoPrevious; this.orSelf = orSelf; }
/// <summary> /// Position this iterator to the next node in the union. /// </summary> public SetIteratorResult MoveNext(XPathNavigator nestedNavigator) { int order; switch (_state) { case IteratorState.InitLeft: // Fetched node from left iterator, now get initial node from right iterator _navLeft = nestedNavigator; _state = IteratorState.NeedRight; return SetIteratorResult.InitRightIterator; case IteratorState.NeedLeft: _navLeft = nestedNavigator; break; case IteratorState.NeedRight: _navRight = nestedNavigator; break; case IteratorState.NeedLeftAndRight: // After fetching left node, still need right node _navLeft = nestedNavigator; _state = IteratorState.NeedRight; return SetIteratorResult.NeedRightNode; case IteratorState.HaveCurrent: // Just returned left node as current, so fetch new left and right nodes Debug.Assert(nestedNavigator == null, "null is passed to MoveNext after IteratorState.HaveCurrent has been returned."); _state = IteratorState.NeedLeftAndRight; return SetIteratorResult.NeedLeftNode; } if (_navLeft == null || _navRight == null) { // No more nodes from either left or right iterator (or both), so iteration is complete return SetIteratorResult.NoMoreNodes; } // Intersect left and right sets order = _runtime.ComparePosition(_navLeft, _navRight); if (order < 0) { // If navLeft is positioned to a node that is before navRight, skip left node _state = IteratorState.NeedLeft; return SetIteratorResult.NeedLeftNode; } else if (order > 0) { // If navLeft is positioned to a node that is after navRight, so skip right node _state = IteratorState.NeedRight; return SetIteratorResult.NeedRightNode; } // Otherwise, navLeft is positioned to the same node as navRight, so found one item in the intersection _state = IteratorState.HaveCurrent; return SetIteratorResult.HaveCurrentNode; }