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 UniqueList
public 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 UniqueList
public 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
- XmlParserContext.cs
- autovalidator.cs
- Directory.cs
- AgileSafeNativeMemoryHandle.cs
- XPathSelectionIterator.cs
- InternalEnumValidatorAttribute.cs
- ConnectionStringsExpressionBuilder.cs
- CompoundFileDeflateTransform.cs
- COM2IProvidePropertyBuilderHandler.cs
- ClientApiGenerator.cs
- RelAssertionDirectKeyIdentifierClause.cs
- TextServicesLoader.cs
- Run.cs
- TextContainerChangeEventArgs.cs
- BamlRecordWriter.cs
- KeyEventArgs.cs
- ImmutableObjectAttribute.cs
- SqlMetaData.cs
- DataContractSerializerServiceBehavior.cs
- BitSet.cs
- PeerSecurityManager.cs
- TextTreeText.cs
- WorkflowRuntimeServiceElement.cs
- EntityRecordInfo.cs
- InheritanceService.cs
- DbExpressionVisitor.cs
- ProjectionPruner.cs
- SelectionRangeConverter.cs
- RijndaelManaged.cs
- StateChangeEvent.cs
- DelegateSerializationHolder.cs
- AlphabeticalEnumConverter.cs
- SqlNotificationEventArgs.cs
- IndexedString.cs
- DescendentsWalker.cs
- PrePostDescendentsWalker.cs
- ConfigXmlDocument.cs
- MetafileEditor.cs
- ObjectDataSourceDisposingEventArgs.cs
- XmlSerializableWriter.cs
- ProcessRequestAsyncResult.cs
- TableItemStyle.cs
- MatrixTransform3D.cs
- XsltContext.cs
- MenuItemBinding.cs
- WS2007FederationHttpBindingElement.cs
- SecurityKeyType.cs
- XmlWrappingReader.cs
- Evaluator.cs
- UICuesEvent.cs
- FlowDocumentFormatter.cs
- KoreanLunisolarCalendar.cs
- CodeBlockBuilder.cs
- SmiTypedGetterSetter.cs
- StrongNameSignatureInformation.cs
- Accessible.cs
- TemplateBamlTreeBuilder.cs
- BamlResourceDeserializer.cs
- XmlLinkedNode.cs
- DataSourceControlBuilder.cs
- SqlBinder.cs
- Baml2006KeyRecord.cs
- SparseMemoryStream.cs
- ZipIOExtraFieldElement.cs
- ObjectItemAttributeAssemblyLoader.cs
- ToolStripArrowRenderEventArgs.cs
- SqlDelegatedTransaction.cs
- ResourceWriter.cs
- AssertSection.cs
- MasterPage.cs
- HebrewNumber.cs
- HtmlInputButton.cs
- GridViewRowCollection.cs
- SerializationSectionGroup.cs
- TaiwanCalendar.cs
- PageContentCollection.cs
- LinqToSqlWrapper.cs
- Win32PrintDialog.cs
- InstanceCompleteException.cs
- TypeDelegator.cs
- WebServiceResponse.cs
- SettingsAttributes.cs
- ColumnCollection.cs
- QueryCacheManager.cs
- TriggerBase.cs
- ModelUIElement3D.cs
- DockPatternIdentifiers.cs
- ProviderConnectionPoint.cs
- GuidelineCollection.cs
- CaseInsensitiveComparer.cs
- HtmlContainerControl.cs
- Soap12ProtocolImporter.cs
- StatusBar.cs
- ListBindingConverter.cs
- SerTrace.cs
- SessionParameter.cs
- HtmlInputSubmit.cs
- ListViewSelectEventArgs.cs
- CacheMemory.cs
- SQLChars.cs