You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@@ -0,0 +1,201 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="Focus.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
// <owner current="true" primary="true">[....]</owner>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Xml.Xsl.XPath;
|
||||
using System.Xml.Xsl.Qil;
|
||||
|
||||
namespace System.Xml.Xsl.Xslt {
|
||||
using T = XmlQueryTypeFactory;
|
||||
|
||||
// <spec>http://www.w3.org/TR/xslt20/#dt-singleton-focus</spec>
|
||||
internal enum SingletonFocusType {
|
||||
// No context set
|
||||
// Used to prevent bugs
|
||||
None,
|
||||
|
||||
// Document node of the document containing the initial context node
|
||||
// Used while compiling global variables and params
|
||||
InitialDocumentNode,
|
||||
|
||||
// Initial context node for the transformation
|
||||
// Used while compiling initial apply-templates
|
||||
InitialContextNode,
|
||||
|
||||
// Context node is specified by iterator
|
||||
// Used while compiling keys
|
||||
Iterator,
|
||||
}
|
||||
|
||||
internal struct SingletonFocus : IFocus {
|
||||
private XPathQilFactory f;
|
||||
private SingletonFocusType focusType;
|
||||
private QilIterator current;
|
||||
|
||||
public SingletonFocus(XPathQilFactory f) {
|
||||
this.f = f;
|
||||
focusType = SingletonFocusType.None;
|
||||
current = null;
|
||||
}
|
||||
|
||||
public void SetFocus(SingletonFocusType focusType) {
|
||||
Debug.Assert(focusType != SingletonFocusType.Iterator);
|
||||
this.focusType = focusType;
|
||||
}
|
||||
|
||||
public void SetFocus(QilIterator current) {
|
||||
if (current != null) {
|
||||
this.focusType = SingletonFocusType.Iterator;
|
||||
this.current = current;
|
||||
} else {
|
||||
this.focusType = SingletonFocusType.None;
|
||||
this.current = null;
|
||||
}
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
private void CheckFocus() {
|
||||
Debug.Assert(focusType != SingletonFocusType.None, "Focus is not set, call SetFocus first");
|
||||
}
|
||||
|
||||
public QilNode GetCurrent() {
|
||||
CheckFocus();
|
||||
switch (focusType) {
|
||||
case SingletonFocusType.InitialDocumentNode: return f.Root(f.XmlContext());
|
||||
case SingletonFocusType.InitialContextNode : return f.XmlContext();
|
||||
default:
|
||||
Debug.Assert(focusType == SingletonFocusType.Iterator && current != null, "Unexpected singleton focus type");
|
||||
return current;
|
||||
}
|
||||
}
|
||||
|
||||
public QilNode GetPosition() {
|
||||
CheckFocus();
|
||||
return f.Double(1);
|
||||
}
|
||||
|
||||
public QilNode GetLast() {
|
||||
CheckFocus();
|
||||
return f.Double(1);
|
||||
}
|
||||
}
|
||||
|
||||
internal struct FunctionFocus : IFocus {
|
||||
private bool isSet;
|
||||
private QilParameter current, position, last;
|
||||
|
||||
public void StartFocus(IList<QilNode> args, XslFlags flags) {
|
||||
Debug.Assert(! IsFocusSet, "Focus was already set");
|
||||
int argNum = 0;
|
||||
if ((flags & XslFlags.Current) != 0) {
|
||||
this.current = (QilParameter)args[argNum ++];
|
||||
Debug.Assert(this.current.Name.NamespaceUri == XmlReservedNs.NsXslDebug && this.current.Name.LocalName == "current");
|
||||
}
|
||||
if ((flags & XslFlags.Position) != 0) {
|
||||
this.position = (QilParameter)args[argNum ++];
|
||||
Debug.Assert(this.position.Name.NamespaceUri == XmlReservedNs.NsXslDebug && this.position.Name.LocalName == "position");
|
||||
}
|
||||
if ((flags & XslFlags.Last) != 0) {
|
||||
this.last = (QilParameter)args[argNum ++];
|
||||
Debug.Assert(this.last.Name.NamespaceUri == XmlReservedNs.NsXslDebug && this.last.Name.LocalName == "last");
|
||||
}
|
||||
this.isSet = true;
|
||||
}
|
||||
public void StopFocus() {
|
||||
Debug.Assert(IsFocusSet, "Focus was not set");
|
||||
isSet = false;
|
||||
this.current = this.position = this.last = null;
|
||||
}
|
||||
public bool IsFocusSet {
|
||||
get { return this.isSet; }
|
||||
}
|
||||
|
||||
public QilNode GetCurrent() {
|
||||
Debug.Assert(this.current != null, "---- current() is not expected in this function");
|
||||
return this.current;
|
||||
}
|
||||
|
||||
public QilNode GetPosition() {
|
||||
Debug.Assert(this.position != null, "---- position() is not expected in this function");
|
||||
return this.position;
|
||||
}
|
||||
|
||||
public QilNode GetLast() {
|
||||
Debug.Assert(this.last != null, "---- last() is not expected in this function");
|
||||
return this.last;
|
||||
}
|
||||
}
|
||||
|
||||
internal struct LoopFocus : IFocus {
|
||||
private XPathQilFactory f;
|
||||
private QilIterator current, cached, last;
|
||||
|
||||
public LoopFocus(XPathQilFactory f) {
|
||||
this.f = f;
|
||||
current = cached = last = null;
|
||||
}
|
||||
|
||||
public void SetFocus(QilIterator current) {
|
||||
this.current = current;
|
||||
cached = last = null;
|
||||
}
|
||||
|
||||
public bool IsFocusSet {
|
||||
get { return current != null; }
|
||||
}
|
||||
|
||||
public QilNode GetCurrent() {
|
||||
return current;
|
||||
}
|
||||
|
||||
public QilNode GetPosition() {
|
||||
return f.XsltConvert(f.PositionOf(current), T.DoubleX);
|
||||
}
|
||||
|
||||
public QilNode GetLast() {
|
||||
if (last == null) {
|
||||
// Create a let that will be fixed up later in ConstructLoop or by LastFixupVisitor
|
||||
last = f.Let(f.Double(0));
|
||||
}
|
||||
return last;
|
||||
}
|
||||
|
||||
public void EnsureCache() {
|
||||
if (cached == null) {
|
||||
cached = f.Let(current.Binding);
|
||||
current.Binding = cached;
|
||||
}
|
||||
}
|
||||
|
||||
public void Sort(QilNode sortKeys) {
|
||||
if (sortKeys != null) {
|
||||
// If sorting is required, cache the input node-set to support last() within sort key expressions
|
||||
EnsureCache();
|
||||
// The rest of the loop content must be compiled in the context of already sorted node-set
|
||||
current = f.For(f.Sort(current, sortKeys));
|
||||
}
|
||||
}
|
||||
|
||||
public QilLoop ConstructLoop(QilNode body) {
|
||||
QilLoop result;
|
||||
if (last != null) {
|
||||
// last() encountered either in the sort keys or in the body of the current loop
|
||||
EnsureCache();
|
||||
last.Binding = f.XsltConvert(f.Length(cached), T.DoubleX);
|
||||
}
|
||||
result = f.BaseFactory.Loop(current, body);
|
||||
if (last != null) {
|
||||
result = f.BaseFactory.Loop(last, result);
|
||||
}
|
||||
if (cached != null) {
|
||||
result = f.BaseFactory.Loop(cached, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user