Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / fx / src / XmlUtils / System / Xml / Xsl / Runtime / XmlSortKey.cs / 1 / XmlSortKey.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //----------------------------------------------------------------------------- using System; using System.Diagnostics; using System.Globalization; namespace System.Xml.Xsl.Runtime { ////// Base internal class for all sort keys. /// Inherits from IComparable, so that Array.Sort can perform comparison. /// internal abstract class XmlSortKey : IComparable { private int priority; // Original input ordering used to ensure that sort is stable private XmlSortKey nextKey; // Next sort key if there are multiple keys (null otherwise) ////// Get or set this key's index, relative to other keys involved in a sort. This priority will /// break ties. If the priority is not set, then the sort will not be stable. /// public int Priority { //get { return this.priority; } set { // All linked keys have same priority XmlSortKey key = this; while (key != null) { key.priority = value; key = key.nextKey; } } } ////// Sometimes a key is composed of multiple parts. For example: (LastName, FirstName). Multi-part /// keys are linked together in a list. This method recursively adds a new key part to the end of the list. /// Returns the first (primary) key in the list. /// public XmlSortKey AddSortKey(XmlSortKey sortKey) { if (this.nextKey != null) { // Add to end of list--this is not it this.nextKey.AddSortKey(sortKey); } else { // This is the end of the list this.nextKey = sortKey; } return this; } ////// When two keys are compared and found to be equal, the tie must be broken. If there is a secondary key, /// then use that to break the tie. Otherwise, use the input ordering to break the tie. Since every key /// has a unique index, this is guaranteed to always break the tie. /// protected int BreakSortingTie(XmlSortKey that) { if (this.nextKey != null) { // There are multiple keys, so break tie using next key Debug.Assert(this.nextKey != null && that.nextKey != null); return this.nextKey.CompareTo(that.nextKey); } Debug.Assert(this.priority != that.priority); return (this.priority < that.priority) ? -1 : 1; } ////// Compare a non-empty key (this) to an empty key (obj). The empty sequence always sorts either before all /// other values, or after all other values. /// protected int CompareToEmpty(object obj) { XmlEmptySortKey that = obj as XmlEmptySortKey; Debug.Assert(that != null && !(this is XmlEmptySortKey)); return that.IsEmptyGreatest ? -1 : 1; } ////// Base internal class is abstract and doesn't actually implement CompareTo; derived classes must do this. /// public abstract int CompareTo(object that); } ////// Sort key for the empty sequence. Empty sequence always compares sorts either before all other values, /// or after all other values. /// internal class XmlEmptySortKey : XmlSortKey { private bool isEmptyGreatest; public XmlEmptySortKey(XmlCollation collation) { // Greatest, Ascending: isEmptyGreatest = true // Greatest, Descending: isEmptyGreatest = false // Least, Ascending: isEmptyGreatest = false // Least, Descending: isEmptyGreatest = true this.isEmptyGreatest = collation.EmptyGreatest != collation.DescendingOrder; } public bool IsEmptyGreatest { get { return this.isEmptyGreatest; } } public override int CompareTo(object obj) { XmlEmptySortKey that = obj as XmlEmptySortKey; if (that == null) { // Empty compared to non-empty Debug.Assert(obj is XmlSortKey); return -(obj as XmlSortKey).CompareTo(this); } // Empty compared to empty return BreakSortingTie(that); } } ////// Sort key for xs:decimal values. /// internal class XmlDecimalSortKey : XmlSortKey { private decimal decVal; public XmlDecimalSortKey(decimal value, XmlCollation collation) { // Invert decimal if sorting in descending order this.decVal = collation.DescendingOrder ? -value : value; } public override int CompareTo(object obj) { XmlDecimalSortKey that = obj as XmlDecimalSortKey; int cmp; if (that == null) return CompareToEmpty(obj); cmp = Decimal.Compare(this.decVal, that.decVal); if (cmp == 0) return BreakSortingTie(that); return cmp; } } ////// Sort key for xs:integer values. /// internal class XmlIntegerSortKey : XmlSortKey { private long longVal; public XmlIntegerSortKey(long value, XmlCollation collation) { // Invert long if sorting in descending order this.longVal = collation.DescendingOrder ? ~value : value; } public override int CompareTo(object obj) { XmlIntegerSortKey that = obj as XmlIntegerSortKey; if (that == null) return CompareToEmpty(obj); if (this.longVal == that.longVal) return BreakSortingTie(that); return (this.longVal < that.longVal) ? -1 : 1; } } ////// Sort key for xs:int values. /// internal class XmlIntSortKey : XmlSortKey { private int intVal; public XmlIntSortKey(int value, XmlCollation collation) { // Invert integer if sorting in descending order this.intVal = collation.DescendingOrder ? ~value : value; } public override int CompareTo(object obj) { XmlIntSortKey that = obj as XmlIntSortKey; if (that == null) return CompareToEmpty(obj); if (this.intVal == that.intVal) return BreakSortingTie(that); return (this.intVal < that.intVal) ? -1 : 1; } } ////// Sort key for xs:string values. Strings are sorted according to a byte-wise sort key calculated by caller. /// internal class XmlStringSortKey : XmlSortKey { private SortKey sortKey; private byte[] sortKeyBytes; private bool descendingOrder; public XmlStringSortKey(SortKey sortKey, bool descendingOrder) { this.sortKey = sortKey; this.descendingOrder = descendingOrder; } public XmlStringSortKey(byte[] sortKey, bool descendingOrder) { this.sortKeyBytes = sortKey; this.descendingOrder = descendingOrder; } public override int CompareTo(object obj) { XmlStringSortKey that = obj as XmlStringSortKey; int idx, cntCmp, result; if (that == null) return CompareToEmpty(obj); // Compare either using SortKey.Compare or byte arrays if (this.sortKey != null) { Debug.Assert(that.sortKey != null, "Both keys must have non-null sortKey field"); result = SortKey.Compare(this.sortKey, that.sortKey); } else { Debug.Assert(this.sortKeyBytes != null && that.sortKeyBytes != null, "Both keys must have non-null sortKeyBytes field"); cntCmp = (this.sortKeyBytes.Length < that.sortKeyBytes.Length) ? this.sortKeyBytes.Length : that.sortKeyBytes.Length; for (idx = 0; idx < cntCmp; idx++) { if (this.sortKeyBytes[idx] < that.sortKeyBytes[idx]) { result = -1; goto Done; } if (this.sortKeyBytes[idx] > that.sortKeyBytes[idx]) { result = 1; goto Done; } } // So far, keys are equal, so now test length of each key if (this.sortKeyBytes.Length < that.sortKeyBytes.Length) result = -1; else if (this.sortKeyBytes.Length > that.sortKeyBytes.Length) result = 1; else result = 0; } Done: // Use document order to break sorting tie if (result == 0) return BreakSortingTie(that); return this.descendingOrder ? -result : result; } } ////// Sort key for Double values. /// internal class XmlDoubleSortKey : XmlSortKey { private double dblVal; private bool isNaN; public XmlDoubleSortKey(double value, XmlCollation collation) { if (Double.IsNaN(value)) { // Treat NaN as if it were the empty sequence this.isNaN = true; // Greatest, Ascending: isEmptyGreatest = true // Greatest, Descending: isEmptyGreatest = false // Least, Ascending: isEmptyGreatest = false // Least, Descending: isEmptyGreatest = true this.dblVal = (collation.EmptyGreatest != collation.DescendingOrder) ? Double.PositiveInfinity : Double.NegativeInfinity; } else { this.dblVal = collation.DescendingOrder ? -value : value; } } public override int CompareTo(object obj) { XmlDoubleSortKey that = obj as XmlDoubleSortKey; if (that == null) { // Compare to empty sequence if (this.isNaN) return BreakSortingTie(obj as XmlSortKey); return CompareToEmpty(obj); } if (this.dblVal == that.dblVal) { if (this.isNaN) { // NaN sorts equal to NaN if (that.isNaN) return BreakSortingTie(that); // NaN sorts before or after all non-NaN values Debug.Assert(this.dblVal == Double.NegativeInfinity || this.dblVal == Double.PositiveInfinity); return (this.dblVal == Double.NegativeInfinity) ? -1 : 1; } else if (that.isNaN) { // NaN sorts before or after all non-NaN values Debug.Assert(that.dblVal == Double.NegativeInfinity || that.dblVal == Double.PositiveInfinity); return (that.dblVal == Double.NegativeInfinity) ? 1 : -1; } return BreakSortingTie(that); } return (this.dblVal < that.dblVal) ? -1 : 1; } } ////// Sort key for DateTime values (just convert DateTime to ticks and use Long sort key). /// internal class XmlDateTimeSortKey : XmlIntegerSortKey { public XmlDateTimeSortKey(DateTime value, XmlCollation collation) : base(value.Ticks, collation) { } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //----------------------------------------------------------------------------- using System; using System.Diagnostics; using System.Globalization; namespace System.Xml.Xsl.Runtime { ////// Base internal class for all sort keys. /// Inherits from IComparable, so that Array.Sort can perform comparison. /// internal abstract class XmlSortKey : IComparable { private int priority; // Original input ordering used to ensure that sort is stable private XmlSortKey nextKey; // Next sort key if there are multiple keys (null otherwise) ////// Get or set this key's index, relative to other keys involved in a sort. This priority will /// break ties. If the priority is not set, then the sort will not be stable. /// public int Priority { //get { return this.priority; } set { // All linked keys have same priority XmlSortKey key = this; while (key != null) { key.priority = value; key = key.nextKey; } } } ////// Sometimes a key is composed of multiple parts. For example: (LastName, FirstName). Multi-part /// keys are linked together in a list. This method recursively adds a new key part to the end of the list. /// Returns the first (primary) key in the list. /// public XmlSortKey AddSortKey(XmlSortKey sortKey) { if (this.nextKey != null) { // Add to end of list--this is not it this.nextKey.AddSortKey(sortKey); } else { // This is the end of the list this.nextKey = sortKey; } return this; } ////// When two keys are compared and found to be equal, the tie must be broken. If there is a secondary key, /// then use that to break the tie. Otherwise, use the input ordering to break the tie. Since every key /// has a unique index, this is guaranteed to always break the tie. /// protected int BreakSortingTie(XmlSortKey that) { if (this.nextKey != null) { // There are multiple keys, so break tie using next key Debug.Assert(this.nextKey != null && that.nextKey != null); return this.nextKey.CompareTo(that.nextKey); } Debug.Assert(this.priority != that.priority); return (this.priority < that.priority) ? -1 : 1; } ////// Compare a non-empty key (this) to an empty key (obj). The empty sequence always sorts either before all /// other values, or after all other values. /// protected int CompareToEmpty(object obj) { XmlEmptySortKey that = obj as XmlEmptySortKey; Debug.Assert(that != null && !(this is XmlEmptySortKey)); return that.IsEmptyGreatest ? -1 : 1; } ////// Base internal class is abstract and doesn't actually implement CompareTo; derived classes must do this. /// public abstract int CompareTo(object that); } ////// Sort key for the empty sequence. Empty sequence always compares sorts either before all other values, /// or after all other values. /// internal class XmlEmptySortKey : XmlSortKey { private bool isEmptyGreatest; public XmlEmptySortKey(XmlCollation collation) { // Greatest, Ascending: isEmptyGreatest = true // Greatest, Descending: isEmptyGreatest = false // Least, Ascending: isEmptyGreatest = false // Least, Descending: isEmptyGreatest = true this.isEmptyGreatest = collation.EmptyGreatest != collation.DescendingOrder; } public bool IsEmptyGreatest { get { return this.isEmptyGreatest; } } public override int CompareTo(object obj) { XmlEmptySortKey that = obj as XmlEmptySortKey; if (that == null) { // Empty compared to non-empty Debug.Assert(obj is XmlSortKey); return -(obj as XmlSortKey).CompareTo(this); } // Empty compared to empty return BreakSortingTie(that); } } ////// Sort key for xs:decimal values. /// internal class XmlDecimalSortKey : XmlSortKey { private decimal decVal; public XmlDecimalSortKey(decimal value, XmlCollation collation) { // Invert decimal if sorting in descending order this.decVal = collation.DescendingOrder ? -value : value; } public override int CompareTo(object obj) { XmlDecimalSortKey that = obj as XmlDecimalSortKey; int cmp; if (that == null) return CompareToEmpty(obj); cmp = Decimal.Compare(this.decVal, that.decVal); if (cmp == 0) return BreakSortingTie(that); return cmp; } } ////// Sort key for xs:integer values. /// internal class XmlIntegerSortKey : XmlSortKey { private long longVal; public XmlIntegerSortKey(long value, XmlCollation collation) { // Invert long if sorting in descending order this.longVal = collation.DescendingOrder ? ~value : value; } public override int CompareTo(object obj) { XmlIntegerSortKey that = obj as XmlIntegerSortKey; if (that == null) return CompareToEmpty(obj); if (this.longVal == that.longVal) return BreakSortingTie(that); return (this.longVal < that.longVal) ? -1 : 1; } } ////// Sort key for xs:int values. /// internal class XmlIntSortKey : XmlSortKey { private int intVal; public XmlIntSortKey(int value, XmlCollation collation) { // Invert integer if sorting in descending order this.intVal = collation.DescendingOrder ? ~value : value; } public override int CompareTo(object obj) { XmlIntSortKey that = obj as XmlIntSortKey; if (that == null) return CompareToEmpty(obj); if (this.intVal == that.intVal) return BreakSortingTie(that); return (this.intVal < that.intVal) ? -1 : 1; } } ////// Sort key for xs:string values. Strings are sorted according to a byte-wise sort key calculated by caller. /// internal class XmlStringSortKey : XmlSortKey { private SortKey sortKey; private byte[] sortKeyBytes; private bool descendingOrder; public XmlStringSortKey(SortKey sortKey, bool descendingOrder) { this.sortKey = sortKey; this.descendingOrder = descendingOrder; } public XmlStringSortKey(byte[] sortKey, bool descendingOrder) { this.sortKeyBytes = sortKey; this.descendingOrder = descendingOrder; } public override int CompareTo(object obj) { XmlStringSortKey that = obj as XmlStringSortKey; int idx, cntCmp, result; if (that == null) return CompareToEmpty(obj); // Compare either using SortKey.Compare or byte arrays if (this.sortKey != null) { Debug.Assert(that.sortKey != null, "Both keys must have non-null sortKey field"); result = SortKey.Compare(this.sortKey, that.sortKey); } else { Debug.Assert(this.sortKeyBytes != null && that.sortKeyBytes != null, "Both keys must have non-null sortKeyBytes field"); cntCmp = (this.sortKeyBytes.Length < that.sortKeyBytes.Length) ? this.sortKeyBytes.Length : that.sortKeyBytes.Length; for (idx = 0; idx < cntCmp; idx++) { if (this.sortKeyBytes[idx] < that.sortKeyBytes[idx]) { result = -1; goto Done; } if (this.sortKeyBytes[idx] > that.sortKeyBytes[idx]) { result = 1; goto Done; } } // So far, keys are equal, so now test length of each key if (this.sortKeyBytes.Length < that.sortKeyBytes.Length) result = -1; else if (this.sortKeyBytes.Length > that.sortKeyBytes.Length) result = 1; else result = 0; } Done: // Use document order to break sorting tie if (result == 0) return BreakSortingTie(that); return this.descendingOrder ? -result : result; } } ////// Sort key for Double values. /// internal class XmlDoubleSortKey : XmlSortKey { private double dblVal; private bool isNaN; public XmlDoubleSortKey(double value, XmlCollation collation) { if (Double.IsNaN(value)) { // Treat NaN as if it were the empty sequence this.isNaN = true; // Greatest, Ascending: isEmptyGreatest = true // Greatest, Descending: isEmptyGreatest = false // Least, Ascending: isEmptyGreatest = false // Least, Descending: isEmptyGreatest = true this.dblVal = (collation.EmptyGreatest != collation.DescendingOrder) ? Double.PositiveInfinity : Double.NegativeInfinity; } else { this.dblVal = collation.DescendingOrder ? -value : value; } } public override int CompareTo(object obj) { XmlDoubleSortKey that = obj as XmlDoubleSortKey; if (that == null) { // Compare to empty sequence if (this.isNaN) return BreakSortingTie(obj as XmlSortKey); return CompareToEmpty(obj); } if (this.dblVal == that.dblVal) { if (this.isNaN) { // NaN sorts equal to NaN if (that.isNaN) return BreakSortingTie(that); // NaN sorts before or after all non-NaN values Debug.Assert(this.dblVal == Double.NegativeInfinity || this.dblVal == Double.PositiveInfinity); return (this.dblVal == Double.NegativeInfinity) ? -1 : 1; } else if (that.isNaN) { // NaN sorts before or after all non-NaN values Debug.Assert(that.dblVal == Double.NegativeInfinity || that.dblVal == Double.PositiveInfinity); return (that.dblVal == Double.NegativeInfinity) ? 1 : -1; } return BreakSortingTie(that); } return (this.dblVal < that.dblVal) ? -1 : 1; } } ////// Sort key for DateTime values (just convert DateTime to ticks and use Long sort key). /// internal class XmlDateTimeSortKey : XmlIntegerSortKey { public XmlDateTimeSortKey(DateTime value, XmlCollation collation) : base(value.Ticks, collation) { } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DeclarativeCatalogPartDesigner.cs
- CodeGenerator.cs
- _ChunkParse.cs
- GridView.cs
- AnnotationAdorner.cs
- DataGridViewButtonCell.cs
- BrushConverter.cs
- GetRecipientListRequest.cs
- RemotingSurrogateSelector.cs
- NameValueSectionHandler.cs
- SecurityRuntime.cs
- FileDataSourceCache.cs
- DataSourceSerializationException.cs
- SerialPinChanges.cs
- MessageBox.cs
- __TransparentProxy.cs
- ExceptionWrapper.cs
- ConstructorBuilder.cs
- FontDifferentiator.cs
- Transform3DGroup.cs
- UnsafeNativeMethods.cs
- HwndSourceKeyboardInputSite.cs
- DCSafeHandle.cs
- XmlHierarchicalDataSourceView.cs
- SqlPersonalizationProvider.cs
- ExtentCqlBlock.cs
- IDQuery.cs
- ColorContextHelper.cs
- UserControl.cs
- WmlValidatorAdapter.cs
- XmlHierarchicalEnumerable.cs
- sqlnorm.cs
- WebPartDisplayModeCancelEventArgs.cs
- ResourceSetExpression.cs
- ChannelSinkStacks.cs
- ToolBarTray.cs
- PartialTrustHelpers.cs
- SystemThemeKey.cs
- ColorAnimationBase.cs
- EditorZoneBase.cs
- XPathDescendantIterator.cs
- QueryCursorEventArgs.cs
- DataGridCellsPresenter.cs
- MulticastIPAddressInformationCollection.cs
- XNodeNavigator.cs
- RepeaterCommandEventArgs.cs
- FontInfo.cs
- NamedPipeTransportBindingElement.cs
- EDesignUtil.cs
- ComPlusTypeValidator.cs
- DataGridHeaderBorder.cs
- InfocardInteractiveChannelInitializer.cs
- QilInvokeEarlyBound.cs
- FlowNode.cs
- ITreeGenerator.cs
- ManagementScope.cs
- LongValidatorAttribute.cs
- SettingsAttributes.cs
- SystemFonts.cs
- UIElementParaClient.cs
- Debug.cs
- SyndicationContent.cs
- RecordBuilder.cs
- Translator.cs
- ProcessingInstructionAction.cs
- WaitForChangedResult.cs
- SystemIPGlobalStatistics.cs
- SQLStringStorage.cs
- ExternalCalls.cs
- DecimalConstantAttribute.cs
- BindingExpressionUncommonField.cs
- SplitContainerDesigner.cs
- dbenumerator.cs
- ExitEventArgs.cs
- DynamicResourceExtension.cs
- XmlUtf8RawTextWriter.cs
- Renderer.cs
- PropertyEmitterBase.cs
- SelectionListComponentEditor.cs
- MinimizableAttributeTypeConverter.cs
- HttpRequestCacheValidator.cs
- TimersDescriptionAttribute.cs
- CommonObjectSecurity.cs
- PermissionSet.cs
- GlyphRunDrawing.cs
- SoundPlayer.cs
- SchemaAttDef.cs
- ErrorLog.cs
- IncomingWebResponseContext.cs
- HttpWebRequest.cs
- DecimalAnimationUsingKeyFrames.cs
- IPGlobalProperties.cs
- XmlSchemaComplexContentExtension.cs
- WsatConfiguration.cs
- WebPartCatalogCloseVerb.cs
- XmlMemberMapping.cs
- PeerApplicationLaunchInfo.cs
- UInt16Storage.cs
- FormViewInsertEventArgs.cs
- TraceLevelStore.cs