| File: System\Xml\Xsl\Runtime\DocumentOrderComparer.cs | Web Access |
| Project: src\runtime\src\libraries\System.Private.Xml\src\System.Private.Xml.csproj (System.Private.Xml) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Xml; using System.Xml.XPath; namespace System.Xml.Xsl.Runtime { /// <summary> /// IComparer implementation that orders navigators based on ComparePosition. When ComparePosition returns /// XmlNodeOrder.Unknown, a stable order between documents is maintained by an ordered list mapping each root node /// to an ordering index. /// </summary> internal sealed class DocumentOrderComparer : IComparer<XPathNavigator> { private List<XPathNavigator>? _roots; /// <summary> /// Return: /// -1 if navThis is positioned before navThat /// 0 if navThis has the same position as navThat /// 1 if navThis is positioned after navThat /// </summary> public int Compare(XPathNavigator? navThis, XPathNavigator? navThat) { switch (navThis!.ComparePosition(navThat)) { case XmlNodeOrder.Before: return -1; case XmlNodeOrder.Same: return 0; case XmlNodeOrder.After: return 1; } // Use this.roots to impose stable ordering _roots ??= new List<XPathNavigator>(); Debug.Assert(GetDocumentIndex(navThis) != GetDocumentIndex(navThat!)); return GetDocumentIndex(navThis) < GetDocumentIndex(navThat!) ? -1 : 1; } /// <summary> /// Map navigator's document to a unique index. /// When consecutive calls are made to GetIndexOfNavigator for navThis and navThat, it is not possible /// for them to return the same index. navThis compared to navThat is always XmlNodeOrder.Unknown. /// Therefore, no matter where navThis is inserted in the list, navThat will never be inserted just /// before navThis, and therefore will never have the same index. /// </summary> public int GetDocumentIndex(XPathNavigator nav) { XPathNavigator navRoot; // Use this.roots to impose stable ordering _roots ??= new List<XPathNavigator>(); // Position navigator to root navRoot = nav.Clone(); navRoot.MoveToRoot(); for (int idx = 0; idx < _roots.Count; idx++) { if (navRoot.IsSamePosition(_roots[idx])) { // navigator's document was previously mapped to a unique index return idx; } } // Add navigator to this.roots mapping _roots.Add(navRoot); return _roots.Count - 1; } } }