1 //------------------------------------------------------------------------------
2 // <copyright file="SqlString.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">junfang</owner>
6 // <owner current="true" primary="false">Microsoft</owner>
7 // <owner current="true" primary="false">Microsoft</owner>
8 //------------------------------------------------------------------------------
10 //**************************************************************************
11 // @File: SqlString.cs
15 // Purpose: Implementation of SqlString which is equivalent to
16 // data type "nvarchar/varchar" in SQL Server
22 // 09/30/99 JunFang Created.
25 //**************************************************************************
28 using System.Data.Common;
29 using System.Globalization;
30 using System.Diagnostics;
31 using System.Runtime.InteropServices;
33 using System.Xml.Schema;
34 using System.Xml.Serialization;
36 namespace System.Data.SqlTypes {
38 using System.Configuration.Assemblies;
40 // Options that are used in comparison
42 public enum SqlCompareOptions {
44 IgnoreCase = 0x00000001,
45 IgnoreNonSpace = 0x00000002,
46 IgnoreKanaType = 0x00000008, // ignore kanatype
47 IgnoreWidth = 0x00000010, // ignore width
48 BinarySort = 0x00008000, // binary sorting
49 BinarySort2 = 0x00004000, // binary sorting 2
54 /// Represents a variable-length stream of characters to be stored in or retrieved from the database.
58 [StructLayout(LayoutKind.Sequential)]
59 [XmlSchemaProvider("GetXsdType")]
60 public struct SqlString : INullable, IComparable, IXmlSerializable {
61 private String m_value;
62 private CompareInfo m_cmpInfo;
63 private int m_lcid; // Locale Id
64 private SqlCompareOptions m_flag; // Compare flags
65 private bool m_fNotNull; // false if null
69 /// Represents a null value that can be assigned to the <see cref='System.Data.SqlTypes.SqlString.Value'/> property of an instance of
70 /// the <see cref='System.Data.SqlTypes.SqlString'/> class.
73 public static readonly SqlString Null = new SqlString(true);
75 internal static readonly UnicodeEncoding x_UnicodeEncoding = new UnicodeEncoding();
79 public static readonly int IgnoreCase = 0x1;
82 public static readonly int IgnoreWidth = 0x10;
85 public static readonly int IgnoreNonSpace = 0x2;
88 public static readonly int IgnoreKanaType = 0x8;
91 public static readonly int BinarySort = 0x8000;
94 public static readonly int BinarySort2 = 0x4000;
96 private static readonly SqlCompareOptions x_iDefaultFlag =
97 SqlCompareOptions.IgnoreCase | SqlCompareOptions.IgnoreKanaType |
98 SqlCompareOptions.IgnoreWidth;
99 private static readonly CompareOptions x_iValidCompareOptionMask =
100 CompareOptions.IgnoreCase | CompareOptions.IgnoreWidth |
101 CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreKanaType;
103 internal static readonly SqlCompareOptions x_iValidSqlCompareOptionMask =
104 SqlCompareOptions.IgnoreCase | SqlCompareOptions.IgnoreWidth |
105 SqlCompareOptions.IgnoreNonSpace | SqlCompareOptions.IgnoreKanaType |
106 SqlCompareOptions.BinarySort | SqlCompareOptions.BinarySort2;
108 internal const int x_lcidUSEnglish = 0x00000409;
109 private const int x_lcidBinary = 0x00008200;
114 private SqlString(bool fNull) {
118 m_flag = SqlCompareOptions.None;
122 // Constructor: Construct from both Unicode and NonUnicode data, according to fUnicode
125 /// Initializes a new instance of the <see cref='System.Data.SqlTypes.SqlString'/> class.
128 public SqlString(int lcid, SqlCompareOptions compareOptions, byte[] data, int index, int count, bool fUnicode) {
130 ValidateSqlCompareOptions(compareOptions);
131 m_flag = compareOptions;
140 // m_cmpInfo is set lazily, so that we don't need to pay the cost
141 // unless the string is used in comparison.
145 m_value = x_UnicodeEncoding.GetString(data, index, count);
148 CultureInfo culInfo = new CultureInfo(m_lcid);
149 Encoding cpe = System.Text.Encoding.GetEncoding(culInfo.TextInfo.ANSICodePage);
150 m_value = cpe.GetString(data, index, count);
155 // Constructor: Construct from both Unicode and NonUnicode data, according to fUnicode
158 /// Initializes a new instance of the <see cref='System.Data.SqlTypes.SqlString'/> class.
161 public SqlString(int lcid, SqlCompareOptions compareOptions, byte[] data, bool fUnicode)
162 : this(lcid, compareOptions, data, 0, data.Length, fUnicode) {
167 /// Initializes a new instance of the <see cref='System.Data.SqlTypes.SqlString'/> class.
170 public SqlString(int lcid, SqlCompareOptions compareOptions, byte[] data, int index, int count)
171 : this(lcid, compareOptions, data, index, count, true) {
176 /// Initializes a new instance of the <see cref='System.Data.SqlTypes.SqlString'/> class.
179 public SqlString(int lcid, SqlCompareOptions compareOptions, byte[] data)
180 : this(lcid, compareOptions, data, 0, data.Length, true) {
206 /// Initializes a new instance of the <see cref='System.Data.SqlTypes.SqlString'/> class.
209 public SqlString(String data, int lcid, SqlCompareOptions compareOptions) {
211 ValidateSqlCompareOptions(compareOptions);
212 m_flag = compareOptions;
220 m_value = data; // PERF: do not String.Copy
226 /// Initializes a new instance of the <see cref='System.Data.SqlTypes.SqlString'/> class.
229 public SqlString(String data, int lcid) : this(data, lcid, x_iDefaultFlag) {
234 /// Initializes a new instance of the <see cref='System.Data.SqlTypes.SqlString'/> class.
237 public SqlString(String data) : this(data, System.Globalization.CultureInfo.CurrentCulture.LCID, x_iDefaultFlag) {
240 private SqlString(int lcid, SqlCompareOptions compareOptions, String data, CompareInfo cmpInfo) {
242 ValidateSqlCompareOptions(compareOptions);
243 m_flag = compareOptions;
260 /// Gets whether the <see cref='System.Data.SqlTypes.SqlString.Value'/> of the <see cref='System.Data.SqlTypes.SqlString'/> is <see cref='System.Data.SqlTypes.SqlString.Null'/>.
264 get { return !m_fNotNull;}
270 /// Gets the string that is to be stored.
273 public String Value {
278 throw new SqlNullValueException();
283 /// <para>[To be supplied.]</para>
290 throw new SqlNullValueException();
295 /// <para>[To be supplied.]</para>
297 public CultureInfo CultureInfo {
300 return CultureInfo.GetCultureInfo(m_lcid);
302 throw new SqlNullValueException();
306 private void SetCompareInfo() {
307 SQLDebug.Check(!IsNull);
308 if (m_cmpInfo == null)
309 m_cmpInfo = (CultureInfo.GetCultureInfo(m_lcid)).CompareInfo;
313 /// <para>[To be supplied.]</para>
315 public CompareInfo CompareInfo {
322 throw new SqlNullValueException();
327 /// <para>[To be supplied.]</para>
329 public SqlCompareOptions SqlCompareOptions {
334 throw new SqlNullValueException();
338 // Implicit conversion from String to SqlString
340 /// <para>[To be supplied.]</para>
342 public static implicit operator SqlString(String x) {
343 return new SqlString(x);
346 // Explicit conversion from SqlString to String. Throw exception if x is Null.
348 /// <para>[To be supplied.]</para>
350 public static explicit operator String(SqlString x) {
356 /// Converts a <see cref='System.Data.SqlTypes.SqlString'/> object to a string.
359 public override String ToString() {
360 return IsNull ? SQLResource.NullString : m_value;
364 /// <para>[To be supplied.]</para>
366 public byte[] GetUnicodeBytes() {
370 return x_UnicodeEncoding.GetBytes(m_value);
374 /// <para>[To be supplied.]</para>
376 public byte[] GetNonUnicodeBytes() {
380 // Get the CultureInfo
381 CultureInfo culInfo = new CultureInfo(m_lcid);
383 Encoding cpe = System.Text.Encoding.GetEncoding(culInfo.TextInfo.ANSICodePage);
384 return cpe.GetBytes(m_value);
388 internal int GetSQLCID() {
390 throw new SqlNullValueException();
392 return MAKECID(m_lcid, m_flag);
400 /// <para>[To be supplied.]</para>
402 public static SqlString operator +(SqlString x, SqlString y) {
403 if (x.IsNull || y.IsNull)
404 return SqlString.Null;
406 if (x.m_lcid != y.m_lcid || x.m_flag != y.m_flag)
407 throw new SqlTypeException(SQLResource.ConcatDiffCollationMessage);
409 return new SqlString(x.m_lcid, x.m_flag, x.m_value + y.m_value,
410 (x.m_cmpInfo == null) ? y.m_cmpInfo : x.m_cmpInfo);
413 // StringCompare: Common compare function which is used by Compare and CompareTo
414 // In the case of Compare (used by comparison operators) the int result needs to be converted to SqlBoolean type
415 // while CompareTo needs the result in int type
416 // Pre-requisite: the null condition of the both string needs to be checked and handled by the caller of this function
417 private static int StringCompare(SqlString x, SqlString y)
419 SQLDebug.Check(!x.IsNull && !y.IsNull,
420 "!x.IsNull && !y.IsNull", "Null condition should be handled by the caller of StringCompare method");
422 if (x.m_lcid != y.m_lcid || x.m_flag != y.m_flag)
423 throw new SqlTypeException(SQLResource.CompareDiffCollationMessage);
427 SQLDebug.Check(x.FBinarySort() || (x.m_cmpInfo != null && y.m_cmpInfo != null),
428 "x.FBinarySort() || (x.m_cmpInfo != null && y.m_cmpInfo != null)", "");
432 if ((x.m_flag & SqlCompareOptions.BinarySort) != 0)
433 iCmpResult = CompareBinary(x, y);
434 else if ((x.m_flag & SqlCompareOptions.BinarySort2) != 0)
435 iCmpResult = CompareBinary2(x, y);
437 // SqlString can be padded with spaces (Padding is turn on by default in SQL Server 2008
438 // Trim the trailing space for comparison
439 // Avoid using String.TrimEnd function to avoid extra string allocations
441 string rgchX = x.m_value;
442 string rgchY = y.m_value;
443 int cwchX = rgchX.Length;
444 int cwchY = rgchY.Length;
446 while (cwchX > 0 && rgchX[cwchX - 1] == ' ')
448 while (cwchY > 0 && rgchY[cwchY - 1] == ' ')
451 CompareOptions options = CompareOptionsFromSqlCompareOptions(x.m_flag);
453 iCmpResult = x.m_cmpInfo.Compare(x.m_value, 0, cwchX, y.m_value, 0, cwchY, options);
459 // Comparison operators
460 private static SqlBoolean Compare(SqlString x, SqlString y, EComparison ecExpectedResult)
462 if (x.IsNull || y.IsNull)
463 return SqlBoolean.Null;
465 int iCmpResult = StringCompare(x, y);
467 bool fResult = false;
469 switch (ecExpectedResult) {
471 fResult = (iCmpResult == 0);
475 fResult = (iCmpResult < 0);
479 fResult = (iCmpResult <= 0);
483 fResult = (iCmpResult > 0);
487 fResult = (iCmpResult >= 0);
491 SQLDebug.Check(false, "Invalid ecExpectedResult");
492 return SqlBoolean.Null;
495 return new SqlBoolean(fResult);
500 // Implicit conversions
504 // Explicit conversions
506 // Explicit conversion from SqlBoolean to SqlString
508 /// <para>[To be supplied.]</para>
510 public static explicit operator SqlString(SqlBoolean x) {
511 return x.IsNull ? Null : new SqlString((x.Value).ToString());
514 // Explicit conversion from SqlByte to SqlString
516 /// <para>[To be supplied.]</para>
518 public static explicit operator SqlString(SqlByte x) {
519 return x.IsNull ? Null : new SqlString((x.Value).ToString((IFormatProvider)null));
522 // Explicit conversion from SqlInt16 to SqlString
524 /// <para>[To be supplied.]</para>
526 public static explicit operator SqlString(SqlInt16 x) {
527 return x.IsNull ? Null : new SqlString((x.Value).ToString((IFormatProvider)null));
530 // Explicit conversion from SqlInt32 to SqlString
532 /// <para>[To be supplied.]</para>
534 public static explicit operator SqlString(SqlInt32 x) {
535 return x.IsNull ? Null : new SqlString((x.Value).ToString((IFormatProvider)null));
538 // Explicit conversion from SqlInt64 to SqlString
540 /// <para>[To be supplied.]</para>
542 public static explicit operator SqlString(SqlInt64 x) {
543 return x.IsNull ? Null : new SqlString((x.Value).ToString((IFormatProvider)null));
546 // Explicit conversion from SqlSingle to SqlString
548 /// <para>[To be supplied.]</para>
550 public static explicit operator SqlString(SqlSingle x) {
551 return x.IsNull ? Null : new SqlString((x.Value).ToString((IFormatProvider)null));
554 // Explicit conversion from SqlDouble to SqlString
556 /// <para>[To be supplied.]</para>
558 public static explicit operator SqlString(SqlDouble x) {
559 return x.IsNull ? Null : new SqlString((x.Value).ToString((IFormatProvider)null));
562 // Explicit conversion from SqlDecimal to SqlString
564 /// <para>[To be supplied.]</para>
566 public static explicit operator SqlString(SqlDecimal x) {
567 return x.IsNull ? Null : new SqlString(x.ToString());
570 // Explicit conversion from SqlMoney to SqlString
572 /// <para>[To be supplied.]</para>
574 public static explicit operator SqlString(SqlMoney x) {
575 return x.IsNull ? Null : new SqlString(x.ToString());
578 // Explicit conversion from SqlDateTime to SqlString
580 /// <para>[To be supplied.]</para>
582 public static explicit operator SqlString(SqlDateTime x) {
583 return x.IsNull ? Null : new SqlString(x.ToString());
586 // Explicit conversion from SqlGuid to SqlString
588 /// <para>[To be supplied.]</para>
590 public static explicit operator SqlString(SqlGuid x) {
591 return x.IsNull ? Null : new SqlString(x.ToString());
595 /// <para>[To be supplied.]</para>
597 public SqlString Clone() {
599 return new SqlString(true);
601 SqlString ret = new SqlString(m_value, m_lcid, m_flag);
606 // Overloading comparison operators
608 /// <para>[To be supplied.]</para>
610 public static SqlBoolean operator==(SqlString x, SqlString y) {
611 return Compare(x, y, EComparison.EQ);
615 /// <para>[To be supplied.]</para>
617 public static SqlBoolean operator!=(SqlString x, SqlString y) {
622 /// <para>[To be supplied.]</para>
624 public static SqlBoolean operator<(SqlString x, SqlString y) {
625 return Compare(x, y, EComparison.LT);
629 /// <para>[To be supplied.]</para>
631 public static SqlBoolean operator>(SqlString x, SqlString y) {
632 return Compare(x, y, EComparison.GT);
636 /// <para>[To be supplied.]</para>
638 public static SqlBoolean operator<=(SqlString x, SqlString y) {
639 return Compare(x, y, EComparison.LE);
643 /// <para>[To be supplied.]</para>
645 public static SqlBoolean operator>=(SqlString x, SqlString y) {
646 return Compare(x, y, EComparison.GE);
649 //--------------------------------------------------
650 // Alternative methods for overloaded operators
651 //--------------------------------------------------
653 // Alternative method for operator +
654 public static SqlString Concat(SqlString x, SqlString y) {
658 public static SqlString Add(SqlString x, SqlString y) {
662 // Alternative method for operator ==
663 public static SqlBoolean Equals(SqlString x, SqlString y) {
667 // Alternative method for operator !=
668 public static SqlBoolean NotEquals(SqlString x, SqlString y) {
672 // Alternative method for operator <
673 public static SqlBoolean LessThan(SqlString x, SqlString y) {
677 // Alternative method for operator >
678 public static SqlBoolean GreaterThan(SqlString x, SqlString y) {
682 // Alternative method for operator <=
683 public static SqlBoolean LessThanOrEqual(SqlString x, SqlString y) {
687 // Alternative method for operator >=
688 public static SqlBoolean GreaterThanOrEqual(SqlString x, SqlString y) {
692 // Alternative method for conversions.
694 public SqlBoolean ToSqlBoolean() {
695 return (SqlBoolean)this;
698 public SqlByte ToSqlByte() {
699 return (SqlByte)this;
702 public SqlDateTime ToSqlDateTime() {
703 return (SqlDateTime)this;
706 public SqlDouble ToSqlDouble() {
707 return (SqlDouble)this;
710 public SqlInt16 ToSqlInt16() {
711 return (SqlInt16)this;
714 public SqlInt32 ToSqlInt32() {
715 return (SqlInt32)this;
718 public SqlInt64 ToSqlInt64() {
719 return (SqlInt64)this;
722 public SqlMoney ToSqlMoney() {
723 return (SqlMoney)this;
726 public SqlDecimal ToSqlDecimal() {
727 return (SqlDecimal)this;
730 public SqlSingle ToSqlSingle() {
731 return (SqlSingle)this;
734 public SqlGuid ToSqlGuid() {
735 return (SqlGuid)this;
741 // Utility functions and constants
743 private static void ValidateSqlCompareOptions(SqlCompareOptions compareOptions) {
744 if ((compareOptions & x_iValidSqlCompareOptionMask) != compareOptions)
745 throw new ArgumentOutOfRangeException ("compareOptions");
748 public static CompareOptions CompareOptionsFromSqlCompareOptions(SqlCompareOptions compareOptions) {
749 CompareOptions options = CompareOptions.None;
751 ValidateSqlCompareOptions(compareOptions);
753 if ((compareOptions & (SqlCompareOptions.BinarySort | SqlCompareOptions.BinarySort2)) != 0)
754 throw ADP.ArgumentOutOfRange("compareOptions");
756 if ((compareOptions & SqlCompareOptions.IgnoreCase) != 0)
757 options |= CompareOptions.IgnoreCase;
758 if ((compareOptions & SqlCompareOptions.IgnoreNonSpace) != 0)
759 options |= CompareOptions.IgnoreNonSpace;
760 if ((compareOptions & SqlCompareOptions.IgnoreKanaType) != 0)
761 options |= CompareOptions.IgnoreKanaType;
762 if ((compareOptions & SqlCompareOptions.IgnoreWidth) != 0)
763 options |= CompareOptions.IgnoreWidth;
770 private static SqlCompareOptions SqlCompareOptionsFromCompareOptions(CompareOptions compareOptions) {
771 SqlCompareOptions sqlOptions = SqlCompareOptions.None;
773 if ((compareOptions & x_iValidCompareOptionMask) != compareOptions)
774 throw new ArgumentOutOfRangeException ("compareOptions");
776 if ((compareOptions & CompareOptions.IgnoreCase) != 0)
777 sqlOptions |= SqlCompareOptions.IgnoreCase;
778 if ((compareOptions & CompareOptions.IgnoreNonSpace) != 0)
779 sqlOptions |= SqlCompareOptions.IgnoreNonSpace;
780 if ((compareOptions & CompareOptions.IgnoreKanaType) != 0)
781 sqlOptions |= SqlCompareOptions.IgnoreKanaType;
782 if ((compareOptions & CompareOptions.IgnoreWidth) != 0)
783 sqlOptions |= SqlCompareOptions.IgnoreWidth;
790 private bool FBinarySort() {
791 return(!IsNull && (m_flag & (SqlCompareOptions.BinarySort | SqlCompareOptions.BinarySort2)) != 0);
794 // Wide-character string comparison for Binary Unicode Collation
796 // -1 : wstr1 < wstr2
800 // Does a memory comparison.
801 private static int CompareBinary(SqlString x, SqlString y) {
802 byte[] rgDataX = x_UnicodeEncoding.GetBytes(x.m_value);
803 byte[] rgDataY = x_UnicodeEncoding.GetBytes(y.m_value);
804 int cbX = rgDataX.Length;
805 int cbY = rgDataY.Length;
806 int cbMin = cbX < cbY ? cbX : cbY;
809 SQLDebug.Check(cbX % 2 == 0);
810 SQLDebug.Check(cbY % 2 == 0);
812 for (i = 0; i < cbMin; i ++) {
813 if (rgDataX[i] < rgDataY[i])
815 else if (rgDataX[i] > rgDataY[i])
822 int iSpace = (int)' ';
825 for (; i < cbY; i += 2) {
826 iCh = ((int)rgDataY[i + 1]) << 8 + rgDataY[i];
828 return (iSpace > iCh) ? 1 : -1;
832 for (; i < cbX; i += 2) {
833 iCh = ((int)rgDataX[i + 1]) << 8 + rgDataX[i];
835 return (iCh > iSpace) ? 1 : -1;
842 // Wide-character string comparison for Binary2 Unicode Collation
844 // -1 : wstr1 < wstr2
848 // Does a wchar comparison (different from memcmp of BinarySort).
849 private static int CompareBinary2(SqlString x, SqlString y) {
850 SQLDebug.Check(!x.IsNull && !y.IsNull);
852 string rgDataX = x.m_value;
853 string rgDataY = y.m_value;
854 int cwchX = rgDataX.Length;
855 int cwchY = rgDataY.Length;
856 int cwchMin = cwchX < cwchY ? cwchX : cwchY;
859 for (i = 0; i < cwchMin; i ++) {
860 if (rgDataX[i] < rgDataY[i])
862 else if (rgDataX[i] > rgDataY[i])
866 // If compares equal up to one of the string terminates,
867 // pad it with spaces and compare with the rest of the other one.
872 for (i = cwchMin; i < cwchY; i ++) {
873 if (rgDataY[i] != chSpace)
874 return (chSpace > rgDataY[i]) ? 1 : -1;
878 for (i = cwchMin; i < cwchX; i ++) {
879 if (rgDataX[i] != chSpace)
880 return (rgDataX[i] > chSpace) ? 1 : -1;
888 private void Print() {
889 Debug.WriteLine("SqlString - ");
890 Debug.WriteLine("\tlcid = " + m_lcid.ToString());
892 if ((m_flag & SqlCompareOptions.IgnoreCase) != 0)
893 Debug.Write("IgnoreCase, ");
894 if ((m_flag & SqlCompareOptions.IgnoreNonSpace) != 0)
895 Debug.Write("IgnoreNonSpace, ");
896 if ((m_flag & SqlCompareOptions.IgnoreKanaType) != 0)
897 Debug.Write("IgnoreKanaType, ");
898 if ((m_flag & SqlCompareOptions.IgnoreWidth) != 0)
899 Debug.Write("IgnoreWidth, ");
901 Debug.WriteLine("\tvalue = " + m_value);
902 Debug.WriteLine("\tcmpinfo = " + m_cmpInfo);
906 // Compares this object to another object, returning an integer that
907 // indicates the relationship.
908 // Returns a value less than zero if this < object, zero if this = object,
909 // or a value greater than zero if this > object.
910 // null is considered to be less than any instance.
911 // If object is not of same type, this method throws an ArgumentException.
913 /// <para>[To be supplied.]</para>
915 public int CompareTo(Object value) {
916 if (value is SqlString) {
917 SqlString i = (SqlString)value;
921 throw ADP.WrongType(value.GetType(), typeof(SqlString));
924 public int CompareTo(SqlString value) {
925 // If both Null, consider them equal.
926 // Otherwise, Null is less than anything.
928 return value.IsNull ? 0 : -1;
929 else if (value.IsNull)
932 int returnValue = StringCompare(this, value);
934 // Conver the result into -1, 0, or 1 as this method never returned any other values
935 // This is to ensure the backcompat
936 if (returnValue < 0) {
939 if (returnValue > 0) {
946 // Compares this instance with a specified object
948 /// <para>[To be supplied.]</para>
950 public override bool Equals(Object value) {
951 if (!(value is SqlString)) {
955 SqlString i = (SqlString)value;
957 if (i.IsNull || IsNull)
958 return (i.IsNull && IsNull);
960 return (this == i).Value;
963 // For hashing purpose
965 /// <para>[To be supplied.]</para>
967 public override int GetHashCode() {
973 rgbSortKey = x_UnicodeEncoding.GetBytes(m_value.TrimEnd());
977 // GetHashCode should not throw just because this instance has an invalid LCID or compare options.
979 CompareOptions options;
983 options = CompareOptionsFromSqlCompareOptions(m_flag);
985 catch (ArgumentException) {
986 // SetCompareInfo throws this when instance's LCID is unsupported
987 // CompareOptionsFromSqlCompareOptions throws this when instance's options are invalid
988 cmpInfo = CultureInfo.InvariantCulture.CompareInfo;
989 options = CompareOptions.None;
991 rgbSortKey = cmpInfo.GetSortKey(m_value.TrimEnd(), options).KeyData;
994 return SqlBinary.HashByteArray(rgbSortKey, rgbSortKey.Length);
998 /// <para>[To be supplied.]</para>
1000 XmlSchema IXmlSerializable.GetSchema() { return null; }
1003 /// <para>[To be supplied.]</para>
1005 void IXmlSerializable.ReadXml(XmlReader reader) {
1006 string isNull = reader.GetAttribute("nil", XmlSchema.InstanceNamespace);
1007 if (isNull != null && XmlConvert.ToBoolean(isNull)) {
1008 // VSTFDevDiv# 479603 - SqlTypes read null value infinitely and never read the next value. Fix - Read the next value.
1009 reader.ReadElementString();
1013 m_value = reader.ReadElementString();
1019 /// <para>[To be supplied.]</para>
1021 void IXmlSerializable.WriteXml(XmlWriter writer) {
1023 writer.WriteAttributeString("xsi", "nil", XmlSchema.InstanceNamespace, "true");
1026 writer.WriteString(m_value);
1031 /// <para>[To be supplied.]</para>
1033 public static XmlQualifiedName GetXsdType(XmlSchemaSet schemaSet) {
1034 return new XmlQualifiedName("string", XmlSchema.Namespace);
1040 internal struct SLocaleMapItem {
1041 public int lcid; // the primary key, not nullable
1042 public String name; // unique, nullable
1043 public int idCodePage; // the ANSI default code page of the locale
1045 public SLocaleMapItem(int lid, String str, int cpid) {
1052 // Struct to map lcid to ordinal
1053 internal struct SLcidOrdMapItem {
1058 // Class to store map of lcids to ordinal
1059 internal class CBuildLcidOrdMap {
1060 internal SLcidOrdMapItem[] m_rgLcidOrdMap;
1061 internal int m_cValidLocales;
1062 internal int m_uiPosEnglish; // Start binary searches here - this is index in array, not ordinal
1064 // Constructor builds the array sorted by lcid
1065 // We use a simple n**2 sort because the array is mostly sorted anyway
1066 // and objects of this class will be const, hence this will be called
1067 // only by VC compiler
1068 public CBuildLcidOrdMap() {
1071 m_rgLcidOrdMap = new SLcidOrdMapItem[SqlString.x_cLocales];
1073 // Compact the array
1074 for (i=0,j=0; i < SqlString.x_cLocales; i++) {
1075 if (SqlString.x_rgLocaleMap[i].lcid != SqlString.x_lcidUnused) {
1076 m_rgLcidOrdMap[j].lcid = SqlString.x_rgLocaleMap[i].lcid;
1077 m_rgLcidOrdMap[j].uiOrd = i;
1082 m_cValidLocales = j;
1084 // Set the rest to invalid
1085 while (j < SqlString.x_cLocales) {
1086 m_rgLcidOrdMap[j].lcid = SqlString.x_lcidUnused;
1087 m_rgLcidOrdMap[j].uiOrd = 0;
1091 // Now sort in place
1093 // Start from 1, assume list before i is sorted, if next item
1094 // violates this assumption, exchange with prev items until the
1095 // item is in its correct place
1096 for (i=1; i<m_cValidLocales; i++) {
1098 m_rgLcidOrdMap[j].lcid < m_rgLcidOrdMap[j-1].lcid; j--) {
1099 // Swap with prev element
1100 int lcidTemp = m_rgLcidOrdMap[j-1].lcid;
1101 int uiOrdTemp = m_rgLcidOrdMap[j-1].uiOrd;
1102 m_rgLcidOrdMap[j-1].lcid = m_rgLcidOrdMap[j].lcid;
1103 m_rgLcidOrdMap[j-1].uiOrd = m_rgLcidOrdMap[j].uiOrd;
1104 m_rgLcidOrdMap[j].lcid = lcidTemp;
1105 m_rgLcidOrdMap[j].uiOrd = uiOrdTemp;
1109 // Set the position of the US_English LCID (Latin1_General)
1110 for (i=0; i<m_cValidLocales && m_rgLcidOrdMap[i].lcid != SqlString.x_lcidUSEnglish; i++)
1111 ; // Deliberately empty
1113 SQLDebug.Check(i<m_cValidLocales); // Latin1_General better be present
1114 m_uiPosEnglish = i; // This is index in array, not ordinal
1117 } // CBuildLcidOrdMap
1120 } // namespace System.Data.SqlTypes