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 / 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
- ThreadExceptionDialog.cs
- TreeNodeBindingCollection.cs
- FlowLayoutPanel.cs
- TreeIterators.cs
- LocatorGroup.cs
- ObjectKeyFrameCollection.cs
- CommandLineParser.cs
- NamedElement.cs
- Margins.cs
- GPRECTF.cs
- ServiceHostingEnvironment.cs
- RoutingTable.cs
- FrugalList.cs
- Console.cs
- XsdValidatingReader.cs
- ObjectListComponentEditor.cs
- FixedBufferAttribute.cs
- WindowsListViewItem.cs
- TrustSection.cs
- CompilationUtil.cs
- InternalResources.cs
- CodeTypeParameterCollection.cs
- PropertyItemInternal.cs
- LassoSelectionBehavior.cs
- SelectingProviderEventArgs.cs
- DesignerVerb.cs
- ActivityMetadata.cs
- WebHttpBinding.cs
- GeneralTransform3DCollection.cs
- XmlComplianceUtil.cs
- WhitespaceSignificantCollectionAttribute.cs
- SqlError.cs
- SiteMapHierarchicalDataSourceView.cs
- WebPartConnectionsCancelVerb.cs
- SimpleWorkerRequest.cs
- PersonalizationProviderCollection.cs
- HMACRIPEMD160.cs
- XmlILStorageConverter.cs
- TableAdapterManagerNameHandler.cs
- FieldToken.cs
- XPathQilFactory.cs
- DataKeyPropertyAttribute.cs
- Span.cs
- TTSEngineProxy.cs
- ProgressBarBrushConverter.cs
- SelectorItemAutomationPeer.cs
- TableCell.cs
- WebPartManagerInternals.cs
- DescriptionAttribute.cs
- ControlCachePolicy.cs
- GrammarBuilder.cs
- SimpleLine.cs
- DbSetClause.cs
- BufferModeSettings.cs
- EventBuilder.cs
- SizeConverter.cs
- AttributeExtensions.cs
- HasCopySemanticsAttribute.cs
- AttributeUsageAttribute.cs
- FormatPage.cs
- DataViewListener.cs
- SafeRegistryHandle.cs
- AppDomainInfo.cs
- TextElementEnumerator.cs
- RtfToXamlReader.cs
- ClientScriptManager.cs
- InvalidEnumArgumentException.cs
- CompilerResults.cs
- NavigationProgressEventArgs.cs
- CriticalFinalizerObject.cs
- PolicyDesigner.cs
- WebScriptEnablingBehavior.cs
- DbParameterHelper.cs
- EdmEntityTypeAttribute.cs
- ZipFileInfo.cs
- CompilationUtil.cs
- InfocardChannelParameter.cs
- CharacterBuffer.cs
- NavigationWindow.cs
- GestureRecognitionResult.cs
- RelationshipEnd.cs
- EditingCoordinator.cs
- SecureStringHasher.cs
- Command.cs
- TaiwanCalendar.cs
- StylusPointCollection.cs
- ProcessModelInfo.cs
- ResXResourceSet.cs
- SqlCharStream.cs
- DynamicDocumentPaginator.cs
- AttributeQuery.cs
- LoginView.cs
- CompoundFileReference.cs
- xmlfixedPageInfo.cs
- TraceLog.cs
- ProfileService.cs
- UserValidatedEventArgs.cs
- XsdDuration.cs
- WebPartConnectionsCloseVerb.cs
- AttachedAnnotation.cs