* OdbcParameterTest.cs: Fixed compilation on 1.0 profile.
[mono.git] / mcs / class / System.Data / System.Data.SqlTypes / SqlString.cs
index 2dd6fe47b051a2ab55b0cf4a7c063c43f8afda57..02d903a48df2c6529155036b31f3080e1d5ce1ad 100644 (file)
 // (C) Copyright 2002 Tim Coleman
 //
 
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
 using System;
-using System.Globalization;
+using System.Xml;
+using System.Text;
 using System.Threading;
+using System.Xml.Schema;
+using System.Globalization;
+using System.Xml.Serialization;
 
 namespace System.Data.SqlTypes
 {
@@ -21,7 +48,14 @@ namespace System.Data.SqlTypes
        /// A variable-length stream of characters 
        /// to be stored in or retrieved from the database
        /// </summary>
+#if NET_2_0
+       [SerializableAttribute]
+       [XmlSchemaProvider ("GetXsdType")]
+#endif
        public struct SqlString : INullable, IComparable 
+#if NET_2_0
+                               , IXmlSerializable
+#endif
        {
 
                #region Fields
@@ -41,7 +75,6 @@ namespace System.Data.SqlTypes
                public static readonly int IgnoreWidth = 0x10;
                public static readonly SqlString Null;
 
-               internal static readonly NumberFormatInfo MoneyFormat;
                internal static NumberFormatInfo DecimalFormat;
                #endregion // Fields
 
@@ -49,10 +82,6 @@ namespace System.Data.SqlTypes
 
                static SqlString ()
                {
-                       MoneyFormat = (NumberFormatInfo) NumberFormatInfo.InvariantInfo.Clone ();
-                       MoneyFormat.NumberDecimalDigits = 4;
-                       MoneyFormat.NumberGroupSeparator = String.Empty;
-
                        DecimalFormat = (NumberFormatInfo) NumberFormatInfo.InvariantInfo.Clone ();
                        DecimalFormat.NumberDecimalDigits = 13;
                        DecimalFormat.NumberGroupSeparator = String.Empty;
@@ -63,7 +92,10 @@ namespace System.Data.SqlTypes
                {
                        this.value = data;
                        lcid = CultureInfo.CurrentCulture.LCID;
-                       notNull = true;
+                       if (value != null)
+                               notNull = true;
+                       else
+                               notNull = false;
                        this.compareOptions = SqlCompareOptions.IgnoreCase |
                                SqlCompareOptions.IgnoreKanaType |
                                SqlCompareOptions.IgnoreWidth;
@@ -74,7 +106,10 @@ namespace System.Data.SqlTypes
                {
                        this.value = data;
                        this.lcid = lcid;
-                       notNull = true;
+                       if (value != null)
+                               notNull = true;
+                       else
+                               notNull = false;
                        this.compareOptions = SqlCompareOptions.IgnoreCase |
                                SqlCompareOptions.IgnoreKanaType |
                                SqlCompareOptions.IgnoreWidth;
@@ -91,36 +126,24 @@ namespace System.Data.SqlTypes
                        this.value = data;
                        this.lcid = lcid;
                        this.compareOptions = compareOptions;
-                       notNull = true;
+                       if (value != null)
+                               notNull = true;
+                       else
+                               notNull = false;
                }
 
                // init with locale id, compare options, array of bytes data,
                // and whether unicode is encoded or not
                public SqlString (int lcid, SqlCompareOptions compareOptions, byte[] data, bool fUnicode) 
                {
-                       char [] chars;
-
-                       if (fUnicode)
-                               chars = new char [data.Length/2];
-                       else
-                               chars = new char [data.Length];
-                       
-                       int j = 0;
-                       for (int i = 0; i < chars.Length; i++) {
-
-                               if (fUnicode) {
-                                       chars [i] = (char)(data [j] << 16);
-                                       chars [i] += (char)data [j + 1];
-                                       j += 2;
-                               } else {
-                                       chars [i] = (char)data[i];
-                               }
-                       }
-                               
-                       this.value = new String (chars);
+                       Encoding encoding = (fUnicode ? Encoding.Unicode : Encoding.ASCII);
+                       this.value = encoding.GetString (data);
                        this.lcid = lcid;
                        this.compareOptions = compareOptions;
-                       notNull = true;
+                       if (value != null)
+                               notNull = true;
+                       else
+                               notNull = false;
                }
 
                // init with locale id, compare options, array of bytes data,
@@ -135,36 +158,14 @@ namespace System.Data.SqlTypes
                // and whether unicode is encoded or not
                public SqlString (int lcid, SqlCompareOptions compareOptions, byte[] data, int index, int count, bool fUnicode) 
                {                      
-                       char [] chars;
-
-                       if (fUnicode)
-                               chars = new char [(count - index) / 2];
-                       else
-                               chars = new char [count - index];
-
-                       if (index >= data.Length)
-                               throw new ArgumentOutOfRangeException ("index");
-
-                       if ((index + count) > data.Length)
-                               throw new ArgumentOutOfRangeException ("count");
-
-                       int j = 0;
-                       for (int i = index; i < chars.Length; i++) {
-                               
-                               if (fUnicode) {
-                                       chars [i] = (char)(data[j] << 16);
-                                       chars [i] += (char)data[j+1];
-                                       j += 2;
-                               } else {
-                                       chars [i] = (char)data [j];
-                                       j++;
-                               }
-                       }
-
-                       this.value = new String (chars);
+                       Encoding encoding = (fUnicode ? Encoding.Unicode : Encoding.ASCII);
+                       this.value = encoding.GetString (data, index, count);
                        this.lcid = lcid;
                        this.compareOptions = compareOptions;
-                       notNull = true;
+                       if (value != null)
+                               notNull = true;
+                       else
+                               notNull = false;
                }
 
                #endregion // Constructors
@@ -210,21 +211,21 @@ namespace System.Data.SqlTypes
                         }
                 }
 
-               #endregion // Public Properties\r
-\r
-               #region Private Properties\r
-\r
-               private CompareOptions CompareOptions {\r
-                       get {\r
-                               return\r
-                                       (this.compareOptions & SqlCompareOptions.BinarySort) != 0 ?\r
-                                       CompareOptions.Ordinal :\r
-                                       // 27 == all SqlCompareOptions - BinarySort \r
-                                       // (1,2,8,24 are common to CompareOptions)\r
-                                       (CompareOptions)((int)this.compareOptions & 27);\r
-                       }\r
-               }\r
-\r
+               #endregion // Public Properties
+
+               #region Private Properties
+
+               private CompareOptions CompareOptions {
+                       get {
+                               return
+                                       (this.compareOptions & SqlCompareOptions.BinarySort) != 0 ?
+                                       CompareOptions.Ordinal :
+                                       // 27 == all SqlCompareOptions - BinarySort 
+                                       // (1,2,8,24 are common to CompareOptions)
+                                       (CompareOptions)((int)this.compareOptions & 27);
+                       }
+               }
+
                #endregion Private Properties
 
                #region Public Methods
@@ -263,11 +264,20 @@ namespace System.Data.SqlTypes
                                return 1;
                        else if (!(value is SqlString))
                                throw new ArgumentException (Locale.GetText ("Value is not a System.Data.SqlTypes.SqlString"));
-                       else if (((SqlString)value).IsNull)
+                       
+                       return CompareSqlString ((SqlString)value);
+               }
+
+               
+               private int CompareSqlString (SqlString value)
+               {
+                       if (value.IsNull)
                                return 1;
+                       else if (value.CompareOptions != this.CompareOptions)
+                               throw new SqlTypeException (Locale.GetText ("Two strings to be compared have different collation"));
 //                     else
 //                             return String.Compare (this.value, ((SqlString)value).Value, (this.SqlCompareOptions & SqlCompareOptions.IgnoreCase) != 0, this.CultureInfo);
-                       return CultureInfo.CompareInfo.Compare (this.value, ((SqlString)value).Value, this.CompareOptions);
+                       return CultureInfo.CompareInfo.Compare (this.value, value.Value, this.CompareOptions);
                }
 
                public static SqlString Concat(SqlString x, SqlString y) 
@@ -279,8 +289,8 @@ namespace System.Data.SqlTypes
                {
                        if (!(value is SqlString))
                                return false;
-                       if (this.IsNull && ((SqlString)value).IsNull)
-                               return true;
+                       if (this.IsNull)
+                               return ((SqlString)value).IsNull;
                        else if (((SqlString)value).IsNull)
                                return false;
                        else
@@ -306,26 +316,12 @@ namespace System.Data.SqlTypes
 
                public byte[] GetNonUnicodeBytes() 
                {
-                       byte [] bytes = new byte [value.Length];
-
-                       for (int i = 0; i < bytes.Length; i++) 
-                               bytes [i] = (byte)value [i];
-
-                       return bytes;
+                       return Encoding.ASCII.GetBytes (value);
                }
 
                public byte[] GetUnicodeBytes() 
                {
-                       byte [] bytes = new byte [value.Length * 2];
-                       
-                       int j = 0;
-                       for (int i = 0; i < value.Length; i++) {                                
-                               bytes [j] = (byte)(value [i] & 0x0000FFFF);
-                               bytes [j + 1] = (byte)((value [i] & 0xFFFF0000) >> 16);
-                               j += 2;
-                       }
-                       
-                       return bytes;
+                       return Encoding.Unicode.GetBytes (value);
                }
 
                public static SqlBoolean GreaterThan(SqlString x, SqlString y) 
@@ -426,10 +422,10 @@ namespace System.Data.SqlTypes
                // Concatenates
                public static SqlString operator + (SqlString x, SqlString y) 
                {
-                       if (x.IsNull || y.IsNull)
-                               return SqlString.Null;
-
-                       return new SqlString (x.Value + y.Value);
+                        if (x.IsNull || y.IsNull)
+                                return SqlString.Null;
+                       else
+                               return new SqlString (x.Value + y.Value);
                }
 
                // Equality
@@ -567,8 +563,7 @@ namespace System.Data.SqlTypes
                        if (x.IsNull)
                                return Null;
                        else
-                               return new SqlString (x.Value.ToString ());
-                               // return new SqlString (x.Value.ToString ("N", MoneyFormat));
+                               return new SqlString (x.ToString ());
                }
 
                public static explicit operator SqlString (SqlSingle x) 
@@ -589,6 +584,79 @@ namespace System.Data.SqlTypes
                        return new SqlString (x);
                }
 
+#if NET_2_0
+                public static SqlString Add (SqlString x, SqlString y)
+                {
+                       return (x + y);
+                }
+
+               public int CompareTo (SqlString value)
+                {
+                       return CompareSqlString (value);
+                }
+#endif
+
+
+
                #endregion // Public Methods
+#if NET_2_0
+               public static XmlQualifiedName GetXsdType (XmlSchemaSet schemaSet)
+               {
+                       if (schemaSet != null && schemaSet.Count == 0) {
+                               XmlSchema xs = new XmlSchema ();
+                               XmlSchemaComplexType ct = new XmlSchemaComplexType ();
+                               ct.Name = "string";
+                               xs.Items.Add (ct);
+                               schemaSet.Add (xs);
+                       }
+                       return new XmlQualifiedName ("string", "http://www.w3.org/2001/XMLSchema");
+               }
+
+               XmlSchema IXmlSerializable.GetSchema ()
+               {
+                       return null;
+               }
+               
+               void IXmlSerializable.ReadXml (XmlReader reader)
+               {
+                       if (reader == null)
+                               return;
+
+                       switch (reader.ReadState) {
+                       case ReadState.EndOfFile:
+                       case ReadState.Error:
+                       case ReadState.Closed:
+                               return;
+                       }
+                       // Skip XML declaration and prolog
+                       // or do I need to validate for the <string> tag?
+                       reader.MoveToContent ();
+                       if (reader.EOF)
+                               return;
+                       
+                       reader.Read ();
+                       if (reader.NodeType == XmlNodeType.EndElement)
+                               return;
+
+                       if (reader.Value.Length > 0) {
+                               if (String.Compare ("Null", reader.Value) == 0) {
+                                       // means a null reference/invalid value
+                                       notNull = false;
+                                       return; 
+                               }
+                               // FIXME: Validate the value for expected format
+                               this.value = reader.Value;
+                               this.notNull = true;
+                               this.compareOptions = SqlCompareOptions.IgnoreCase |
+                                       SqlCompareOptions.IgnoreKanaType |
+                                       SqlCompareOptions.IgnoreWidth;
+                       }
+               }
+               
+               void IXmlSerializable.WriteXml (XmlWriter writer) 
+               {
+                       writer.WriteString (this.ToString ());
+               }
+#endif
        }
 }