e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
940 lines
25 KiB
C#
940 lines
25 KiB
C#
//------------------------------------------------------------
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//------------------------------------------------------------
|
|
namespace System.ServiceModel.Dispatcher
|
|
{
|
|
using System.Runtime;
|
|
using System.Xml;
|
|
using System.Xml.XPath;
|
|
|
|
#if NO
|
|
//
|
|
// A message is just one more source of Xml data. To filter a message, we create a navigator over it that
|
|
// surfaces its contained Xml to the filter engine.
|
|
// In M5.1, we navigate messages by first writing them into a message document. This turns the message into an
|
|
// Xml DOM. we then get a navigator from the DOM.
|
|
// In M5.2, we'll navigate messages without requiring this step.
|
|
//
|
|
internal class MessageNavigator : GenericSeekableNavigator
|
|
{
|
|
StringBuilder builder;
|
|
int headerCollectionVersion;
|
|
bool loaded;
|
|
bool navigatesBody;
|
|
|
|
internal MessageNavigator(MessageNavigator nav)
|
|
: base(nav)
|
|
{
|
|
this.headerCollectionVersion = nav.headerCollectionVersion;
|
|
this.loaded = nav.loaded;
|
|
this.navigatesBody = nav.navigatesBody;
|
|
}
|
|
|
|
internal MessageNavigator(Message message, bool navigateBody)
|
|
: base()
|
|
{
|
|
this.navigatesBody = navigateBody;
|
|
this.Load(message, this.navigatesBody);
|
|
}
|
|
|
|
internal bool IsLoaded
|
|
{
|
|
get
|
|
{
|
|
return this.loaded;
|
|
}
|
|
}
|
|
|
|
internal bool NavigatesBody
|
|
{
|
|
get
|
|
{
|
|
return this.navigatesBody;
|
|
}
|
|
}
|
|
|
|
internal override void Clear()
|
|
{
|
|
base.Clear();
|
|
this.loaded = false;
|
|
this.navigatesBody = false;
|
|
}
|
|
|
|
public override XPathNavigator Clone()
|
|
{
|
|
return new MessageNavigator(this);
|
|
}
|
|
|
|
internal MessageNavigator Ensure(Message message, bool navigateBody)
|
|
{
|
|
// Rebuild the navigator if:
|
|
// If this navigator does not navigate on bodies and now we need to (or vice versa)
|
|
// Or the header collection changed under us
|
|
if (this.navigatesBody != navigateBody || message.Headers.CollectionVersion != this.headerCollectionVersion)
|
|
{
|
|
this.Load(message, navigateBody);
|
|
}
|
|
else
|
|
{
|
|
this.MoveToRoot();
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
// To load a message into a message document, we write the message into a buffer and then let XPathDocument
|
|
// load that buffer
|
|
internal void Load(Message message, bool navigatesBody)
|
|
{
|
|
if (null == this.builder)
|
|
{
|
|
this.builder = new StringBuilder(1024);
|
|
}
|
|
|
|
StringWriter stringWriter = new StringWriter(this.builder);
|
|
XmlWriter writer = new XmlTextWriter(stringWriter);
|
|
|
|
message.WriteMessage(writer, navigatesBody);
|
|
writer.Close();
|
|
|
|
StringReader reader = new StringReader(this.builder.ToString());
|
|
XPathDocument messageDoc = new XPathDocument(reader);
|
|
reader.Close();
|
|
this.builder.Length = 0;
|
|
|
|
this.Init(messageDoc.CreateNavigator());
|
|
this.loaded = true;
|
|
this.navigatesBody = navigatesBody;
|
|
this.headerCollectionVersion = message.Headers.CollectionVersion;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// To prevent XPaths from running forever etc, users can specify limits on:
|
|
// the # of nodes a filter or filter table should inspect
|
|
//
|
|
// This file contains navigators that impose these limits
|
|
|
|
internal interface INodeCounter
|
|
{
|
|
int CounterMarker { get; set; }
|
|
int MaxCounter { set; }
|
|
int ElapsedCount(int marker);
|
|
void Increase();
|
|
void IncreaseBy(int count);
|
|
}
|
|
|
|
internal class DummyNodeCounter : INodeCounter
|
|
{
|
|
internal static DummyNodeCounter Dummy = new DummyNodeCounter();
|
|
public int CounterMarker
|
|
{
|
|
get { return 0; }
|
|
set { }
|
|
}
|
|
|
|
public int MaxCounter
|
|
{
|
|
set { }
|
|
}
|
|
|
|
public int ElapsedCount(int marker) { return 0; }
|
|
|
|
public void Increase() { }
|
|
public void IncreaseBy(int count) { }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Seekable navigators that wrap other navigators and doesn't exceed node counting limits
|
|
/// </summary>
|
|
internal class SafeSeekableNavigator : SeekableXPathNavigator, INodeCounter
|
|
{
|
|
SeekableXPathNavigator navigator;
|
|
SafeSeekableNavigator counter;
|
|
int nodeCount;
|
|
int nodeCountMax;
|
|
|
|
internal SafeSeekableNavigator(SafeSeekableNavigator nav)
|
|
{
|
|
this.navigator = (SeekableXPathNavigator)nav.navigator.Clone();
|
|
this.counter = nav.counter;
|
|
}
|
|
|
|
internal SafeSeekableNavigator(SeekableXPathNavigator navigator, int nodeCountMax)
|
|
{
|
|
this.navigator = navigator;
|
|
this.counter = this;
|
|
this.nodeCount = nodeCountMax;
|
|
this.nodeCountMax = nodeCountMax;
|
|
}
|
|
|
|
public override string BaseURI
|
|
{
|
|
get
|
|
{
|
|
return this.navigator.BaseURI;
|
|
}
|
|
}
|
|
|
|
public int CounterMarker
|
|
{
|
|
get
|
|
{
|
|
return this.counter.nodeCount;
|
|
}
|
|
set
|
|
{
|
|
this.counter.nodeCount = value;
|
|
}
|
|
}
|
|
|
|
public int MaxCounter
|
|
{
|
|
set
|
|
{
|
|
this.counter.nodeCountMax = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Setting the current position moves this navigator to the location specified by the given position
|
|
/// </summary>
|
|
public override long CurrentPosition
|
|
{
|
|
get
|
|
{
|
|
return this.navigator.CurrentPosition;
|
|
}
|
|
set
|
|
{
|
|
this.navigator.CurrentPosition = value;
|
|
}
|
|
}
|
|
|
|
public override bool HasAttributes
|
|
{
|
|
get
|
|
{
|
|
return this.navigator.HasAttributes;
|
|
}
|
|
}
|
|
|
|
public override bool HasChildren
|
|
{
|
|
get
|
|
{
|
|
return this.navigator.HasChildren;
|
|
}
|
|
}
|
|
|
|
public override bool IsEmptyElement
|
|
{
|
|
get
|
|
{
|
|
return this.navigator.IsEmptyElement;
|
|
}
|
|
}
|
|
|
|
public override string LocalName
|
|
{
|
|
get
|
|
{
|
|
return this.navigator.LocalName;
|
|
}
|
|
}
|
|
|
|
public override string Name
|
|
{
|
|
get
|
|
{
|
|
return this.navigator.Name;
|
|
}
|
|
}
|
|
|
|
public override string NamespaceURI
|
|
{
|
|
get
|
|
{
|
|
return this.navigator.NamespaceURI;
|
|
}
|
|
}
|
|
|
|
public override XmlNameTable NameTable
|
|
{
|
|
get
|
|
{
|
|
return this.navigator.NameTable;
|
|
}
|
|
}
|
|
|
|
public override XPathNodeType NodeType
|
|
{
|
|
get
|
|
{
|
|
return this.navigator.NodeType;
|
|
}
|
|
}
|
|
|
|
public override string Prefix
|
|
{
|
|
get
|
|
{
|
|
return this.navigator.Prefix;
|
|
}
|
|
}
|
|
|
|
public override string Value
|
|
{
|
|
get
|
|
{
|
|
return this.navigator.Value;
|
|
}
|
|
}
|
|
|
|
public override string XmlLang
|
|
{
|
|
get
|
|
{
|
|
return this.navigator.XmlLang;
|
|
}
|
|
}
|
|
|
|
public override XPathNavigator Clone()
|
|
{
|
|
return new SafeSeekableNavigator(this);
|
|
}
|
|
|
|
#if NO
|
|
internal SafeNavigator CreateSafeXPathNavigator()
|
|
{
|
|
return new SafeNavigator(this, this.navigator);
|
|
}
|
|
#endif
|
|
public override XmlNodeOrder ComparePosition(XPathNavigator navigator)
|
|
{
|
|
if (navigator == null)
|
|
{
|
|
return XmlNodeOrder.Unknown;
|
|
}
|
|
|
|
SafeSeekableNavigator nav = navigator as SafeSeekableNavigator;
|
|
if (nav != null)
|
|
{
|
|
return this.navigator.ComparePosition(nav.navigator);
|
|
}
|
|
return XmlNodeOrder.Unknown;
|
|
}
|
|
|
|
public override XmlNodeOrder ComparePosition(long x, long y)
|
|
{
|
|
return this.navigator.ComparePosition(x, y);
|
|
}
|
|
|
|
public int ElapsedCount(int marker)
|
|
{
|
|
return marker - this.counter.nodeCount;
|
|
}
|
|
|
|
public override string GetLocalName(long nodePosition)
|
|
{
|
|
return this.navigator.GetLocalName(nodePosition);
|
|
}
|
|
|
|
public override string GetName(long nodePosition)
|
|
{
|
|
return this.navigator.GetName(nodePosition);
|
|
}
|
|
|
|
public override string GetNamespace(long nodePosition)
|
|
{
|
|
return this.navigator.GetNamespace(nodePosition);
|
|
}
|
|
|
|
public override XPathNodeType GetNodeType(long nodePosition)
|
|
{
|
|
return this.navigator.GetNodeType(nodePosition);
|
|
}
|
|
|
|
public override string GetValue(long nodePosition)
|
|
{
|
|
return this.navigator.GetValue(nodePosition);
|
|
}
|
|
|
|
public override string GetNamespace(string name)
|
|
{
|
|
this.IncrementNodeCount();
|
|
return this.navigator.GetNamespace(name);
|
|
}
|
|
|
|
public override string GetAttribute(string localName, string namespaceURI)
|
|
{
|
|
this.IncrementNodeCount();
|
|
return this.navigator.GetAttribute(localName, namespaceURI);
|
|
}
|
|
|
|
public void Increase()
|
|
{
|
|
this.IncrementNodeCount();
|
|
}
|
|
|
|
public void IncreaseBy(int count)
|
|
{
|
|
this.counter.nodeCount -= (count - 1);
|
|
Increase();
|
|
}
|
|
|
|
internal void IncrementNodeCount()
|
|
{
|
|
if (this.counter.nodeCount > 0)
|
|
{
|
|
this.counter.nodeCount--;
|
|
}
|
|
else
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XPathNavigatorException(SR.GetString(SR.FilterNodeQuotaExceeded, this.counter.nodeCountMax)));
|
|
}
|
|
}
|
|
#if NO
|
|
internal virtual void Init(SeekableXPathNavigator navigator, int nodeCountMax)
|
|
{
|
|
this.navigator = navigator;
|
|
this.nodeCount = nodeCountMax;
|
|
this.counter = this;
|
|
}
|
|
#endif
|
|
public override bool IsDescendant(XPathNavigator navigator)
|
|
{
|
|
if (navigator == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
SafeSeekableNavigator nav = navigator as SafeSeekableNavigator;
|
|
if (nav != null)
|
|
{
|
|
return this.navigator.IsDescendant(nav.navigator);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public override bool IsSamePosition(XPathNavigator other)
|
|
{
|
|
if (other == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
SafeSeekableNavigator nav = other as SafeSeekableNavigator;
|
|
if (nav != null)
|
|
{
|
|
return this.navigator.IsSamePosition(nav.navigator);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public override void MoveToRoot()
|
|
{
|
|
this.IncrementNodeCount();
|
|
this.navigator.MoveToRoot();
|
|
}
|
|
|
|
public override bool MoveToNextNamespace(XPathNamespaceScope namespaceScope)
|
|
{
|
|
this.IncrementNodeCount();
|
|
return this.navigator.MoveToNextNamespace(namespaceScope);
|
|
}
|
|
|
|
public override bool MoveToNextAttribute()
|
|
{
|
|
this.IncrementNodeCount();
|
|
return this.navigator.MoveToNextAttribute();
|
|
}
|
|
|
|
public override bool MoveToPrevious()
|
|
{
|
|
this.IncrementNodeCount();
|
|
return this.navigator.MoveToPrevious();
|
|
}
|
|
|
|
public override bool MoveToFirstAttribute()
|
|
{
|
|
this.IncrementNodeCount();
|
|
return this.navigator.MoveToFirstAttribute();
|
|
}
|
|
|
|
public override bool MoveToNamespace(string name)
|
|
{
|
|
this.IncrementNodeCount();
|
|
return this.navigator.MoveToNamespace(name);
|
|
}
|
|
|
|
public override bool MoveToParent()
|
|
{
|
|
this.IncrementNodeCount();
|
|
return this.navigator.MoveToParent();
|
|
}
|
|
|
|
public override bool MoveTo(XPathNavigator other)
|
|
{
|
|
if (other == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
this.IncrementNodeCount();
|
|
SafeSeekableNavigator nav = other as SafeSeekableNavigator;
|
|
if (nav != null)
|
|
{
|
|
return this.navigator.MoveTo(nav.navigator);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public override bool MoveToId(string id)
|
|
{
|
|
this.IncrementNodeCount();
|
|
return this.navigator.MoveToId(id);
|
|
}
|
|
|
|
public override bool MoveToFirstChild()
|
|
{
|
|
this.IncrementNodeCount();
|
|
return this.navigator.MoveToFirstChild();
|
|
}
|
|
|
|
public override bool MoveToFirstNamespace(XPathNamespaceScope namespaceScope)
|
|
{
|
|
this.IncrementNodeCount();
|
|
return this.navigator.MoveToFirstNamespace(namespaceScope);
|
|
}
|
|
|
|
public override bool MoveToAttribute(string localName, string namespaceURI)
|
|
{
|
|
this.IncrementNodeCount();
|
|
return this.navigator.MoveToAttribute(localName, namespaceURI);
|
|
}
|
|
|
|
public override bool MoveToNext()
|
|
{
|
|
this.IncrementNodeCount();
|
|
return this.navigator.MoveToNext();
|
|
}
|
|
|
|
public override bool MoveToFirst()
|
|
{
|
|
this.IncrementNodeCount();
|
|
return this.navigator.MoveToFirst();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The filter engine works with seekable navigators. This class takes a generic XPathNavigator implementation
|
|
/// and transforms it into a seekable navigator. Seekable navigators associate a 'position' to every node in a DOM.
|
|
///
|
|
/// This class maintains a (position, navigator) map. Cloning navigators is unavoidable - XPathNavigator offers
|
|
/// no other way to snapshot its current position. However, caching allows memory allocations to be avoided - but
|
|
/// only once the navigator is warmed up.
|
|
/// </summary>
|
|
internal class GenericSeekableNavigator : SeekableXPathNavigator
|
|
{
|
|
QueryBuffer<XPathNavigator> nodes;
|
|
long currentPosition;
|
|
XPathNavigator navigator;
|
|
|
|
GenericSeekableNavigator dom;
|
|
#if NO
|
|
internal GenericSeekableNavigator()
|
|
{
|
|
this.nodes = new QueryBuffer<XPathNavigator>(4);
|
|
this.currentPosition = -1;
|
|
}
|
|
#endif
|
|
internal GenericSeekableNavigator(XPathNavigator navigator)
|
|
{
|
|
this.navigator = navigator;
|
|
this.nodes = new QueryBuffer<XPathNavigator>(4);
|
|
this.currentPosition = -1;
|
|
this.dom = this;
|
|
}
|
|
|
|
internal GenericSeekableNavigator(GenericSeekableNavigator navigator)
|
|
{
|
|
this.navigator = navigator.navigator.Clone();
|
|
this.nodes = default(QueryBuffer<XPathNavigator>);
|
|
this.currentPosition = navigator.currentPosition;
|
|
this.dom = navigator.dom;
|
|
}
|
|
|
|
public override string BaseURI
|
|
{
|
|
get
|
|
{
|
|
return this.navigator.BaseURI;
|
|
}
|
|
}
|
|
|
|
public override bool HasAttributes
|
|
{
|
|
get
|
|
{
|
|
return this.navigator.HasAttributes;
|
|
}
|
|
}
|
|
|
|
public override bool HasChildren
|
|
{
|
|
get
|
|
{
|
|
return this.navigator.HasChildren;
|
|
}
|
|
}
|
|
|
|
#if NO
|
|
internal XPathNavigator InternalNavigator
|
|
{
|
|
get
|
|
{
|
|
return this.navigator;
|
|
}
|
|
}
|
|
#endif
|
|
public override bool IsEmptyElement
|
|
{
|
|
get
|
|
{
|
|
return this.navigator.IsEmptyElement;
|
|
}
|
|
}
|
|
|
|
public override string LocalName
|
|
{
|
|
get
|
|
{
|
|
return this.navigator.LocalName;
|
|
}
|
|
}
|
|
|
|
public override string Name
|
|
{
|
|
get
|
|
{
|
|
return this.navigator.Name;
|
|
}
|
|
}
|
|
|
|
public override string NamespaceURI
|
|
{
|
|
get
|
|
{
|
|
return this.navigator.NamespaceURI;
|
|
}
|
|
}
|
|
|
|
public override XmlNameTable NameTable
|
|
{
|
|
get
|
|
{
|
|
return this.navigator.NameTable;
|
|
}
|
|
}
|
|
|
|
public override XPathNodeType NodeType
|
|
{
|
|
get
|
|
{
|
|
return this.navigator.NodeType;
|
|
}
|
|
}
|
|
|
|
public override string Prefix
|
|
{
|
|
get
|
|
{
|
|
return this.navigator.Prefix;
|
|
}
|
|
}
|
|
|
|
public override string Value
|
|
{
|
|
get
|
|
{
|
|
return this.navigator.Value;
|
|
}
|
|
}
|
|
|
|
public override string XmlLang
|
|
{
|
|
get
|
|
{
|
|
return this.navigator.XmlLang;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Setting the current position moves this navigator to the location specified by the given position
|
|
/// </summary>
|
|
public override long CurrentPosition
|
|
{
|
|
get
|
|
{
|
|
if (-1 == this.currentPosition)
|
|
{
|
|
this.SnapshotNavigator();
|
|
}
|
|
return this.currentPosition;
|
|
}
|
|
set
|
|
{
|
|
this.navigator.MoveTo(this[value]);
|
|
this.currentPosition = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Return the XPathNavigator that has the given position
|
|
/// </summary>
|
|
internal XPathNavigator this[long nodePosition]
|
|
{
|
|
get
|
|
{
|
|
int pos = (int)nodePosition;
|
|
Fx.Assert(this.dom.nodes.IsValidIndex(pos) && null != this.dom.nodes[pos], "");
|
|
return this.dom.nodes[pos];
|
|
}
|
|
}
|
|
|
|
#if NO
|
|
internal virtual void Clear()
|
|
{
|
|
this.navigator = null;
|
|
this.currentPosition = -1;
|
|
}
|
|
#endif
|
|
public override XPathNavigator Clone()
|
|
{
|
|
return new GenericSeekableNavigator(this);
|
|
}
|
|
|
|
public override XmlNodeOrder ComparePosition(XPathNavigator navigator)
|
|
{
|
|
if (navigator == null)
|
|
{
|
|
return XmlNodeOrder.Unknown;
|
|
}
|
|
|
|
GenericSeekableNavigator nav = navigator as GenericSeekableNavigator;
|
|
if (nav != null)
|
|
{
|
|
return this.navigator.ComparePosition(nav.navigator);
|
|
}
|
|
return XmlNodeOrder.Unknown;
|
|
}
|
|
|
|
public override XmlNodeOrder ComparePosition(long x, long y)
|
|
{
|
|
XPathNavigator nodeX = this[x];
|
|
XPathNavigator nodeY = this[y];
|
|
|
|
return nodeX.ComparePosition(nodeY);
|
|
}
|
|
|
|
public override string GetLocalName(long nodePosition)
|
|
{
|
|
return this[nodePosition].LocalName;
|
|
}
|
|
|
|
public override string GetName(long nodePosition)
|
|
{
|
|
return this[nodePosition].Name;
|
|
}
|
|
|
|
public override string GetNamespace(long nodePosition)
|
|
{
|
|
return this[nodePosition].NamespaceURI;
|
|
}
|
|
|
|
public override XPathNodeType GetNodeType(long nodePosition)
|
|
{
|
|
return this[nodePosition].NodeType;
|
|
}
|
|
|
|
public override string GetValue(long nodePosition)
|
|
{
|
|
return this[nodePosition].Value;
|
|
}
|
|
|
|
public override string GetNamespace(string name)
|
|
{
|
|
return this.navigator.GetNamespace(name);
|
|
}
|
|
|
|
public override string GetAttribute(string localName, string namespaceURI)
|
|
{
|
|
return this.navigator.GetAttribute(localName, namespaceURI);
|
|
}
|
|
|
|
#if NO
|
|
internal void Init(XPathNavigator navigator)
|
|
{
|
|
Fx.Assert(null != navigator, "");
|
|
this.navigator = navigator;
|
|
this.currentPosition = -1;
|
|
}
|
|
#endif
|
|
public override bool IsDescendant(XPathNavigator navigator)
|
|
{
|
|
if (navigator == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
GenericSeekableNavigator nav = navigator as GenericSeekableNavigator;
|
|
if (null != nav)
|
|
{
|
|
return this.navigator.IsDescendant(nav.navigator);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public override bool IsSamePosition(XPathNavigator other)
|
|
{
|
|
GenericSeekableNavigator nav = other as GenericSeekableNavigator;
|
|
if (null != nav)
|
|
{
|
|
return this.navigator.IsSamePosition(nav.navigator);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public override void MoveToRoot()
|
|
{
|
|
this.currentPosition = -1;
|
|
this.navigator.MoveToRoot();
|
|
}
|
|
|
|
public override bool MoveToNextNamespace(XPathNamespaceScope namespaceScope)
|
|
{
|
|
this.currentPosition = -1;
|
|
return this.navigator.MoveToNextNamespace(namespaceScope);
|
|
}
|
|
|
|
public override bool MoveToNextAttribute()
|
|
{
|
|
this.currentPosition = -1;
|
|
return this.navigator.MoveToNextAttribute();
|
|
}
|
|
|
|
public override bool MoveToPrevious()
|
|
{
|
|
this.currentPosition = -1;
|
|
return this.navigator.MoveToPrevious();
|
|
}
|
|
|
|
public override bool MoveToFirstAttribute()
|
|
{
|
|
this.currentPosition = -1;
|
|
return this.navigator.MoveToFirstAttribute();
|
|
}
|
|
|
|
public override bool MoveToNamespace(string name)
|
|
{
|
|
this.currentPosition = -1;
|
|
return this.navigator.MoveToNamespace(name);
|
|
}
|
|
|
|
public override bool MoveToParent()
|
|
{
|
|
this.currentPosition = -1;
|
|
return this.navigator.MoveToParent();
|
|
}
|
|
|
|
public override bool MoveTo(XPathNavigator other)
|
|
{
|
|
GenericSeekableNavigator nav = other as GenericSeekableNavigator;
|
|
if (null != nav)
|
|
{
|
|
if (this.navigator.MoveTo(nav.navigator))
|
|
{
|
|
this.currentPosition = nav.currentPosition;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public override bool MoveToId(string id)
|
|
{
|
|
this.currentPosition = -1;
|
|
return this.navigator.MoveToId(id);
|
|
}
|
|
|
|
public override bool MoveToFirstChild()
|
|
{
|
|
this.currentPosition = -1;
|
|
return this.navigator.MoveToFirstChild();
|
|
}
|
|
|
|
public override bool MoveToFirstNamespace(XPathNamespaceScope namespaceScope)
|
|
{
|
|
this.currentPosition = -1;
|
|
return this.navigator.MoveToFirstNamespace(namespaceScope);
|
|
}
|
|
|
|
public override bool MoveToAttribute(string localName, string namespaceURI)
|
|
{
|
|
this.currentPosition = -1;
|
|
return this.navigator.MoveToAttribute(localName, namespaceURI);
|
|
}
|
|
|
|
public override bool MoveToNext()
|
|
{
|
|
this.currentPosition = -1;
|
|
return this.navigator.MoveToNext();
|
|
}
|
|
|
|
public override bool MoveToFirst()
|
|
{
|
|
this.currentPosition = -1;
|
|
return this.navigator.MoveToFirst();
|
|
}
|
|
|
|
internal void SnapshotNavigator()
|
|
{
|
|
this.currentPosition = this.dom.nodes.Count;
|
|
this.dom.nodes.Add(this.navigator.Clone());
|
|
/*
|
|
if (this.currentPosition < this.nodes.Count)
|
|
{
|
|
// Use a cached navigator
|
|
XPathNavigator clonedNavigator = this.nodes[(int)this.currentPosition];
|
|
Fx.Assert(null != clonedNavigator, "");
|
|
clonedNavigator.MoveTo(this);
|
|
}
|
|
else
|
|
{
|
|
this.nodes.Add(this.navigator.Clone());
|
|
}
|
|
*/
|
|
}
|
|
|
|
#region IQueryBufferPool Members
|
|
#if NO
|
|
/// <summary>
|
|
/// Reset the pool by deleting it entirely and starting it over
|
|
/// </summary>
|
|
public void Reset()
|
|
{
|
|
this.nodes.count = 0;
|
|
this.nodes.TrimToCount();
|
|
}
|
|
|
|
public void Trim()
|
|
{
|
|
this.nodes.TrimToCount();
|
|
}
|
|
#endif
|
|
#endregion
|
|
}
|
|
}
|