1 //------------------------------------------------------------------------------
2 // <copyright file="DocumentOrderComparer.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
8 using System.Collections;
9 using System.Collections.Generic;
11 using System.Xml.XPath;
12 using System.Diagnostics;
14 namespace System.Xml.Xsl.Runtime {
17 /// IComparer implementation that orders navigators based on ComparePosition. When ComparePosition returns
18 /// XmlNodeOrder.Unknown, a stable order between documents is maintained by an ordered list mapping each root node
19 /// to an ordering index.
21 internal class DocumentOrderComparer : IComparer<XPathNavigator> {
22 private List<XPathNavigator> roots;
26 /// -1 if navThis is positioned before navThat
27 /// 0 if navThis has the same position as navThat
28 /// 1 if navThis is positioned after navThat
30 public int Compare(XPathNavigator navThis, XPathNavigator navThat) {
31 switch (navThis.ComparePosition(navThat)) {
32 case XmlNodeOrder.Before: return -1;
33 case XmlNodeOrder.Same: return 0;
34 case XmlNodeOrder.After: return 1;
37 // Use this.roots to impose stable ordering
38 if (this.roots == null)
39 this.roots = new List<XPathNavigator>();
41 Debug.Assert(GetDocumentIndex(navThis) != GetDocumentIndex(navThat));
42 return GetDocumentIndex(navThis) < GetDocumentIndex(navThat) ? -1 : 1;
46 /// Map navigator's document to a unique index.
47 /// When consecutive calls are made to GetIndexOfNavigator for navThis and navThat, it is not possible
48 /// for them to return the same index. navThis compared to navThat is always XmlNodeOrder.Unknown.
49 /// Therefore, no matter where navThis is inserted in the list, navThat will never be inserted just
50 /// before navThis, and therefore will never have the same index.
52 public int GetDocumentIndex(XPathNavigator nav) {
53 XPathNavigator navRoot;
55 // Use this.roots to impose stable ordering
56 if (this.roots == null)
57 this.roots = new List<XPathNavigator>();
59 // Position navigator to root
60 navRoot = nav.Clone();
63 for (int idx = 0; idx < this.roots.Count; idx++) {
64 if (navRoot.IsSamePosition(this.roots[idx])) {
65 // navigator's document was previously mapped to a unique index
70 // Add navigator to this.roots mapping
71 this.roots.Add(navRoot);
73 return this.roots.Count - 1;