System.Xml.Xsl.IlGen.XmlILVisitor.MatchesNodeKinds C# (CSharp) Метод

MatchesNodeKinds() приватный Метод

Faster code can be generated if type test is just a node kind test. If this special case is detected, then generate code and return true. Otherwise, return false, and a call to MatchesXmlType will be generated instead.
private MatchesNodeKinds ( QilTargetType ndIsType, XmlQueryType typDerived, XmlQueryType typBase ) : bool
ndIsType System.Xml.Xsl.Qil.QilTargetType
typDerived XmlQueryType
typBase XmlQueryType
Результат bool
        private bool MatchesNodeKinds(QilTargetType ndIsType, XmlQueryType typDerived, XmlQueryType typBase) {
            XmlNodeKindFlags kinds;
            bool allowKinds = true;
            XPathNodeType kindsRuntime;
            int kindsUnion;

            // If not checking whether typDerived is some kind of singleton node, then fallback to MatchesXmlType
            if (!typBase.IsNode || !typBase.IsSingleton)
                return false;

            // If typDerived is not statically guaranteed to be a singleton node (and not an rtf), then fallback to MatchesXmlType
            if (!typDerived.IsNode || !typDerived.IsSingleton || !typDerived.IsNotRtf)
                return false;

            // Now we are guaranteed that typDerived is a node, and typBase is a node, so check node kinds
            // Ensure that typBase is only composed of kind-test prime types (no name-test, no schema-test, etc.)
            kinds = XmlNodeKindFlags.None;
            foreach (XmlQueryType typItem in typBase) {
                if (Ref.Equals(typItem, TypeFactory.Element)) kinds |= XmlNodeKindFlags.Element;
                else if (Ref.Equals(typItem, TypeFactory.Attribute)) kinds |= XmlNodeKindFlags.Attribute;
                else if (Ref.Equals(typItem, TypeFactory.Text)) kinds |= XmlNodeKindFlags.Text;
                else if (Ref.Equals(typItem, TypeFactory.Document)) kinds |= XmlNodeKindFlags.Document;
                else if (Ref.Equals(typItem, TypeFactory.Comment)) kinds |= XmlNodeKindFlags.Comment;
                else if (Ref.Equals(typItem, TypeFactory.PI)) kinds |= XmlNodeKindFlags.PI;
                else if (Ref.Equals(typItem, TypeFactory.Namespace)) kinds |= XmlNodeKindFlags.Namespace;
                else return false;
            }

            Debug.Assert((typDerived.NodeKinds & kinds) != XmlNodeKindFlags.None, "Normalizer should have taken care of case where node kinds are disjoint.");

            kinds = typDerived.NodeKinds & kinds;

            // Attempt to allow or disallow exactly one kind
            if (!Bits.ExactlyOne((uint) kinds)) {
                // Not possible to allow one kind, so try to disallow one kind
                kinds = ~kinds & XmlNodeKindFlags.Any;
                allowKinds = !allowKinds;
            }

            switch (kinds) {
                case XmlNodeKindFlags.Element: kindsRuntime = XPathNodeType.Element; break;
                case XmlNodeKindFlags.Attribute: kindsRuntime = XPathNodeType.Attribute; break;
                case XmlNodeKindFlags.Namespace: kindsRuntime = XPathNodeType.Namespace; break;
                case XmlNodeKindFlags.PI: kindsRuntime = XPathNodeType.ProcessingInstruction; break;
                case XmlNodeKindFlags.Comment: kindsRuntime = XPathNodeType.Comment; break;
                case XmlNodeKindFlags.Document: kindsRuntime = XPathNodeType.Root; break;

                default:
                    // Union of several types (when testing for Text, we need to test for Whitespace as well)

                    // if (((1 << navigator.NodeType) & nodesDisallow) op 0) goto LabelBranch;
                    this.helper.Emit(OpCodes.Ldc_I4_1);
                    kindsRuntime = XPathNodeType.All;
                    break;
            }

            // Push navigator.NodeType onto the stack
            NestedVisitEnsureStack(ndIsType.Source);
            this.helper.Call(XmlILMethods.NavType);

            if (kindsRuntime == XPathNodeType.All) {
                // if (((1 << navigator.NodeType) & kindsUnion) op 0) goto LabelBranch;
                this.helper.Emit(OpCodes.Shl);

                kindsUnion = 0;
                if ((kinds & XmlNodeKindFlags.Document) != 0) kindsUnion |= (1 << (int) XPathNodeType.Root);
                if ((kinds & XmlNodeKindFlags.Element) != 0) kindsUnion |= (1 << (int) XPathNodeType.Element);
                if ((kinds & XmlNodeKindFlags.Attribute) != 0) kindsUnion |= (1 << (int) XPathNodeType.Attribute);
                if ((kinds & XmlNodeKindFlags.Text) != 0) kindsUnion |= (1 << (int) (int) XPathNodeType.Text) |
                                                                      (1 << (int) (int) XPathNodeType.SignificantWhitespace) |
                                                                      (1 << (int) (int) XPathNodeType.Whitespace);
                if ((kinds & XmlNodeKindFlags.Comment) != 0) kindsUnion |= (1 << (int) XPathNodeType.Comment);
                if ((kinds & XmlNodeKindFlags.PI) != 0) kindsUnion |= (1 << (int) XPathNodeType.ProcessingInstruction);
                if ((kinds & XmlNodeKindFlags.Namespace) != 0) kindsUnion |= (1 << (int) XPathNodeType.Namespace);
                
                this.helper.LoadInteger(kindsUnion);
                this.helper.Emit(OpCodes.And);
                ZeroCompare(allowKinds ? QilNodeType.Ne : QilNodeType.Eq, false);
            }
            else {
                // if (navigator.NodeType op runtimeItem) goto LabelBranch;
                this.helper.LoadInteger((int) kindsRuntime);
                ClrCompare(allowKinds ? QilNodeType.Eq : QilNodeType.Ne, XmlTypeCode.Int);
            }

            return true;
        }
XmlILVisitor