Code:
/ FX-1434 / FX-1434 / 1.0 / untmp / whidbey / REDBITS / ndp / fx / src / Xml / System / Xml / XPath / Internal / Query.cs / 2 / Query.cs
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// [....]
//-----------------------------------------------------------------------------
namespace MS.Internal.Xml.XPath {
using System;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl;
using System.Diagnostics;
using System.Collections.Generic;
// See comments to QueryBuilder.Props
// Not all of them are used currently
internal enum QueryProps {
None = 0x00,
Position = 0x01,
Count = 0x02,
Cached = 0x04,
Reverse = 0x08,
Merge = 0x10,
};
// Turn off DebuggerDisplayAttribute. in subclasses of Query.
// Calls to Current in the XPathNavigator.DebuggerDisplayProxy may change state or throw
[DebuggerDisplay("{ToString()}")]
internal abstract class Query : ResetableIterator {
public Query() { }
protected Query(Query other) : base(other) { }
// -- XPathNodeIterator --
//public abstract XPathNodeIterator Clone();
//public abstract XPathNavigator Current { get; }
//public abstract int CurrentPosition { get; }
public override bool MoveNext() { return Advance() != null; }
public override int Count {
get {
// Query can be ordered in reverse order. So we can't assume like base.Count that last node has greatest position.
if (count == -1) {
Query clone = (Query)this.Clone();
clone.Reset();
count = 0;
while (clone.MoveNext()) count ++;
}
return count;
}
}
// ------------- ResetableIterator -----------
// It's importent that Query is resetable. This fact is used in several plases:
// 1. In LogicalExpr: "foo = bar"
// 2. In SelectionOperator.Reset().
// In all this cases Reset() means restart iterate through the same nodes.
// So reset shouldn't clean bufferes in query. This should be done in set context.
//public abstract void Reset();
// -------------------- Query ------------------
public virtual void SetXsltContext(XsltContext context) { }
public abstract object Evaluate(XPathNodeIterator nodeIterator);
public abstract XPathNavigator Advance();
public virtual XPathNavigator MatchNode(XPathNavigator current) {
throw XPathException.Create(Res.Xp_InvalidPattern);
}
public virtual double XsltDefaultPriority { get { return 0.5; } }
public abstract XPathResultType StaticType { get; }
public virtual QueryProps Properties { get { return QueryProps.Merge; } }
// ----------------- Helper methods -------------
public static Query Clone(Query input) {
if (input != null) {
return (Query)input.Clone();
}
return null;
}
protected static XPathNodeIterator Clone(XPathNodeIterator input) {
if (input != null) {
return input.Clone();
}
return null;
}
protected static XPathNavigator Clone(XPathNavigator input) {
if (input != null) {
return input.Clone();
}
return null;
}
// -----------------------------------------------------
// Set of methods to support insertion to sorted buffer.
// buffer is always sorted here
public bool Insert(List buffer, XPathNavigator nav) {
int l = 0;
int r = buffer.Count;
// In most cases nodes are already sorted.
// This means that nav often will be equal or after then last item in the buffer
// So let's check this first.
if (r != 0) {
switch (CompareNodes(buffer[r - 1], nav)) {
case XmlNodeOrder.Same:
return false;
case XmlNodeOrder.Before:
buffer.Add(nav.Clone());
return true;
default:
r --;
break;
}
}
while (l < r) {
int m = GetMedian(l, r);
switch (CompareNodes(buffer[m], nav)) {
case XmlNodeOrder.Same:
return false;
case XmlNodeOrder.Before:
l = m + 1;
break;
default:
r = m;
break;
}
}
AssertDOD(buffer, nav, l);
buffer.Insert(l, nav.Clone());
return true;
}
private static int GetMedian(int l, int r) {
Debug.Assert(0 <= l && l < r);
return (int) (((uint) l + (uint) r) >> 1);
}
public static XmlNodeOrder CompareNodes(XPathNavigator l, XPathNavigator r) {
XmlNodeOrder cmp = l.ComparePosition(r);
if (cmp == XmlNodeOrder.Unknown) {
XPathNavigator copy = l.Clone();
copy.MoveToRoot();
string baseUriL = copy.BaseURI;
if (! copy.MoveTo(r)) {
copy = r.Clone();
}
copy.MoveToRoot();
string baseUriR = copy.BaseURI;
int cmpBase = string.CompareOrdinal(baseUriL, baseUriR);
cmp = (
cmpBase < 0 ? XmlNodeOrder.Before :
cmpBase > 0 ? XmlNodeOrder.After :
/*default*/ XmlNodeOrder.Unknown
);
}
return cmp;
}
[Conditional("DEBUG")]
private void AssertDOD(List buffer, XPathNavigator nav, int pos) {
if (nav.GetType().ToString() == "Microsoft.VisualStudio.Modeling.StoreNavigator") return;
if (nav.GetType().ToString() == "System.Xml.DataDocumentXPathNavigator") return;
Debug.Assert(0 <= pos && pos <= buffer.Count, "Algorithm error: Insert()");
XmlNodeOrder cmp;
if (0 < pos) {
cmp = CompareNodes(buffer[pos - 1], nav);
Debug.Assert(cmp == XmlNodeOrder.Before, "Algorithm error: Insert()");
}
if (pos < buffer.Count) {
cmp = CompareNodes(nav, buffer[pos]);
Debug.Assert(cmp == XmlNodeOrder.Before, "Algorithm error: Insert()");
}
}
[Conditional("DEBUG")]
public static void AssertQuery(Query query) {
Debug.Assert(query != null, "AssertQuery(): query == null");
if (query is FunctionQuery) return; // Temp Fix. Functions (as document()) return now unordered sequences
query = Clone(query);
XPathNavigator last = null;
XPathNavigator curr;
int querySize = query.Clone().Count;
int actualSize = 0;
while ((curr = query.Advance()) != null) {
if (curr.GetType().ToString() == "Microsoft.VisualStudio.Modeling.StoreNavigator") return;
if (curr.GetType().ToString() == "System.Xml.DataDocumentXPathNavigator") return;
Debug.Assert(curr == query.Current, "AssertQuery(): query.Advance() != query.Current");
if (last != null) {
if (last.NodeType == XPathNodeType.Namespace && curr.NodeType == XPathNodeType.Namespace) {
// NamespaceQuery reports namsespaces in mixed order.
// Ignore this for now.
// It seams that this doesn't breake other queries becasue NS can't have children
} else {
XmlNodeOrder cmp = CompareNodes(last, curr);
Debug.Assert(cmp == XmlNodeOrder.Before, "AssertQuery(): Wrong node order");
}
}
last = curr.Clone();
actualSize++;
}
Debug.Assert(actualSize == querySize, "AssertQuery(): actualSize != querySize");
}
// =================== XPathResultType_Navigator ======================
// In v.1.0 and v.1.1 XPathResultType.Navigator is defined == to XPathResultType.String
// This is source for multiple bugs or additional type casts.
// To fix all of them in one change in v.2 we internaly use one more value:
public const XPathResultType XPathResultType_Navigator = (XPathResultType) 4;
// The biggest challenge in this change is preserve backward compatibility with v.1.1
// To achive this in all places where we accept from or report to user XPathResultType.
// On my best knowledge this happens only in XsltContext.ResolveFunction() / IXsltContextFunction.ReturnType
protected XPathResultType GetXPathType(object value) {
if (value is XPathNodeIterator) return XPathResultType.NodeSet;
if (value is string ) return XPathResultType.String;
if (value is double ) return XPathResultType.Number;
if (value is bool ) return XPathResultType.Boolean;
Debug.Assert(value is XPathNavigator, "Unknown value type");
return XPathResultType_Navigator;
}
// =================== Serialization ======================
public virtual void PrintQuery(XmlWriter w) {
w.WriteElementString(this.GetType().Name, string.Empty);
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- Emitter.cs
- XPathNode.cs
- ConfigsHelper.cs
- ECDiffieHellmanPublicKey.cs
- ActivitySurrogate.cs
- WindowHideOrCloseTracker.cs
- TailCallAnalyzer.cs
- ProcessModelInfo.cs
- LostFocusEventManager.cs
- Win32KeyboardDevice.cs
- BackoffTimeoutHelper.cs
- XmlSortKey.cs
- TypeReference.cs
- AnnouncementService.cs
- Thumb.cs
- BaseCollection.cs
- ExceptionRoutedEventArgs.cs
- SoundPlayer.cs
- SocketAddress.cs
- XmlEntityReference.cs
- Point3DCollectionValueSerializer.cs
- SQLGuidStorage.cs
- DataKey.cs
- FileReservationCollection.cs
- Style.cs
- GridViewAutomationPeer.cs
- Separator.cs
- DataGridColumn.cs
- FrugalList.cs
- TaiwanLunisolarCalendar.cs
- NumberFormatInfo.cs
- Config.cs
- DebugManager.cs
- DrawListViewColumnHeaderEventArgs.cs
- hresults.cs
- SafeFileMapViewHandle.cs
- RequestCachePolicyConverter.cs
- _BufferOffsetSize.cs
- Command.cs
- Activation.cs
- TextEditorSpelling.cs
- DiagnosticTraceSource.cs
- Win32Exception.cs
- MatrixAnimationUsingPath.cs
- TreeNodeStyle.cs
- MouseActionValueSerializer.cs
- GeneralTransform3D.cs
- XmlStreamStore.cs
- ProgressiveCrcCalculatingStream.cs
- PenThreadWorker.cs
- TextParaLineResult.cs
- WmlPageAdapter.cs
- SamlSerializer.cs
- CommandBinding.cs
- Int32EqualityComparer.cs
- AutomationPropertyInfo.cs
- XmlSchemaIdentityConstraint.cs
- ChangeTracker.cs
- DataBindingList.cs
- MembershipUser.cs
- DbMetaDataColumnNames.cs
- LineServices.cs
- DynamicPropertyHolder.cs
- SessionStateSection.cs
- ViewValidator.cs
- MetadataAssemblyHelper.cs
- OLEDB_Util.cs
- TextViewSelectionProcessor.cs
- DiscoveryOperationContextExtension.cs
- X509Certificate.cs
- EntityDataSourceUtil.cs
- PermissionListSet.cs
- PassportAuthenticationEventArgs.cs
- GridPattern.cs
- InboundActivityHelper.cs
- BitHelper.cs
- DynamicUpdateCommand.cs
- Propagator.JoinPropagator.cs
- OracleFactory.cs
- RemotingConfiguration.cs
- DeferredTextReference.cs
- InfoCardSymmetricCrypto.cs
- StaticFileHandler.cs
- DesignSurfaceManager.cs
- PerformanceCounterPermissionEntry.cs
- UserControlBuildProvider.cs
- ResXResourceSet.cs
- FrameworkTemplate.cs
- GregorianCalendarHelper.cs
- SafeEventLogReadHandle.cs
- ProbeDuplexCD1AsyncResult.cs
- XamlInt32CollectionSerializer.cs
- ObjectView.cs
- ExtenderProvidedPropertyAttribute.cs
- VBCodeProvider.cs
- InfocardChannelParameter.cs
- Compress.cs
- _HelperAsyncResults.cs
- RegexCaptureCollection.cs
- RenderContext.cs