File: DocumentOrderComparer.cs

package info (click to toggle)
mono 6.14.1%2Bds2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,282,732 kB
  • sloc: cs: 11,182,461; xml: 2,850,281; ansic: 699,123; cpp: 122,919; perl: 58,604; javascript: 30,841; asm: 21,845; makefile: 19,602; sh: 10,973; python: 4,772; pascal: 925; sql: 859; sed: 16; php: 1
file content (76 lines) | stat: -rw-r--r-- 3,181 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
//------------------------------------------------------------------------------
// <copyright file="DocumentOrderComparer.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>                                                                
// <owner current="true" primary="true">Microsoft</owner>
//------------------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Xml;
using System.Xml.XPath;
using System.Diagnostics;

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 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
            if (this.roots == null)
                this.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
            if (this.roots == null)
                this.roots = new List<XPathNavigator>();

            // Position navigator to root
            navRoot = nav.Clone();
            navRoot.MoveToRoot();

            for (int idx = 0; idx < this.roots.Count; idx++) {
                if (navRoot.IsSamePosition(this.roots[idx])) {
                    // navigator's document was previously mapped to a unique index
                    return idx;
                }
            }

            // Add navigator to this.roots mapping
            this.roots.Add(navRoot);

            return this.roots.Count - 1;
        }
    }
}