Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / ndp / fx / src / XmlUtils / System / Xml / Xsl / Runtime / XmlCollation.cs / 1 / XmlCollation.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //----------------------------------------------------------------------------- using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; namespace System.Xml.Xsl.Runtime { using Res = System.Xml.Utils.Res; [EditorBrowsable(EditorBrowsableState.Never)] public sealed class XmlCollation { // lgid support for sort private const int deDE = 0x0407; private const int huHU = 0x040E; private const int jaJP = 0x0411; private const int kaGE = 0x0437; private const int koKR = 0x0412; private const int zhTW = 0x0404; private const int zhCN = 0x0804; private const int zhHK = 0x0C04; private const int zhSG = 0x1004; private const int zhMO = 0x1404; private const int zhTWbopo = 0x030404; private const int deDEphon = 0x010407; private const int huHUtech = 0x01040e; private const int kaGEmode = 0x010437; // Sort ID private const int strksort = 0x02; // Stroke private const int unicsort = 0x01; // Unicode // Options private const string ignoreCaseStr = "IGNORECASE"; private const string ignoreKanatypeStr = "IGNOREKANATYPE"; private const string ignoreNonspaceStr = "IGNORENONSPACE"; private const string ignoreSymbolsStr = "IGNORESYMBOLS"; private const string ignoreWidthStr = "IGNOREWIDTH"; private const string upperFirstStr = "UPPERFIRST"; private const string emptyGreatestStr = "EMPTYGREATEST"; private const string descendingOrderStr = "DESCENDINGORDER"; private const string sortStr = "SORT"; private bool upperFirst; private bool emptyGreatest; private bool descendingOrder; private CultureInfo cultinfo; private CompareOptions compops; //----------------------------------------------- // Constructors //----------------------------------------------- ////// By default, create a collation that uses the current thread's culture, and has no compare options set /// private XmlCollation() : this(null, CompareOptions.None) { } ////// Construct a collation that uses the specified culture and compare options. /// private XmlCollation(CultureInfo cultureInfo, CompareOptions compareOptions) { this.cultinfo = cultureInfo; this.compops = compareOptions; } //----------------------------------------------- // Create //----------------------------------------------- ////// Singleton collation that sorts according to Unicode code points. /// private static XmlCollation cp = new XmlCollation(CultureInfo.InvariantCulture, CompareOptions.Ordinal); internal static XmlCollation CodePointCollation { get { return cp; } } ////// This function is used in both parser and f&o library, so just strictly map valid literals to XmlCollation. /// Set compare options one by one: /// 0, false: no effect; 1, true: yes /// Disregard unrecognized options. /// internal static XmlCollation Create(string collationLiteral) { Debug.Assert(collationLiteral != null, "collation literal should not be null"); if (collationLiteral == XmlReservedNs.NsCollCodePoint) { return CodePointCollation; } XmlCollation coll = new XmlCollation(); Uri collationUri = new Uri(collationLiteral); string authority = collationUri.GetLeftPart(UriPartial.Authority); if (authority == XmlReservedNs.NsCollationBase) { // Language // at least a '/' will be returned for Uri.LocalPath string lang = collationUri.LocalPath.Substring(1); if (lang.Length == 0) { // Use default culture of current thread (cultinfo = null) } else { // Create culture from RFC 1766 string try { coll.cultinfo = new CultureInfo(lang); } catch (ArgumentException) { throw new XslTransformException(Res.Coll_UnsupportedLanguage, lang); } } } else if (collationUri.IsBaseOf(new Uri(XmlReservedNs.NsCollCodePoint))) { // language with codepoint collation is not allowed coll.compops = CompareOptions.Ordinal; } else { // Unrecognized collation throw new XslTransformException(Res.Coll_Unsupported, collationLiteral); } // Sort & Compare option // at least a '?' will be returned for Uri.Query if not empty string query = collationUri.Query; string sort = null; if (query.Length != 0) { foreach (string option in query.Substring(1).Split('&')) { string[] pair = option.Split('='); if (pair.Length != 2) throw new XslTransformException(Res.Coll_BadOptFormat, option); string optionName = pair[0].ToUpper(CultureInfo.InvariantCulture); string optionValue = pair[1].ToUpper(CultureInfo.InvariantCulture); if (optionName == sortStr) { sort = optionValue; } else if (optionValue == "1" || optionValue == "TRUE") { switch (optionName) { case ignoreCaseStr: coll.compops |= CompareOptions.IgnoreCase; break; case ignoreKanatypeStr: coll.compops |= CompareOptions.IgnoreKanaType; break; case ignoreNonspaceStr: coll.compops |= CompareOptions.IgnoreNonSpace; break; case ignoreSymbolsStr: coll.compops |= CompareOptions.IgnoreSymbols; break; case ignoreWidthStr: coll.compops |= CompareOptions.IgnoreWidth; break; case upperFirstStr: coll.upperFirst = true; break; case emptyGreatestStr: coll.emptyGreatest = true; break; case descendingOrderStr: coll.descendingOrder = true; break; default: throw new XslTransformException(Res.Coll_UnsupportedOpt, pair[0]); } } else if (optionValue == "0" || optionValue == "FALSE") { switch (optionName) { case ignoreCaseStr: coll.compops &= ~CompareOptions.IgnoreCase; break; case ignoreKanatypeStr: coll.compops &= ~CompareOptions.IgnoreKanaType; break; case ignoreNonspaceStr: coll.compops &= ~CompareOptions.IgnoreNonSpace; break; case ignoreSymbolsStr: coll.compops &= ~CompareOptions.IgnoreSymbols; break; case ignoreWidthStr: coll.compops &= ~CompareOptions.IgnoreWidth; break; case upperFirstStr: coll.upperFirst = false; break; case emptyGreatestStr: coll.emptyGreatest = false; break; case descendingOrderStr: coll.descendingOrder = false; break; default: throw new XslTransformException(Res.Coll_UnsupportedOpt, pair[0]); } } else { throw new XslTransformException(Res.Coll_UnsupportedOptVal, pair[0], pair[1]); } } } // upperfirst option is only meaningful when not ignore case if (coll.upperFirst && (coll.compops & CompareOptions.IgnoreCase) != 0) coll.upperFirst = false; // other CompareOptions are only meaningful if Ordinal comparison is not being used if ((coll.compops & CompareOptions.Ordinal) != 0) { coll.compops = CompareOptions.Ordinal; coll.upperFirst = false; } // new cultureinfo based on alternate sorting option if (sort != null && coll.cultinfo != null) { int lgid = GetLangID(coll.cultinfo.LCID); switch (sort) { case "bopo": if (lgid == zhTW) { coll.cultinfo = new CultureInfo(zhTWbopo); } break; case "strk": if (lgid == zhCN || lgid == zhHK || lgid == zhSG || lgid == zhMO) { coll.cultinfo = new CultureInfo(MakeLCID(coll.cultinfo.LCID, strksort)); } break; case "uni": if (lgid == jaJP || lgid == koKR) { coll.cultinfo = new CultureInfo(MakeLCID(coll.cultinfo.LCID, unicsort)); } break; case "phn": if (lgid == deDE) { coll.cultinfo = new CultureInfo(deDEphon); } break; case "tech": if (lgid == huHU) { coll.cultinfo = new CultureInfo(huHUtech); } break; case "mod": // ka-GE(Georgian - Georgia) Modern Sort: 0x00010437 if (lgid == kaGE) { coll.cultinfo = new CultureInfo(kaGEmode); } break; case "pron": case "dict": case "trad": // es-ES(Spanish - Spain) Traditional: 0x0000040A // They are removing 0x040a (Spanish Traditional sort) in NLS+. // So if you create 0x040a, it's just like 0x0c0a (Spanish International sort). // Thus I don't handle it differently. break; default: throw new XslTransformException(Res.Coll_UnsupportedSortOpt, sort); } } return coll; } //----------------------------------------------- // Convert options to and from an integer //----------------------------------------------- private const int FlagUpperFirst = 0x1000; private const int FlagEmptyGreatest = 0x2000; private const int FlagDescendingOrder = 0x4000; private const int CollationFlagsMask = FlagUpperFirst | FlagEmptyGreatest | FlagDescendingOrder; private int GetOptions() { int result = (int)this.compops; Debug.Assert((result & CollationFlagsMask) == 0, "CompareOptions and collation flags overlap"); if (upperFirst) result |= FlagUpperFirst; if (emptyGreatest) result |= FlagEmptyGreatest; if (descendingOrder) result |= FlagDescendingOrder; return result; } private void SetOptions(int options) { this.upperFirst = (options & FlagUpperFirst ) != 0; this.emptyGreatest = (options & FlagEmptyGreatest ) != 0; this.descendingOrder = (options & FlagDescendingOrder) != 0; this.compops = (CompareOptions)(options & ~CollationFlagsMask); } //----------------------------------------------- // Collection Support //----------------------------------------------- // Redefine Equals and GetHashCode methods, they are needed for UniqueListpublic override bool Equals(object obj) { if (this == obj) { return true; } XmlCollation that = obj as XmlCollation; return that != null && this.GetOptions() == that.GetOptions() && object.Equals(this.cultinfo, that.cultinfo); } public override int GetHashCode() { int hashCode = this.GetOptions(); if (this.cultinfo != null) { hashCode ^= this.cultinfo.GetHashCode(); } return hashCode; } //----------------------------------------------- // Serialization Support //----------------------------------------------- // Denotes the current thread locale private const int LOCALE_CURRENT = -1; internal void GetObjectData(BinaryWriter writer) { // NOTE: For CultureInfo we serialize only LCID. It seems to suffice for our purposes. Debug.Assert(this.cultinfo == null || this.cultinfo.Equals(new CultureInfo(this.cultinfo.LCID)), "Cannot serialize CultureInfo correctly"); writer.Write(this.cultinfo != null ? this.cultinfo.LCID : LOCALE_CURRENT); writer.Write(this.GetOptions()); } internal XmlCollation(BinaryReader reader) { int lcid = reader.ReadInt32(); this.cultinfo = (lcid != LOCALE_CURRENT) ? new CultureInfo(lcid) : null; this.SetOptions(reader.ReadInt32()); } //----------------------------------------------- // Compare Properties //----------------------------------------------- internal bool EmptyGreatest { get { return this.emptyGreatest; } } internal bool DescendingOrder { get { return this.descendingOrder; } } internal CultureInfo Culture { get { // Use default thread culture if this.cultinfo = null if (this.cultinfo == null) return CultureInfo.CurrentCulture; return this.cultinfo; } } //----------------------------------------------- // //----------------------------------------------- /// /// Create a sort key that can be compared quickly with other keys. /// internal XmlSortKey CreateSortKey(string s) { SortKey sortKey; byte[] bytesKey; int idx; // sortKey = Culture.CompareInfo.GetSortKey(s, this.compops); // Create an XmlStringSortKey using the SortKey if possible #if DEBUG // In debug-only code, test other code path more frequently if (!this.upperFirst && this.descendingOrder) return new XmlStringSortKey(sortKey, this.descendingOrder); #else if (!this.upperFirst) return new XmlStringSortKey(sortKey, this.descendingOrder); #endif // Get byte buffer from SortKey and modify it bytesKey = sortKey.KeyData; if (this.upperFirst && bytesKey.Length != 0) { // By default lower-case is always sorted first for any locale (verified by empirical testing). // In order to place upper-case first, invert the case weights in the generated sort key. // Skip to case weight section (3rd weight section) idx = 0; while (bytesKey[idx] != 1) idx++; do { idx++; } while (bytesKey[idx] != 1); // Invert all case weights (including terminating 0x1) do { idx++; bytesKey[idx] ^= 0xff; } while (bytesKey[idx] != 0xfe); } return new XmlStringSortKey(bytesKey, this.descendingOrder); } #if not_used ////// Compare two strings with each other. Return <0 if str1 sorts before str2, 0 if they're equal, and >0 /// if str1 sorts after str2. /// internal int Compare(string str1, string str2) { CultureInfo cultinfo = Culture; int result; if (UseOrdinalCompare) { result = string.CompareOrdinal(str1, str2); if (result < 0) result = -1; else if (result > 0) result = 1; } else if (this.upperFirst) { // First compare case-insensitive, then break ties by considering case result = cultinfo.CompareInfo.Compare(str1, str2, this.compops | CompareOptions.IgnoreCase); if (result == 0) result = -cultinfo.CompareInfo.Compare(str1, str2, this.compops); } else { result = cultinfo.CompareInfo.Compare(str1, str2, this.compops); } if (this.descendingOrder) result = -result; return result; } ////// Return the index of str1 in str2, or -1 if str1 is not a substring of str2. /// internal int IndexOf(string str1, string str2) { return Culture.CompareInfo.IndexOf(str1, str2, this.compops); } ////// Return true if str1 ends with str2. /// internal bool IsSuffix(string str1, string str2) { if (UseOrdinalCompare){ if (str1.Length < str2.Length) { return false; } else { return String.CompareOrdinal(str1, str1.Length - str2.Length, str2, 0, str2.Length) == 0; } } return Culture.CompareInfo.IsSuffix (str1, str2, this.compops); } ////// Return true if str1 starts with str2. /// internal bool IsPrefix(string str1, string str2) { if (UseOrdinalCompare) { if (str1.Length < str2.Length) { return false; } else { return String.CompareOrdinal(str1, 0, str2, 0, str2.Length) == 0; } } return Culture.CompareInfo.IsPrefix (str1, str2, this.compops); } private bool UseOrdinalCompare { get { return (this.compops & CompareOptions.Ordinal) != 0; } } #endif //----------------------------------------------- // Helper Functions //----------------------------------------------- private static int MakeLCID(int langid, int sortid) { return (langid & 0xffff) | ((sortid & 0xf) << 16); } private static int GetLangID(int lcid) { return (lcid & 0xffff); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //----------------------------------------------------------------------------- using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; namespace System.Xml.Xsl.Runtime { using Res = System.Xml.Utils.Res; [EditorBrowsable(EditorBrowsableState.Never)] public sealed class XmlCollation { // lgid support for sort private const int deDE = 0x0407; private const int huHU = 0x040E; private const int jaJP = 0x0411; private const int kaGE = 0x0437; private const int koKR = 0x0412; private const int zhTW = 0x0404; private const int zhCN = 0x0804; private const int zhHK = 0x0C04; private const int zhSG = 0x1004; private const int zhMO = 0x1404; private const int zhTWbopo = 0x030404; private const int deDEphon = 0x010407; private const int huHUtech = 0x01040e; private const int kaGEmode = 0x010437; // Sort ID private const int strksort = 0x02; // Stroke private const int unicsort = 0x01; // Unicode // Options private const string ignoreCaseStr = "IGNORECASE"; private const string ignoreKanatypeStr = "IGNOREKANATYPE"; private const string ignoreNonspaceStr = "IGNORENONSPACE"; private const string ignoreSymbolsStr = "IGNORESYMBOLS"; private const string ignoreWidthStr = "IGNOREWIDTH"; private const string upperFirstStr = "UPPERFIRST"; private const string emptyGreatestStr = "EMPTYGREATEST"; private const string descendingOrderStr = "DESCENDINGORDER"; private const string sortStr = "SORT"; private bool upperFirst; private bool emptyGreatest; private bool descendingOrder; private CultureInfo cultinfo; private CompareOptions compops; //----------------------------------------------- // Constructors //----------------------------------------------- ////// By default, create a collation that uses the current thread's culture, and has no compare options set /// private XmlCollation() : this(null, CompareOptions.None) { } ////// Construct a collation that uses the specified culture and compare options. /// private XmlCollation(CultureInfo cultureInfo, CompareOptions compareOptions) { this.cultinfo = cultureInfo; this.compops = compareOptions; } //----------------------------------------------- // Create //----------------------------------------------- ////// Singleton collation that sorts according to Unicode code points. /// private static XmlCollation cp = new XmlCollation(CultureInfo.InvariantCulture, CompareOptions.Ordinal); internal static XmlCollation CodePointCollation { get { return cp; } } ////// This function is used in both parser and f&o library, so just strictly map valid literals to XmlCollation. /// Set compare options one by one: /// 0, false: no effect; 1, true: yes /// Disregard unrecognized options. /// internal static XmlCollation Create(string collationLiteral) { Debug.Assert(collationLiteral != null, "collation literal should not be null"); if (collationLiteral == XmlReservedNs.NsCollCodePoint) { return CodePointCollation; } XmlCollation coll = new XmlCollation(); Uri collationUri = new Uri(collationLiteral); string authority = collationUri.GetLeftPart(UriPartial.Authority); if (authority == XmlReservedNs.NsCollationBase) { // Language // at least a '/' will be returned for Uri.LocalPath string lang = collationUri.LocalPath.Substring(1); if (lang.Length == 0) { // Use default culture of current thread (cultinfo = null) } else { // Create culture from RFC 1766 string try { coll.cultinfo = new CultureInfo(lang); } catch (ArgumentException) { throw new XslTransformException(Res.Coll_UnsupportedLanguage, lang); } } } else if (collationUri.IsBaseOf(new Uri(XmlReservedNs.NsCollCodePoint))) { // language with codepoint collation is not allowed coll.compops = CompareOptions.Ordinal; } else { // Unrecognized collation throw new XslTransformException(Res.Coll_Unsupported, collationLiteral); } // Sort & Compare option // at least a '?' will be returned for Uri.Query if not empty string query = collationUri.Query; string sort = null; if (query.Length != 0) { foreach (string option in query.Substring(1).Split('&')) { string[] pair = option.Split('='); if (pair.Length != 2) throw new XslTransformException(Res.Coll_BadOptFormat, option); string optionName = pair[0].ToUpper(CultureInfo.InvariantCulture); string optionValue = pair[1].ToUpper(CultureInfo.InvariantCulture); if (optionName == sortStr) { sort = optionValue; } else if (optionValue == "1" || optionValue == "TRUE") { switch (optionName) { case ignoreCaseStr: coll.compops |= CompareOptions.IgnoreCase; break; case ignoreKanatypeStr: coll.compops |= CompareOptions.IgnoreKanaType; break; case ignoreNonspaceStr: coll.compops |= CompareOptions.IgnoreNonSpace; break; case ignoreSymbolsStr: coll.compops |= CompareOptions.IgnoreSymbols; break; case ignoreWidthStr: coll.compops |= CompareOptions.IgnoreWidth; break; case upperFirstStr: coll.upperFirst = true; break; case emptyGreatestStr: coll.emptyGreatest = true; break; case descendingOrderStr: coll.descendingOrder = true; break; default: throw new XslTransformException(Res.Coll_UnsupportedOpt, pair[0]); } } else if (optionValue == "0" || optionValue == "FALSE") { switch (optionName) { case ignoreCaseStr: coll.compops &= ~CompareOptions.IgnoreCase; break; case ignoreKanatypeStr: coll.compops &= ~CompareOptions.IgnoreKanaType; break; case ignoreNonspaceStr: coll.compops &= ~CompareOptions.IgnoreNonSpace; break; case ignoreSymbolsStr: coll.compops &= ~CompareOptions.IgnoreSymbols; break; case ignoreWidthStr: coll.compops &= ~CompareOptions.IgnoreWidth; break; case upperFirstStr: coll.upperFirst = false; break; case emptyGreatestStr: coll.emptyGreatest = false; break; case descendingOrderStr: coll.descendingOrder = false; break; default: throw new XslTransformException(Res.Coll_UnsupportedOpt, pair[0]); } } else { throw new XslTransformException(Res.Coll_UnsupportedOptVal, pair[0], pair[1]); } } } // upperfirst option is only meaningful when not ignore case if (coll.upperFirst && (coll.compops & CompareOptions.IgnoreCase) != 0) coll.upperFirst = false; // other CompareOptions are only meaningful if Ordinal comparison is not being used if ((coll.compops & CompareOptions.Ordinal) != 0) { coll.compops = CompareOptions.Ordinal; coll.upperFirst = false; } // new cultureinfo based on alternate sorting option if (sort != null && coll.cultinfo != null) { int lgid = GetLangID(coll.cultinfo.LCID); switch (sort) { case "bopo": if (lgid == zhTW) { coll.cultinfo = new CultureInfo(zhTWbopo); } break; case "strk": if (lgid == zhCN || lgid == zhHK || lgid == zhSG || lgid == zhMO) { coll.cultinfo = new CultureInfo(MakeLCID(coll.cultinfo.LCID, strksort)); } break; case "uni": if (lgid == jaJP || lgid == koKR) { coll.cultinfo = new CultureInfo(MakeLCID(coll.cultinfo.LCID, unicsort)); } break; case "phn": if (lgid == deDE) { coll.cultinfo = new CultureInfo(deDEphon); } break; case "tech": if (lgid == huHU) { coll.cultinfo = new CultureInfo(huHUtech); } break; case "mod": // ka-GE(Georgian - Georgia) Modern Sort: 0x00010437 if (lgid == kaGE) { coll.cultinfo = new CultureInfo(kaGEmode); } break; case "pron": case "dict": case "trad": // es-ES(Spanish - Spain) Traditional: 0x0000040A // They are removing 0x040a (Spanish Traditional sort) in NLS+. // So if you create 0x040a, it's just like 0x0c0a (Spanish International sort). // Thus I don't handle it differently. break; default: throw new XslTransformException(Res.Coll_UnsupportedSortOpt, sort); } } return coll; } //----------------------------------------------- // Convert options to and from an integer //----------------------------------------------- private const int FlagUpperFirst = 0x1000; private const int FlagEmptyGreatest = 0x2000; private const int FlagDescendingOrder = 0x4000; private const int CollationFlagsMask = FlagUpperFirst | FlagEmptyGreatest | FlagDescendingOrder; private int GetOptions() { int result = (int)this.compops; Debug.Assert((result & CollationFlagsMask) == 0, "CompareOptions and collation flags overlap"); if (upperFirst) result |= FlagUpperFirst; if (emptyGreatest) result |= FlagEmptyGreatest; if (descendingOrder) result |= FlagDescendingOrder; return result; } private void SetOptions(int options) { this.upperFirst = (options & FlagUpperFirst ) != 0; this.emptyGreatest = (options & FlagEmptyGreatest ) != 0; this.descendingOrder = (options & FlagDescendingOrder) != 0; this.compops = (CompareOptions)(options & ~CollationFlagsMask); } //----------------------------------------------- // Collection Support //----------------------------------------------- // Redefine Equals and GetHashCode methods, they are needed for UniqueListpublic override bool Equals(object obj) { if (this == obj) { return true; } XmlCollation that = obj as XmlCollation; return that != null && this.GetOptions() == that.GetOptions() && object.Equals(this.cultinfo, that.cultinfo); } public override int GetHashCode() { int hashCode = this.GetOptions(); if (this.cultinfo != null) { hashCode ^= this.cultinfo.GetHashCode(); } return hashCode; } //----------------------------------------------- // Serialization Support //----------------------------------------------- // Denotes the current thread locale private const int LOCALE_CURRENT = -1; internal void GetObjectData(BinaryWriter writer) { // NOTE: For CultureInfo we serialize only LCID. It seems to suffice for our purposes. Debug.Assert(this.cultinfo == null || this.cultinfo.Equals(new CultureInfo(this.cultinfo.LCID)), "Cannot serialize CultureInfo correctly"); writer.Write(this.cultinfo != null ? this.cultinfo.LCID : LOCALE_CURRENT); writer.Write(this.GetOptions()); } internal XmlCollation(BinaryReader reader) { int lcid = reader.ReadInt32(); this.cultinfo = (lcid != LOCALE_CURRENT) ? new CultureInfo(lcid) : null; this.SetOptions(reader.ReadInt32()); } //----------------------------------------------- // Compare Properties //----------------------------------------------- internal bool EmptyGreatest { get { return this.emptyGreatest; } } internal bool DescendingOrder { get { return this.descendingOrder; } } internal CultureInfo Culture { get { // Use default thread culture if this.cultinfo = null if (this.cultinfo == null) return CultureInfo.CurrentCulture; return this.cultinfo; } } //----------------------------------------------- // //----------------------------------------------- /// /// Create a sort key that can be compared quickly with other keys. /// internal XmlSortKey CreateSortKey(string s) { SortKey sortKey; byte[] bytesKey; int idx; // sortKey = Culture.CompareInfo.GetSortKey(s, this.compops); // Create an XmlStringSortKey using the SortKey if possible #if DEBUG // In debug-only code, test other code path more frequently if (!this.upperFirst && this.descendingOrder) return new XmlStringSortKey(sortKey, this.descendingOrder); #else if (!this.upperFirst) return new XmlStringSortKey(sortKey, this.descendingOrder); #endif // Get byte buffer from SortKey and modify it bytesKey = sortKey.KeyData; if (this.upperFirst && bytesKey.Length != 0) { // By default lower-case is always sorted first for any locale (verified by empirical testing). // In order to place upper-case first, invert the case weights in the generated sort key. // Skip to case weight section (3rd weight section) idx = 0; while (bytesKey[idx] != 1) idx++; do { idx++; } while (bytesKey[idx] != 1); // Invert all case weights (including terminating 0x1) do { idx++; bytesKey[idx] ^= 0xff; } while (bytesKey[idx] != 0xfe); } return new XmlStringSortKey(bytesKey, this.descendingOrder); } #if not_used ////// Compare two strings with each other. Return <0 if str1 sorts before str2, 0 if they're equal, and >0 /// if str1 sorts after str2. /// internal int Compare(string str1, string str2) { CultureInfo cultinfo = Culture; int result; if (UseOrdinalCompare) { result = string.CompareOrdinal(str1, str2); if (result < 0) result = -1; else if (result > 0) result = 1; } else if (this.upperFirst) { // First compare case-insensitive, then break ties by considering case result = cultinfo.CompareInfo.Compare(str1, str2, this.compops | CompareOptions.IgnoreCase); if (result == 0) result = -cultinfo.CompareInfo.Compare(str1, str2, this.compops); } else { result = cultinfo.CompareInfo.Compare(str1, str2, this.compops); } if (this.descendingOrder) result = -result; return result; } ////// Return the index of str1 in str2, or -1 if str1 is not a substring of str2. /// internal int IndexOf(string str1, string str2) { return Culture.CompareInfo.IndexOf(str1, str2, this.compops); } ////// Return true if str1 ends with str2. /// internal bool IsSuffix(string str1, string str2) { if (UseOrdinalCompare){ if (str1.Length < str2.Length) { return false; } else { return String.CompareOrdinal(str1, str1.Length - str2.Length, str2, 0, str2.Length) == 0; } } return Culture.CompareInfo.IsSuffix (str1, str2, this.compops); } ////// Return true if str1 starts with str2. /// internal bool IsPrefix(string str1, string str2) { if (UseOrdinalCompare) { if (str1.Length < str2.Length) { return false; } else { return String.CompareOrdinal(str1, 0, str2, 0, str2.Length) == 0; } } return Culture.CompareInfo.IsPrefix (str1, str2, this.compops); } private bool UseOrdinalCompare { get { return (this.compops & CompareOptions.Ordinal) != 0; } } #endif //----------------------------------------------- // Helper Functions //----------------------------------------------- private static int MakeLCID(int langid, int sortid) { return (langid & 0xffff) | ((sortid & 0xf) << 16); } private static int GetLangID(int lcid) { return (lcid & 0xffff); } } } // 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
- XsltQilFactory.cs
- ClientConfigurationSystem.cs
- WebServiceParameterData.cs
- ReachSerializationCacheItems.cs
- CodeTypeDelegate.cs
- HttpDigestClientCredential.cs
- XmlValidatingReaderImpl.cs
- HttpListenerException.cs
- FormViewDeletedEventArgs.cs
- Rule.cs
- MenuItemCollectionEditorDialog.cs
- ZoneLinkButton.cs
- SafeCryptContextHandle.cs
- XmlBoundElement.cs
- XmlArrayAttribute.cs
- IdentityReference.cs
- VirtualPath.cs
- HyperlinkAutomationPeer.cs
- VisualTransition.cs
- ManipulationPivot.cs
- BindingExpressionUncommonField.cs
- SelectedPathEditor.cs
- SqlBuilder.cs
- PenContext.cs
- Propagator.Evaluator.cs
- CapabilitiesState.cs
- CommonDialog.cs
- DuplexChannelBinder.cs
- RealizationContext.cs
- CapabilitiesRule.cs
- Vector3D.cs
- ImageFormat.cs
- DelegatedStream.cs
- ProgressBarRenderer.cs
- RevocationPoint.cs
- UInt16Converter.cs
- DataListCommandEventArgs.cs
- ContextTokenTypeConverter.cs
- PathFigureCollection.cs
- XmlReaderDelegator.cs
- ChangePassword.cs
- DataGridViewDataConnection.cs
- TCPListener.cs
- ObjectSerializerFactory.cs
- BamlResourceContent.cs
- EditorOptionAttribute.cs
- XmlDocumentSerializer.cs
- InfoCardProofToken.cs
- ThicknessAnimationUsingKeyFrames.cs
- XmlHierarchicalDataSourceView.cs
- DataGridViewSelectedCellsAccessibleObject.cs
- CodeNamespaceCollection.cs
- SoapDocumentMethodAttribute.cs
- EntityProviderServices.cs
- HwndSourceKeyboardInputSite.cs
- WpfPayload.cs
- PermissionSetEnumerator.cs
- BackStopAuthenticationModule.cs
- PageAdapter.cs
- WebPartEditorApplyVerb.cs
- ResolvedKeyFrameEntry.cs
- SmiContext.cs
- WindowsFormsLinkLabel.cs
- RightsManagementEncryptedStream.cs
- PrefixQName.cs
- Positioning.cs
- EntityDataSourceValidationException.cs
- OleDbConnectionPoolGroupProviderInfo.cs
- DataBinding.cs
- SignatureConfirmationElement.cs
- SwitchElementsCollection.cs
- UserControlDocumentDesigner.cs
- PageCatalogPart.cs
- DataListItemCollection.cs
- TargetFrameworkUtil.cs
- SqlXml.cs
- ViewManager.cs
- DataGridViewSortCompareEventArgs.cs
- Scheduler.cs
- DataGridViewCheckBoxColumn.cs
- TypedAsyncResult.cs
- InvalidDocumentContentsException.cs
- ExecutedRoutedEventArgs.cs
- FactoryGenerator.cs
- ColorContext.cs
- Transform3DGroup.cs
- InstanceCreationEditor.cs
- BitConverter.cs
- FormsAuthenticationTicket.cs
- BindingMAnagerBase.cs
- SqlNodeTypeOperators.cs
- ExtentCqlBlock.cs
- RequiredFieldValidator.cs
- MenuItemBinding.cs
- FilterRepeater.cs
- InitializerFacet.cs
- HelloOperationAsyncResult.cs
- TimelineClockCollection.cs
- ResourceDisplayNameAttribute.cs
- SrgsToken.cs