2003-06-11 Tim Coleman <tim@timcoleman.com>
authorTim Coleman <tim@mono-cvs.ximian.com>
Wed, 11 Jun 2003 18:22:02 +0000 (18:22 -0000)
committerTim Coleman <tim@mono-cvs.ximian.com>
Wed, 11 Jun 2003 18:22:02 +0000 (18:22 -0000)
        * SybaseConnection.cs:
                Make connection parameter parsing "more correct"
                and throw appropriate exceptions, similar to MS SqlClient
        * SybaseBinary.cs:
        * SybaseBoolean.cs:
        * SybaseByte.cs:
        * SybaseDateTime.cs:
        * SybaseDecimal.cs:
        * SybaseDouble.cs:
        * SybaseMoney.cs:
        * SybaseString.cs:
                Mass import of code from SqlClient to make this behave
                better.

svn path=/trunk/mcs/; revision=15324

mcs/class/Mono.Data.SybaseClient/ChangeLog
mcs/class/Mono.Data.SybaseClient/Mono.Data.SybaseClient/SybaseConnection.cs
mcs/class/Mono.Data.SybaseClient/Mono.Data.SybaseTypes/SybaseBinary.cs
mcs/class/Mono.Data.SybaseClient/Mono.Data.SybaseTypes/SybaseBoolean.cs
mcs/class/Mono.Data.SybaseClient/Mono.Data.SybaseTypes/SybaseByte.cs
mcs/class/Mono.Data.SybaseClient/Mono.Data.SybaseTypes/SybaseDateTime.cs
mcs/class/Mono.Data.SybaseClient/Mono.Data.SybaseTypes/SybaseDecimal.cs
mcs/class/Mono.Data.SybaseClient/Mono.Data.SybaseTypes/SybaseDouble.cs
mcs/class/Mono.Data.SybaseClient/Mono.Data.SybaseTypes/SybaseMoney.cs
mcs/class/Mono.Data.SybaseClient/Mono.Data.SybaseTypes/SybaseString.cs

index 28bd41069fd91adfeefcd40c9cb357a01acbcb83..d85a6fb97d9eba5215da243375e8392261fcec74 100644 (file)
@@ -1,3 +1,18 @@
+2003-06-11  Tim Coleman <tim@timcoleman.com>
+       * SybaseConnection.cs:
+               Make connection parameter parsing "more correct"
+               and throw appropriate exceptions, similar to MS SqlClient
+       * SybaseBinary.cs:
+       * SybaseBoolean.cs:
+       * SybaseByte.cs:
+       * SybaseDateTime.cs:
+       * SybaseDecimal.cs:
+       * SybaseDouble.cs:
+       * SybaseMoney.cs:
+       * SybaseString.cs:
+               Mass import of code from SqlClient to make this behave
+               better.
+
 2003-02-16  Daniel Morgan <danmorg@sc.rr.com>
 
        * SybaseConnection.cs: - parse data source for 2 possible uses:
index dfa513d798135a8b83e97e0e108f3ff065588757..b2d8397de38932aefc12eb9524fdd8cac53b9dea 100644 (file)
@@ -5,7 +5,7 @@
 //   Tim Coleman (tim@timcoleman.com)
 //   Daniel Morgan (danmorg@sc.rr.com)
 //
-// Copyright (C) Tim Coleman, 20022003
+// Copyright (C) Tim Coleman, 2002-2003
 // Copyright (C) Daniel Morgan, 2003
 //
 
@@ -48,7 +48,7 @@ namespace Mono.Data.SybaseClient {
                int minPoolSize;
                int maxPoolSize;
                int packetSize;
-               int port = 1533;
+               int port = 2048;
 
                // The current state
                ConnectionState state = ConnectionState.Closed;
@@ -286,7 +286,7 @@ namespace Mono.Data.SybaseClient {
                public void Open () 
                {
                        string serverName = "";
-                       if (connectionString == null)
+                       if (connectionString == null || connectionString.Equals (""))
                                throw new InvalidOperationException ("Connection string has not been initialized.");
 
                        try {
@@ -325,10 +325,10 @@ namespace Mono.Data.SybaseClient {
                private void ParseDataSource (string theDataSource, out int thePort, out string theServerName) 
                {
                        theServerName = "";
-                       thePort = 1433; // default TCP port for SQL Server
-                                               \r
-                       int idx = 0;\r
-                       if ((idx = theDataSource.IndexOf (",")) > -1) {\r
+                       thePort = 2048; 
+                                               
+                       int idx = 0;
+                       if ((idx = theDataSource.IndexOf (",")) > -1) {
                                theServerName = theDataSource.Substring (0, idx);
                                string p = theDataSource.Substring (idx + 1);
                                thePort = Int32.Parse (p);
@@ -338,174 +338,187 @@ namespace Mono.Data.SybaseClient {
                        }
                }
 
-                void SetConnectionString (string connectionString)
-                {
-                        connectionString += ";";
-                        NameValueCollection parameters = new NameValueCollection ();
-
-                        if (connectionString == String.Empty)
-                                return;
-
-                        bool inQuote = false;
-                        bool inDQuote = false;
-
-                        string name = String.Empty;
-                        string value = String.Empty;
-                        StringBuilder sb = new StringBuilder ();
-
-                        foreach (char c in connectionString)
-                        {
-                                switch (c) {
-                                case '\'':
-                                        inQuote = !inQuote;
-                                        break;
-                                case '"' :
-                                        inDQuote = !inDQuote;
-                                        break;
-                                case ';' :
-                                        if (!inDQuote && !inQuote) {
-                                               if (name != String.Empty && name != null) {
-                                                       value = sb.ToString ();
-                                                       parameters [name.ToUpper ().Trim ()] = value.Trim ();
-                                               }
-                                                name = String.Empty;
-                                                value = String.Empty;
-                                                sb = new StringBuilder ();
-                                        }
-                                        else
-                                                sb.Append (c);
-                                        break;
-                                case '=' :
-                                        if (!inDQuote && !inQuote) {
-                                                name = sb.ToString ();
-                                                sb = new StringBuilder ();
-                                        }
-                                        else
-                                                sb.Append (c);
-                                        break;
-                                default:
-                                        sb.Append (c);
-                                        break;
-                                }
-                        }
-
-                        if (this.ConnectionString == null)
-                        {
-                                SetDefaultConnectionParameters (parameters);
-                        }
-
-                        SetProperties (parameters);
-
-                        this.connectionString = connectionString;
-                }
-
-                void SetDefaultConnectionParameters (NameValueCollection parameters)
-                {
-                        if (null == parameters.Get ("APPLICATION NAME"))
-                                parameters["APPLICATION NAME"] = ".Net SybaseClient Data Provider";
-                        if (null == parameters.Get ("CONNECT TIMEOUT") && null == parameters.Get ("CONNECTION TIMEOUT"))
-                                parameters["CONNECT TIMEOUT"] = "15";
-                        if (null == parameters.Get ("CONNECTION LIFETIME"))
-                                parameters["CONNECTION LIFETIME"] = "0";
-                        if (null == parameters.Get ("CONNECTION RESET"))
-                                parameters["CONNECTION RESET"] = "true";
-                        if (null == parameters.Get ("ENLIST"))
-                                parameters["ENLIST"] = "true";
-                        if (null == parameters.Get ("INTEGRATED SECURITY") && null == parameters.Get ("TRUSTED_CONNECTION"))
-                                parameters["INTEGRATED SECURITY"] = "false";
-                        if (null == parameters.Get ("MAX POOL SIZE"))
-                                parameters["MAX POOL SIZE"] = "100";
-                        if (null == parameters.Get ("MIN POOL SIZE"))
-                                parameters["MIN POOL SIZE"] = "0";
-                        if (null == parameters.Get ("NETWORK LIBRARY") && null == parameters.Get ("NET"))
-                                parameters["NETWORK LIBRARY"] = "dbmssocn";
-                        if (null == parameters.Get ("PACKET SIZE"))
-                                parameters["PACKET SIZE"] = "512";
-                        if (null == parameters.Get ("PERSIST SECURITY INFO"))
-                                parameters["PERSIST SECURITY INFO"] = "false";
-                        if (null == parameters.Get ("POOLING"))
-                                parameters["POOLING"] = "true";
-                        if (null == parameters.Get ("WORKSTATION ID"))
-                                parameters["WORKSTATION ID"] = Dns.GetHostByName ("localhost").HostName;
-                }
-
-                private void SetProperties (NameValueCollection parameters)
-                {
-                        string value;
-                        foreach (string name in parameters) {
-                                value = parameters[name];
-
-                                switch (name) {
-                                case "APPLICATION NAME" :
-                                        parms.ApplicationName = value;
-                                        break;
-                                case "ATTACHDBFILENAME" :
-                                case "EXTENDED PROPERTIES" :
-                                case "INITIAL FILE NAME" :
-                                        break;
-                                case "CONNECT TIMEOUT" :
-                                case "CONNECTION TIMEOUT" :
-                                        connectionTimeout = Int32.Parse (value);
-                                        break;
-                                case "CONNECTION LIFETIME" :
-                                        break;
-                                case "CONNECTION RESET" :
-                                        connectionReset = !(value.ToUpper ().Equals ("FALSE") || value.ToUpper ().Equals ("NO"));
-                                        break;
-                                case "CURRENT LANGUAGE" :
-                                        parms.Language = value;
-                                        break;
-                                case "DATA SOURCE" :
-                                case "SERVER" :
-                                case "ADDRESS" :
-                                case "ADDR" :
-                                case "NETWORK ADDRESS" :
-                                        dataSource = value;
-                                        break;
-                                case "ENLIST" :
-                                        break;
-                                case "INITIAL CATALOG" :
-                                case "DATABASE" :
-                                        parms.Database = value;
-                                        break;
-                                case "INTEGRATED SECURITY" :
-                                case "TRUSTED_CONNECTION" :
-                                        break;
-                                case "MAX POOL SIZE" :
-                                        maxPoolSize = Int32.Parse (value);
-                                        break;
-                                case "MIN POOL SIZE" :
-                                        minPoolSize = Int32.Parse (value);
-                                        break;
-                                case "NET" :
-                                case "NETWORK LIBRARY" :
-                                        if (!value.ToUpper ().Equals ("DBMSSOCN"))
-                                                throw new ArgumentException ("Unsupported network library.");
-                                        break;
-                                case "PACKET SIZE" :
-                                        packetSize = Int32.Parse (value);
-                                        break;
-                                case "PASSWORD" :
-                                case "PWD" :
-                                        parms.Password = value;
-                                        break;
-                                case "PERSIST SECURITY INFO" :
-                                        break;
-                                case "POOLING" :
-                                        pooling = !(value.ToUpper ().Equals ("FALSE") || value.ToUpper ().Equals ("NO"));
-                                        break;
-                                case "USER ID" :
-                                        parms.User = value;
-                                        break;
-                                case "WORKSTATION ID" :
-                                        parms.Hostname = value;
-                                        break;
-                                }
+               private string ParseValue (string name, string value)
+               {
+                       if (name.Length == 0 && value.Length > 0)
+                               throw new ArgumentException ("Expected '=' delimiter while parsing connection value pair.");
+                       if (name.Length > 0)
+                               return value.Trim ();
+                       return String.Empty;
+               }
+
+               private void SetConnectionString (string connectionString)
+               {
+                       if (connectionString == String.Empty) {
+                               this.connectionString = connectionString;
+                               return;
                        }
+
+                       NameValueCollection parameters = new NameValueCollection ();
+
+                       string name = String.Empty;
+                       string value = String.Empty;
+                       StringBuilder sb = new StringBuilder ();
+
+                       char delimiter = '\0';
+
+                       foreach (char c in connectionString) {
+                               switch (c) {
+                               case '\'' :
+                               case '"' :
+                                       if (delimiter.Equals (c))
+                                               delimiter = '\0';
+                                       else if (delimiter.Equals ('\0'))
+                                               delimiter = c;
+                                       else
+                                               sb.Append (c);
+                                       break;
+                               case ';' :
+                                       if (delimiter.Equals ('\0')) {
+                                               value = ParseValue (name, sb.ToString ());
+                                               if (!value.Equals ("")) 
+                                                       parameters [name.ToUpper ().Trim ()] = value;
+                                               name = String.Empty;
+                                               sb = new StringBuilder ();
+                                       } 
+                                       else
+                                               sb.Append (c);
+                                       break;
+                               case '=' :
+                                       if (delimiter.Equals ('\0')) {
+                                               name = sb.ToString ();
+                                               sb = new StringBuilder ();
+                                       }
+                                       else
+                                               sb.Append (c);
+                                       break;
+                               default:
+                                       sb.Append (c);
+                                       break;
+                               }
+                       }
+
+                       if (!delimiter.Equals ('\0'))
+                               throw new ArgumentException (String.Format ("Matching end delimiter {0} not found in connection option value.", delimiter));
+
+                       value = ParseValue (name, sb.ToString ());
+                       if (!value.Equals (""))
+                               parameters [name.ToUpper ().Trim ()] = value;
+
+                       if (this.ConnectionString == null)
+                               SetDefaultConnectionParameters (parameters);
+
+                       SetProperties (parameters);
+
+                       this.connectionString = connectionString;
                }
 
+               private void SetDefaultConnectionParameters (NameValueCollection parameters)
+               {
+                       if (null == parameters.Get ("APPLICATION NAME"))
+                               parameters["APPLICATION NAME"] = "Mono SybaseClient Data Provider";
+                       if (null == parameters.Get ("CONNECT TIMEOUT") && null == parameters.Get ("CONNECTION TIMEOUT"))
+                               parameters["CONNECT TIMEOUT"] = "15";
+                       if (null == parameters.Get ("CONNECTION LIFETIME"))
+                               parameters["CONNECTION LIFETIME"] = "0";
+                       if (null == parameters.Get ("CONNECTION RESET"))
+                               parameters["CONNECTION RESET"] = "true";
+                       if (null == parameters.Get ("ENLIST"))
+                               parameters["ENLIST"] = "true";
+                       if (null == parameters.Get ("INTEGRATED SECURITY") && null == parameters.Get ("TRUSTED_CONNECTION"))
+                               parameters["INTEGRATED SECURITY"] = "false";
+                       if (null == parameters.Get ("MAX POOL SIZE"))
+                               parameters["MAX POOL SIZE"] = "100";
+                       if (null == parameters.Get ("MIN POOL SIZE"))
+                               parameters["MIN POOL SIZE"] = "0";
+                       if (null == parameters.Get ("NETWORK LIBRARY") && null == parameters.Get ("NET"))
+                               parameters["NETWORK LIBRARY"] = "dbmssocn";
+                       if (null == parameters.Get ("PACKET SIZE"))
+                               parameters["PACKET SIZE"] = "512";
+                       if (null == parameters.Get ("PERSIST SECURITY INFO"))
+                               parameters["PERSIST SECURITY INFO"] = "false";
+                       if (null == parameters.Get ("POOLING"))
+                               parameters["POOLING"] = "true";
+                       if (null == parameters.Get ("WORKSTATION ID"))
+                               parameters["WORKSTATION ID"] = Dns.GetHostByName ("localhost").HostName;
+               }
+
+               private void SetProperties (NameValueCollection parameters)
+               {
+                       string value;
+                       foreach (string name in parameters) {
+                               value = parameters [name];
+
+                               switch (name) {
+                               case "APPLICATION NAME" :
+                                       parms.ApplicationName = value;
+                                       break;
+                               case "ATTACHDBFILENAME" :
+                               case "EXTENDED PROPERTIES" :
+                               case "INITIAL FILE NAME" :
+                                       break;
+                               case "CONNECT TIMEOUT" :
+                               case "CONNECTION TIMEOUT" :
+                                       connectionTimeout = Int32.Parse (value);
+                                       break;
+                               case "CONNECTION LIFETIME" :
+                                       break;
+                               case "CONNECTION RESET" :
+                                       connectionReset = !(value.ToUpper ().Equals ("FALSE") || value.ToUpper ().Equals ("NO"));
+                                       break;
+                               case "CURRENT LANGUAGE" :
+                                       parms.Language = value;
+                                       break;
+                               case "DATA SOURCE" :
+                               case "SERVER" :
+                               case "ADDRESS" :
+                               case "ADDR" :
+                               case "NETWORK ADDRESS" :
+                                       dataSource = value;
+                                       break;
+                               case "ENLIST" :
+                                       break;
+                               case "INITIAL CATALOG" :
+                               case "DATABASE" :
+                                       parms.Database = value;
+                                       break;
+                               case "INTEGRATED SECURITY" :
+                               case "TRUSTED_CONNECTION" :
+                                       break;
+                               case "MAX POOL SIZE" :
+                                       maxPoolSize = Int32.Parse (value);
+                                       break;
+                               case "MIN POOL SIZE" :
+                                       minPoolSize = Int32.Parse (value);
+                                       break;
+                               case "NET" :
+                               case "NETWORK LIBRARY" :
+                                       if (!value.ToUpper ().Equals ("DBMSSOCN"))
+                                               throw new ArgumentException ("Unsupported network library.");
+                                       break;
+                               case "PACKET SIZE" :
+                                       packetSize = Int32.Parse (value);
+                                       break;
+                               case "PASSWORD" :
+                               case "PWD" :
+                                       parms.Password = value;
+                                       break;
+                               case "PERSIST SECURITY INFO" :
+                                       break;
+                               case "POOLING" :
+                                       pooling = !(value.ToUpper ().Equals ("FALSE") || value.ToUpper ().Equals ("NO"));
+                                       break;
+                               case "USER ID" :
+                                       parms.User = value;
+                                       break;
+                               case "WORKSTATION ID" :
+                                       parms.Hostname = value;
+                                       break;
+                               }
+                       }
+               }
 
-               static bool IsValidDatabaseName (string database)
+               private static bool IsValidDatabaseName (string database)
                {
                        if (database.Length > 32 || database.Length < 1)
                                return false;
index d0fbe92d52f47ffe7238b84c97f8a6c7559a73d9..f319f79f51c8853c53491268c8ec6b3c961c3816 100644 (file)
@@ -4,7 +4,10 @@
 // Author:
 //   Tim Coleman (tim@timcoleman.com)
 //
-// (C) Copyright Tim Coleman, 2002
+// Based on System.Data.SqlTypes.SqlBinary
+//
+// (C) Ximian, Inc. 2002-2003
+// (C) Copyright Tim Coleman, 2002-2003
 //
 
 using Mono.Data.SybaseClient;
@@ -74,10 +77,16 @@ namespace Mono.Data.SybaseTypes {
 
                #region Methods
 
-               [MonoTODO]
                public int CompareTo (object value) 
                {
-                       throw new NotImplementedException ();
+                       if (value == null)
+                               return 1;
+                       else if (!(value is SybaseBinary))
+                               throw new ArgumentException ("Value is not a Mono.Data.SybaseTypes.SybaseBinary.");
+                       else if (((SybaseBinary) value).IsNull)
+                               return 1;
+                       else
+                               return Compare (this, (SybaseBinary) value);
                }
 
                public static SybaseBinary Concat (SybaseBinary x, SybaseBinary y) 
@@ -98,10 +107,12 @@ namespace Mono.Data.SybaseTypes {
                        return (x == y);
                }
 
-               [MonoTODO]
                public override int GetHashCode () 
                {
-                       throw new NotImplementedException ();
+                       int result = 10;
+                       for (int i = 0; i < value.Length; i += 1) 
+                               result = 91 * result + ((int) value [i]);
+                       return result;
                }
 
                #endregion
@@ -149,64 +160,69 @@ namespace Mono.Data.SybaseTypes {
 
                #region Operators
 
-               [MonoTODO]
                public static SybaseBinary operator + (SybaseBinary x, SybaseBinary y) 
                {
-                       throw new NotImplementedException ();
+                       byte[] b = new byte [x.Length + y.Length];
+                       int j = 0;
+                       int i;
+
+                       for (i = 0; i < x.Length; i += 1)
+                               b [i] = x [i];
+
+                       for (; i < x.Length + y.Length; i += 1) {
+                               b [i] = y [j];
+                               j += 1;
+                       }
+
+                       return new SybaseBinary (b);
                }
 
-               [MonoTODO]
                public static SybaseBoolean operator == (SybaseBinary x, SybaseBinary y) 
                {
                        if (x.IsNull || y.IsNull) 
                                return SybaseBoolean.Null;
                        else
-                               throw new NotImplementedException ();
+                               return new SybaseBoolean (Compare (x, y) == 0);
                }
 
-               [MonoTODO]
                public static SybaseBoolean operator > (SybaseBinary x, SybaseBinary y) 
                {
                        if (x.IsNull || y.IsNull) 
                                return SybaseBoolean.Null;
                        else
-                               throw new NotImplementedException ();
+                               return new SybaseBoolean (Compare (x, y) > 0);
                }
 
-               [MonoTODO]
                public static SybaseBoolean operator >= (SybaseBinary x, SybaseBinary y) 
                {
                        if (x.IsNull || y.IsNull) 
                                return SybaseBoolean.Null;
                        else
-                               throw new NotImplementedException ();
+                               return new SybaseBoolean (Compare (x, y) >= 0);
                }
 
-               [MonoTODO]
                public static SybaseBoolean operator != (SybaseBinary x, SybaseBinary y) 
                {
                        if (x.IsNull || y.IsNull) 
                                return SybaseBoolean.Null;
                        else
-                               throw new NotImplementedException ();
+                               return new SybaseBoolean (Compare (x, y) != 0);
                }
 
-               [MonoTODO]
                public static SybaseBoolean operator < (SybaseBinary x, SybaseBinary y) 
                {
                        if (x.IsNull || y.IsNull) 
                                return SybaseBoolean.Null;
                        else
-                               throw new NotImplementedException ();
+                               return new SybaseBoolean (Compare (x, y) < 0);
                }
 
-               [MonoTODO]
                public static SybaseBoolean operator <= (SybaseBinary x, SybaseBinary y) 
                {
                        if (x.IsNull || y.IsNull) 
                                return SybaseBoolean.Null;
                        else
-                               throw new NotImplementedException ();
+                               return new SybaseBoolean (Compare (x, y) <= 0);
                }
 
                public static explicit operator byte[] (SybaseBinary x) 
@@ -214,10 +230,9 @@ namespace Mono.Data.SybaseTypes {
                        return x.Value;
                }
 
-               [MonoTODO]
                public static explicit operator SybaseBinary (SybaseGuid x) 
                {
-                       throw new NotImplementedException ();
+                       return new SybaseBinary (x.ToByteArray ());
                }
 
                public static implicit operator SybaseBinary (byte[] x) 
@@ -225,6 +240,41 @@ namespace Mono.Data.SybaseTypes {
                        return new SybaseBinary (x);
                }
 
+               private static int Compare (SybaseBinary x, SybaseBinary y)
+               {
+                       int lengthDiff = 0;
+                       
+                       if (x.Length != y.Length) {
+                               lengthDiff = x.Length - y.Length;
+                               
+                               // if diff more than 0, x is longer
+                               if (lengthDiff > 0) {
+                                       for (int i = x.Length - 1; i > x.Length - lengthDiff; i -= 1) 
+                                               if (x [i] != (byte) 0)
+                                                       return 1;
+                               } else {
+                                       for (int i = y.Length - 1; i > y.Length - lengthDiff; i -= 1) 
+                                               if (y [i] != (byte) 0)
+                                                       return -1;
+                               }
+                       }
+
+                       // choose shorter
+                       int len = (lengthDiff > 0) ? y.Length : x.Length;
+
+                       for (int i = len - 1; i > 0; i -= 1) {
+                               byte bx = x [i];
+                               byte by = y [i];
+
+                               if (bx > by)
+                                       return 1;
+                               else if (bx < by)
+                                       return -1;
+                       }
+
+                       return 0;
+               }
+
                #endregion
        }
 }
index 92fbfcd84dcec28c88ae8c8b4a3e0749c8bc1f06..19bb0613a5022ee7c36170c1c3081d4c5600d05b 100644 (file)
@@ -4,12 +4,15 @@
 // Author:
 //   Tim Coleman (tim@timcoleman.com)
 //
-// (C) Copyright Tim Coleman, 2002
+// Based on System.Data.SqlTypes.SqlBoolean
+//
+// (C) Ximian, Inc. 2002-2003
+// (C) Copyright Tim Coleman, 2002-2003
 //
 
 using Mono.Data.SybaseClient;
 using System;
-using System.Data.SqlTypes;
+using System.Data.SqlTypes; 
 using System.Globalization;
 
 namespace Mono.Data.SybaseTypes {
index 0b65ffaa52ad5bee404a147b0782e6b9d30f9b61..eebdbab9cb54fa7a706fe88545dd5bb11c1fd7ce 100644 (file)
@@ -4,6 +4,10 @@
 // Author:
 //   Tim Coleman <tim@timcoleman.com>
 //
+// Based on System.Data.SqlTypes.SqlByte
+//
+//
+// (C) Ximian, Inc. 2002-2003
 // (C) Copyright Tim Coleman, 2002
 //
 
index 36981171e5c8f855baa1df36cabe12ebae76840e..634e28828ebc1905d3273bff0e31bafc0b525021 100644 (file)
@@ -4,7 +4,10 @@
 // Author:
 //   Tim Coleman <tim@timcoleman.com>
 //
-// (C) Copyright Tim Coleman, 2002
+// Based on System.Data.SqlTypes.SqlDateTime
+//
+// (C) Ximian, Inc. 2002-2003
+// (C) Copyright Tim Coleman, 2002-2003
 //
 
 using Mono.Data.SybaseClient;
@@ -18,13 +21,15 @@ namespace Mono.Data.SybaseTypes {
                #region Fields
                private DateTime value;
                private bool notNull;
+               private static readonly float DateTimeTicksPerHour = 3.6E+10f;
+               private static readonly DateTime Epoch = new DateTime (1900, 1, 1);
 
-               public static readonly SybaseDateTime MaxValue = new SybaseDateTime (9999,12,31);
+               public static readonly SybaseDateTime MaxValue = new SybaseDateTime (9999, 12, 31, 23, 59, 59);
                public static readonly SybaseDateTime MinValue = new SybaseDateTime (1753,1,1);
                public static readonly SybaseDateTime Null;
-               public static readonly int SQLTicksPerHour;
-               public static readonly int SQLTicksPerMinute;
-               public static readonly int SQLTicksPerSecond;
+               public static readonly int SQLTicksPerHour = 1080000;
+               public static readonly int SQLTicksPerMinute = 18000;
+               public static readonly int SQLTicksPerSecond = 300;
 
                #endregion
 
@@ -36,10 +41,10 @@ namespace Mono.Data.SybaseTypes {
                        notNull = true;
                }
 
-               [MonoTODO]
                public SybaseDateTime (int dayTicks, int timeTicks) 
                {
-                       throw new NotImplementedException ();
+                       this.value = new DateTime (Epoch.Ticks + (long) (dayTicks + timeTicks));
+                       notNull = true;
                }
 
                public SybaseDateTime (int year, int month, int day) 
@@ -54,34 +59,40 @@ namespace Mono.Data.SybaseTypes {
                        notNull = true;
                }
 
-               [MonoTODO]
                public SybaseDateTime (int year, int month, int day, int hour, int minute, int second, double millisecond) 
                {
-                       throw new NotImplementedException ();
+                       DateTime t = new DateTime (year, month, day);
+                       this.value = new DateTime ((long) (t.Day * 24 * SQLTicksPerHour + hour * SQLTicksPerHour + minute * SQLTicksPerMinute + second * SQLTicksPerSecond + millisecond * 1000));
+                       notNull = true;
                }
 
-               [MonoTODO]
                public SybaseDateTime (int year, int month, int day, int hour, int minute, int second, int bilisecond) 
                {
-                       throw new NotImplementedException ();
+                       DateTime t = new DateTime (year, month, day);
+                       this.value = new DateTime ((long) (t.Day * 24 * SQLTicksPerHour + hour * SQLTicksPerHour + minute * SQLTicksPerMinute + second * SQLTicksPerSecond + bilisecond));
+                       notNull = true;
                }
 
                #endregion
 
                #region Properties
 
-               [MonoTODO]
                public int DayTicks {
-                       get { throw new NotImplementedException (); }
+                       get { 
+                               return (int) ((this.Value.Ticks - Epoch.Ticks) / (24 * DateTimeTicksPerHour));
+                       }
                }
 
                public bool IsNull { 
                        get { return !notNull; }
                }
 
-               [MonoTODO]
                public int TimeTicks {
-                       get { throw new NotImplementedException (); }
+                       get { 
+                               if (this.IsNull)
+                                       throw new SybaseNullValueException ();
+                               return (int) (value.Hour * SQLTicksPerHour + value.Minute * SQLTicksPerMinute + value.Second * SQLTicksPerSecond + value.Millisecond);
+                       }
                }
 
                public DateTime Value {
@@ -122,10 +133,9 @@ namespace Mono.Data.SybaseTypes {
                        return (x == y);
                }
 
-               [MonoTODO]
                public override int GetHashCode ()
                {
-                       return 42;
+                       return value.GetHashCode ();
                }
 
                public static SybaseBoolean GreaterThan (SybaseDateTime x, SybaseDateTime y)
@@ -153,10 +163,9 @@ namespace Mono.Data.SybaseTypes {
                        return (x != y);
                }
 
-               [MonoTODO]
                public static SybaseDateTime Parse (string s)
                {
-                       throw new NotImplementedException ();
+                       return new SybaseDateTime (DateTime.Parse (s));
                }
 
                public SybaseString ToSybaseString ()
@@ -172,10 +181,11 @@ namespace Mono.Data.SybaseTypes {
                                return value.ToString ();
                }
        
-               [MonoTODO]      
                public static SybaseDateTime operator + (SybaseDateTime x, TimeSpan t)
                {
-                       throw new NotImplementedException ();
+                       if (x.IsNull)
+                               return SybaseDateTime.Null;
+                       return new SybaseDateTime (x.Value + t);
                }
 
                public static SybaseBoolean operator == (SybaseDateTime x, SybaseDateTime y)
@@ -226,10 +236,11 @@ namespace Mono.Data.SybaseTypes {
                                return new SybaseBoolean (x.Value <= y.Value);
                }
 
-               [MonoTODO]
                public static SybaseDateTime operator - (SybaseDateTime x, TimeSpan t)
                {
-                       throw new NotImplementedException ();
+                       if (x.IsNull)
+                               return SybaseDateTime.Null;
+                       return new SybaseDateTime (x.Value - t);
                }
 
                public static explicit operator DateTime (SybaseDateTime x)
@@ -237,10 +248,9 @@ namespace Mono.Data.SybaseTypes {
                        return x.Value;
                }
 
-               [MonoTODO]
                public static explicit operator SybaseDateTime (SybaseString x)
                {
-                       throw new NotImplementedException();
+                       return SybaseDateTime.Parse (x.Value);
                }
 
                public static implicit operator SybaseDateTime (DateTime x)
index aa1f5ddb297cebb37e8021512460bc74e669bbd9..0a8118c69c22f4626e5cf293beac2c87f469085c 100644 (file)
@@ -4,6 +4,9 @@
 // Author:
 //   Tim Coleman <tim@timcoleman.com>
 //
+// Based on System.Data.SqlTypes.SqlDecimal
+//
+// (C) Ximian, Inc. 2002-2003
 // (C) Copyright Tim Coleman, 2002
 //
 
@@ -11,6 +14,7 @@ using Mono.Data.Tds.Protocol;
 using System;
 using System.Data.SqlTypes;
 using System.Globalization;
+using System.Text;
 
 namespace Mono.Data.SybaseTypes {
        public struct SybaseDecimal : INullable, IComparable
@@ -29,6 +33,14 @@ namespace Mono.Data.SybaseTypes {
                const int SCALE_SHIFT = 16;
                const int SIGN_SHIFT = 31;
                const int RESERVED_SS32_BITS = 0x7F00FFFF;
+               const ulong LIT_GUINT64_HIGHBIT = 0x8000000000000000;
+               const ulong LIT_GUINT32_HIGHBIT = 0x80000000;
+               const byte DECIMAL_MAX_INTFACTORS = 9;
+               static uint [] constantsDecadeInt32Factors = new uint [10]
+                       {
+                               1u, 10u, 100u, 1000u, 10000u, 100000u, 1000000u,
+                               10000000u, 100000000u, 1000000000u
+                       };
 
                public static readonly byte MaxPrecision = 38;
                public static readonly byte MaxScale = 38;
@@ -45,19 +57,19 @@ namespace Mono.Data.SybaseTypes {
                {
                        int[] binData = Decimal.GetBits (value);
 
-                       this.precision = MaxPrecision; // this value seems unclear
-
                        this.scale = (byte)(binData[3] >> SCALE_SHIFT);
                        if (this.scale > MaxScale || (this.scale & RESERVED_SS32_BITS) != 0)
                                throw new ArgumentException(Locale.GetText ("Invalid scale"));
 
-                       this.positive = ((binData[3] >> SIGN_SHIFT) > 0);
                        this.value = new int[4];
                        this.value[0] = binData[0];
                        this.value[1] = binData[1];
                        this.value[2] = binData[2];
                        this.value[3] = 0;
                        notNull = true;
+
+                       positive = (value >= 0);
+                       precision = GetPrecision (value);
                }
 
                public SybaseDecimal (double value) : this ((decimal)value) { }
@@ -77,15 +89,29 @@ namespace Mono.Data.SybaseTypes {
                        this.value[2] = data3;
                        this.value[3] = data4;
                        notNull = true;
+
+                       if (precision < scale)
+                               throw new ArgumentException ("Invalid scale");
+                       if (this.ToDouble () > (Math.Pow (10, 38) -1) || this.ToDouble () < -(Math.Pow (10, 38)))
+                               throw new SybaseTypeException ("Can't convert to SybaseDecimal.");
                }
 
                #endregion
 
                #region Properties
 
-               [MonoTODO]
                public byte[] BinData {
-                       get { throw new NotImplementedException (); }
+                       get { 
+                               byte[] b = new byte [value.Length * 4];
+                               int j = 0;
+                               for (int i = 0; i < value.Length; i += 1) {
+                                       b [j++] = (byte) (0xff & value [i]);
+                                       b [j++] = (byte) (0xff & value [i] >> 8);
+                                       b [j++] = (byte) (0xff & value [i] >> 16);
+                                       b [j++] = (byte) (0xff & value [i] >> 24);
+                               }
+                               return b;
+                       }
                }
 
                public int[] Data { 
@@ -117,12 +143,9 @@ namespace Mono.Data.SybaseTypes {
                        get { 
                                if (this.IsNull) 
                                        throw new SybaseNullValueException ();
-                               else 
-                                       if (this.value[3] > 0)
-                                               throw new OverflowException ();
-                                       else
-                                               System.Console.WriteLine( "boo!" );
-                                               return new decimal (value[0], value[1], value[2], !positive, scale);
+                               if (this.value[3] > 0)
+                                       throw new OverflowException ();
+                               return new decimal (value[0], value[1], value[2], !positive, scale);
                        }
                }
 
@@ -130,10 +153,9 @@ namespace Mono.Data.SybaseTypes {
 
                #region Methods
 
-               [MonoTODO]
                public static SybaseDecimal Abs (SybaseDecimal n)
                {
-                       throw new NotImplementedException();
+                       return new SybaseDecimal (n.Precision, n.Scale, true, n.BinData [0], n.BinData [1], n.BinData [2], n.BinData [3]);
                }
 
                public static SybaseDecimal Add (SybaseDecimal x, SybaseDecimal y)
@@ -141,16 +163,21 @@ namespace Mono.Data.SybaseTypes {
                        return (x + y);
                }
 
-               [MonoTODO]
                public static SybaseDecimal AdjustScale (SybaseDecimal n, int digits, bool fRound)
                {
-                       throw new NotImplementedException ();
+                       byte prec = n.Precision;
+                       if (n.IsNull)
+                               throw new SybaseNullValueException ();
+                       if (digits > 0)
+                               prec = (byte) (prec + digits);
+                       if (fRound)
+                               n = Round (n, digits + n.Scale);
+                       return new SybaseDecimal (prec, (byte) (n.Scale + digits), n.IsPositive, n.Data);
                }
 
-               [MonoTODO]
                public static SybaseDecimal Ceiling (SybaseDecimal n)
                {
-                       throw new NotImplementedException();
+                       return AdjustScale (n, -(n.Scale), true);
                }
 
                public int CompareTo (object value)
@@ -165,10 +192,9 @@ namespace Mono.Data.SybaseTypes {
                                return this.Value.CompareTo (((SybaseDecimal)value).Value);
                }
 
-               [MonoTODO]
                public static SybaseDecimal ConvertToPrecScale (SybaseDecimal n, int precision, int scale)
                {
-                       throw new NotImplementedException ();
+                       return new SybaseDecimal ((byte) precision, (byte) scale, n.IsPositive, n.Data);
                }
 
                public static SybaseDecimal Divide (SybaseDecimal x, SybaseDecimal y)
@@ -180,6 +206,10 @@ namespace Mono.Data.SybaseTypes {
                {
                        if (!(value is SybaseDecimal))
                                return false;
+                       else if (this.IsNull && ((SybaseDecimal) value).IsNull)
+                               return true;
+                       else if (((SybaseDecimal) value).IsNull)
+                               return false;
                        else
                                return (bool) (this == (SybaseDecimal)value);
                }
@@ -189,10 +219,9 @@ namespace Mono.Data.SybaseTypes {
                        return (x == y);
                }
 
-               [MonoTODO]
                public static SybaseDecimal Floor (SybaseDecimal n)
                {
-                       throw new NotImplementedException ();
+                       return AdjustScale (n, -(n.Scale), false);
                }
 
                internal static SybaseDecimal FromTdsBigDecimal (TdsBigDecimal x)
@@ -205,7 +234,15 @@ namespace Mono.Data.SybaseTypes {
 
                public override int GetHashCode ()
                {
-                       return (int)this.Value;
+                       int result = 10;
+                       result = 91 * result + this.Data [0];
+                       result = 91 * result + this.Data [1];
+                       result = 91 * result + this.Data [2];
+                       result = 91 * result + this.Data [3];
+                       result = 91 * result + (int) this.Scale;
+                       result = 91 * result + (int) this.Precision;
+
+                       return result;
                }
 
                public static SybaseBoolean GreaterThan (SybaseDecimal x, SybaseDecimal y)
@@ -238,28 +275,38 @@ namespace Mono.Data.SybaseTypes {
                        return (x != y);
                }
 
-               [MonoTODO]
                public static SybaseDecimal Parse (string s)
                {
-                       throw new NotImplementedException ();
+                       if (s == null)
+                               throw new ArgumentNullException ();
+                       else
+                               return SybaseDouble.Parse (s).ToSybaseDecimal ();
                }
 
-               [MonoTODO]
                public static SybaseDecimal Power (SybaseDecimal n, double exp)
                {
-                       throw new NotImplementedException ();
+                       if (n.IsNull)
+                               return SybaseDecimal.Null;
+                       return new SybaseDecimal (Math.Pow (n.ToDouble (), exp));
                }
 
-               [MonoTODO]
                public static SybaseDecimal Round (SybaseDecimal n, int position)
                {
-                       throw new NotImplementedException ();
+                       if (n.IsNull)
+                               throw new SybaseNullValueException ();
+                       SybaseDecimal result = new SybaseDecimal (Math.Round ((double) (n.ToDouble () * Math.Pow (10, position))));
+                       result = result / new SybaseDecimal (Math.Pow (10, position));
+                       return result;
                }
 
-               [MonoTODO]
                public static SybaseInt32 Sign (SybaseDecimal n)
                {
-                       throw new NotImplementedException ();
+                       SybaseInt32 result = 0;
+                       if (n >= new SybaseDecimal (0))
+                               result = 1;
+                       else
+                               result = -1;
+                       return result;
                }
 
                public static SybaseDecimal Subtract (SybaseDecimal x, SybaseDecimal y)
@@ -267,9 +314,25 @@ namespace Mono.Data.SybaseTypes {
                        return (x - y);
                }
 
+               private static byte GetPrecision (decimal value)
+               {
+                       string str = value.ToString ();
+                       byte result = 0;
+                       foreach (char c in str) 
+                               if (c >= '0' && c <= '9')
+                                       result ++;
+                       return result;
+               }
+
                public double ToDouble ()
                {
-                       return ((double)this.Value);
+                       // FIXME: This is the wrong way to do this
+                       double d = (uint) this.Data [0];
+                       d += ((uint) this.Data [1]) * Math.Pow (2, 32);
+                       d += ((uint) this.Data [2]) * Math.Pow (2, 64);
+                       d += ((uint) this.Data [3]) * Math.Pow (2, 96);
+                       d /= Math.Pow (10, scale);
+                       return d;
                }
 
                public SybaseBoolean ToSybaseBoolean ()
@@ -321,14 +384,520 @@ namespace Mono.Data.SybaseTypes {
                {
                        if (this.IsNull)
                                return String.Empty;
+
+                       // convert int [4] -> ulong [2]
+                       ulong lo = (uint) this.Data [0] + (ulong) ((ulong) this.Data [1] << 32);
+                       ulong hi = (uint) this.Data [2] + (ulong) ((ulong) this.Data [3] << 32);
+
+                       uint rest = 0;
+                       StringBuilder result = new StringBuilder ();
+                       for (int i = 0; lo != 0 || hi != 0; i += 1) {
+                               Div128By32 (ref hi, ref lo, 10, ref rest);
+                               result.Insert (0, rest.ToString ());
+                       }
+                       while (result.Length < Precision)
+                               result.Append ("0");
+                       while (result.Length > Precision)
+                               result.Remove (result.Length - 1, 1);
+                       if (Scale > 0)
+                               result.Insert (result.Length - Scale, ".");
+                       return result.ToString ();
+               }
+
+               // from decimal.c
+               private static int Div128By32 (ref ulong hi, ref ulong lo, uint divider)
+               {
+                       uint t = 0;
+                       return Div128By32 (ref hi, ref lo, divider, ref t);
+               }
+
+               // from decimal.c
+               private static int Div128By32 (ref ulong hi, ref ulong lo, uint divider, ref uint rest)
+               {
+                       ulong a = 0;
+                       ulong b = 0;
+                       ulong c = 0;
+
+                       a = (uint) (hi >> 32);
+                       b = a / divider;
+                       a -= b * divider;
+                       a <<= 32;
+                       a |= (uint) hi;
+                       c = a / divider;
+                       a -= c * divider;
+                       a <<= 32;
+                       hi = b << 32 | (uint) c;
+
+                       a = (uint) (lo >> 32);
+                       b = a / divider;
+                       a -= b * divider;
+                       a <<= 32;
+                       a |= (uint) lo;
+                       c = a / divider;
+                       a -= c * divider;
+                       a <<= 32;
+                       lo = b << 32 | (uint) c;
+
+                       rest = (uint) a;
+                       a <<= 1;
+
+                       return (a > divider || (a == divider && (c & 1) == 1)) ? 1 : 0;
+               }
+
+               [MonoTODO ("Find out what is the right way to set scale and precision")]
+               private static SybaseDecimal DecimalDiv (SybaseDecimal x, SybaseDecimal y)
+               {
+                       ulong lo = 0;
+                       ulong hi = 0;
+                       int sc = 0; // scale
+                       int texp = 0;
+                       byte prec = 0;
+
+                       prec = x.Precision >= y.Precision ? x.Precision : y.Precision;
+                       DecimalDivSub (ref x, ref y, ref lo, ref hi, ref texp);
+
+                       sc = x.Scale - y.Scale;
+
+                       Rescale128 (ref lo, ref hi, ref sc, texp, 0, 38, 1);
+
+                       uint r = 0;
+                       while (prec < sc) {
+                               Div128By32 (ref hi, ref lo, 10, ref r);
+                               sc -= 1;
+                       }
+
+                       if (r >= 5)
+                               lo += 1;
+               
+                       while ((((double) hi) * Math.Pow (2, 64) + lo) - Math.Pow (10, prec) > 0)
+                               prec += 1;
+
+                       while ((prec + sc) > MaxScale) {
+                               Div128By32 (ref hi, ref lo, 10, ref r);
+                               sc -= 1;
+                               if (r >= 5)
+                                       lo += 1;
+                       }
+
+                       int resultLo = (int) lo;
+                       int resultMi = (int) (lo >> 32);
+                       int resultMi2 = (int) hi;
+                       int resultHi = (int) (hi >> 32);
+
+                       return new SybaseDecimal (prec, (byte) sc, true, resultLo, resultMi, resultMi2, resultHi);
+               }
+
+               // From decimal.c
+               private static void Rescale128 (ref ulong clo, ref ulong chi, ref int scale, int texp, int minScale, int maxScale, int roundFlag) 
+               {
+                       uint factor = 0;
+                       uint overhang = 0;
+                       int sc = 0;
+                       int i = 0;
+                       int roundBit = 0;
+
+                       sc = scale;
+                       if (texp > 0) {
+                               // reduce exp
+                               while (texp > 0 && sc <= maxScale) {
+                                       overhang = (uint) (chi >> 64);
+                                       while (texp > 0 && (((clo & 1) == 0) || overhang > 0)) {
+                                               if (--texp == 0)
+                                                       roundBit = (int) (clo & 1);
+                                               RShift128 (ref clo, ref chi);
+                                               overhang = (uint) (chi >> 32);
+                                       }
+
+                                       if (texp > DECIMAL_MAX_INTFACTORS)
+                                               i = DECIMAL_MAX_INTFACTORS;
+                                       else
+                                               i = texp;
+                                       
+                                       if (sc + i > maxScale) 
+                                               i = maxScale - sc;
+                                       if (i == 0)
+                                               break;
+                                       
+                                       texp -= i;
+                                       sc += i;
+
+                                       // 10^i/2^i=5^i
+                                       factor = constantsDecadeInt32Factors [i] >> i;
+                                       Mult128By32 (ref clo, ref chi, factor, 0);
+                               }
+
+                               while (texp > 0) {
+                                       if (--texp == 0)
+                                               roundBit = (int) (clo & 1);
+                                       RShift128 (ref clo, ref chi);
+
+                               }
+                       }
+
+                       while (sc > maxScale) {
+                               i = scale - maxScale;
+                               if (i > DECIMAL_MAX_INTFACTORS)
+                                       i = DECIMAL_MAX_INTFACTORS;
+                               sc -= i;
+                               roundBit = Div128By32 (ref clo, ref chi, constantsDecadeInt32Factors [i]);
+                       }
+
+                       while (sc < minScale) {
+                               if (roundFlag == 0)
+                                       roundBit = 0;
+                               i = minScale - sc;
+                               if (i > DECIMAL_MAX_INTFACTORS)
+                                       i = DECIMAL_MAX_INTFACTORS;
+                               sc += i;
+                               Mult128By32 (ref clo, ref chi, constantsDecadeInt32Factors [i], roundBit);
+                               roundBit = 0;
+                       }
+                       scale = sc;
+                       Normalize128 (ref clo, ref chi, ref sc, roundFlag, roundBit);
+               }
+
+               // from decimal.c
+               private static void Normalize128 (ref ulong clo, ref ulong chi, ref int scale, int roundFlag, int roundBit)
+               {
+                       if ((roundFlag != 0) && (roundBit != 0))
+                               RoundUp128 (ref clo, ref chi);
+               }
+
+               // from decimal.c
+               private static void RoundUp128 (ref ulong lo, ref ulong hi)
+               {
+                       if ((++lo) == 0)
+                               ++hi;
+               }
+
+               // from decimal.c
+               private static void DecimalDivSub (ref SybaseDecimal x, ref SybaseDecimal y, ref ulong clo, ref ulong chi, ref int exp)
+               {
+                       ulong xlo, xmi, xhi;
+                       ulong tlo = 0;
+                       ulong tmi = 0;
+                       ulong thi = 0;
+                       uint ylo = 0;
+                       uint ymi = 0;
+                       uint ymi2 = 0;
+                       uint yhi = 0;
+                       int ashift = 0;
+                       int bshift = 0;
+                       int extraBit = 0;
+
+                       xhi = (ulong) ((ulong) x.Data [3] << 32) | (ulong) x.Data [2];
+                       xmi = (ulong) ((ulong) x.Data [1] << 32) | (ulong) x.Data [0];
+                       xlo = (uint) 0;
+                       ylo = (uint) y.Data [0];
+                       ymi = (uint) y.Data [1];
+                       ymi2 = (uint) y.Data [2];
+                       yhi = (uint) y.Data [3];
+
+                       if (ylo == 0 && ymi == 0 && ymi2 == 0 && yhi == 0)
+                               throw new DivideByZeroException ();
+                       if (xmi == 0 && xhi == 0) {
+                               clo = chi = 0;
+                               return;
+                       }
+
+                       // enlarge dividend to get maximal precision
+                       for (ashift = 0; (xhi & LIT_GUINT64_HIGHBIT) == 0; ++ashift) 
+                               LShift128 (ref xmi, ref xhi);
+
+                       // ensure that divisor is at least 2^95
+                       for (bshift = 0; (yhi & LIT_GUINT32_HIGHBIT) == 0; ++bshift) 
+                               LShift128 (ref ylo, ref ymi, ref ymi2, ref yhi);
+
+                       thi = ((ulong) yhi) << 32 | (ulong) ymi2;
+                       tmi = ((ulong) ymi) << 32 | (ulong) ylo;
+                       tlo = 0;
+
+                       if (xhi > thi || (xhi == thi && xmi >= tmi)) {
+                               Sub192 (xlo, xmi, xhi, tlo, tmi, thi, ref xlo, ref xmi, ref xhi);
+                               extraBit = 1;
+                       } else {
+                               extraBit = 0;
+                       }
+
+                       Div192By128To128 (xlo, xmi, xhi, ylo, ymi, ymi2, yhi, ref clo, ref chi);
+
+                       exp = 128 + ashift - bshift;
+
+                       if (extraBit != 0) {
+                               RShift128 (ref clo, ref chi);
+                               chi += LIT_GUINT64_HIGHBIT;
+                               exp -= 1;
+                       }
+
+                       // try loss free right shift
+                       while (exp > 0 && (clo & 1) == 0) {
+                               RShift128 (ref clo, ref chi);
+                               exp -= 1;
+                       }
+               }
+
+               // From decimal.c
+               private static void RShift192 (ref ulong lo, ref ulong mi, ref ulong hi)
+               {
+                       lo >>= 1;
+                       if ((mi & 1) != 0)
+                               lo |= LIT_GUINT64_HIGHBIT;
+                       
+                       mi >>= 1;
+                       if ((hi & 1) != 0)
+                               mi |= LIT_GUINT64_HIGHBIT;
+       
+                       hi >>= 1;
+               }
+
+               // From decimal.c
+               private static void RShift128 (ref ulong lo, ref ulong hi)
+               {
+                       lo >>= 1;
+                       if ((hi & 1) != 0)
+                               lo |= LIT_GUINT64_HIGHBIT;
+                       hi >>= 1;
+               }
+
+               // From decimal.c
+               private static void LShift128 (ref ulong lo, ref ulong hi)
+               {
+                       hi <<= 1;
+
+                       if ((lo & LIT_GUINT64_HIGHBIT) != 0)
+                               hi += 1;
+                       
+                       lo <<= 1;
+               }
+
+               // From decimal.c
+               private static void LShift128 (ref uint lo, ref uint mi, ref uint mi2, ref uint hi)
+               {
+                       hi <<= 1;
+                       if ((mi2 & LIT_GUINT32_HIGHBIT) != 0)
+                               hi += 1;
+
+                       mi2 <<= 1;
+                       if ((mi & LIT_GUINT32_HIGHBIT) != 0)
+                               mi2 += 1;
+
+                       mi <<= 1;
+                       if ((lo & LIT_GUINT32_HIGHBIT) != 0)
+                               mi += 1;
+
+                       lo <<= 1;
+               }
+
+               // From decimal.c
+               private static void Div192By128To128 (ulong xlo, ulong xmi, ulong xhi, uint ylo, uint ymi, uint ymi2, uint yhi, ref ulong clo, ref ulong chi)
+               {
+                       ulong rlo, rmi, rhi; // remainders
+                       uint h, c;
+
+                       rlo = xlo;
+                       rmi = xmi;
+                       rhi = xhi;
+
+                       h = Div192By128To32WithRest (ref rlo, ref rmi, ref rhi, ylo, ymi, ymi2, yhi);
+
+                       // mid 32 bit
+                       rhi = (rhi << 32) | (rmi >> 32);
+                       rmi = (rmi << 32) | (rlo >> 32);
+                       rlo <<= 32;
+
+                       chi = (((ulong)h) << 32) | Div192By128To32WithRest (ref rlo, ref rmi, ref rhi, ylo, ymi, ymi2, yhi);
+
+                       // low 32 bit
+                       rhi = (rhi << 32) | (rmi >> 32);
+                       rmi = (rmi << 32) | (rlo >> 32);
+                       rlo <<= 32;
+
+                       h = Div192By128To32WithRest (ref rlo, ref rmi, ref rhi, ylo, ymi, ymi2, yhi);
+
+                       // estimate lowest 32 bit (two last bits may be wrong)
+                       if (rhi >= yhi)
+                               c =  0xFFFFFFFF;
+                       else {
+                               rhi <<= 32;
+                               c = (uint)(rhi / yhi);
+                       }
+
+                       clo = (((ulong)h) << 32) | c;
+               }
+
+               // From decimal.c
+               private static uint Div192By128To32WithRest (ref ulong xlo, ref ulong xmi, ref ulong xhi, uint ylo, uint ymi, uint ymi2, uint yhi)
+               {
+                       ulong rlo, rmi, rhi; // remainder
+                       ulong tlo = 0;
+                       ulong thi = 0;
+                       uint c;
+
+                       rlo = xlo;
+                       rmi = xmi;
+                       rhi = xhi;
+
+                       if (rhi >= (((ulong)yhi << 32)))
+                               c = 0xFFFFFFFF;
                        else
-                               return value.ToString ();
+                               c = (uint) (rhi / yhi);
+
+                       Mult128By32To128 (ylo, ymi, ymi2, yhi, c, ref tlo, ref thi);
+                       Sub192 (rlo, rmi, rhi, 0, tlo, thi, ref rlo, ref rmi, ref rhi);
+
+                       while (((long)rhi) < 0) {
+                               c--;
+                               Add192 (rlo, rmi, rhi, 0, (((ulong)ymi) << 32) | ylo, yhi | ymi2, ref rlo, ref rmi, ref rhi);
+                       }
+                       xlo = rlo;
+                       xmi = rmi;
+                       xhi = rhi;
+
+                       return c;
+               }
+
+               // From decimal.c
+               private static void Mult192By32 (ref ulong clo, ref ulong cmi, ref ulong chi, ulong factor, int roundBit)
+               {
+                       ulong a = 0;
+                       uint h0 = 0;
+                       uint h1 = 0;
+
+                       a = ((ulong)(uint)clo) * factor;
+
+                       if (roundBit != 0)
+                               a += factor / 2;
+
+                       h0 = (uint)a;
+                       a >>= 32;
+                       a += (clo >> 32) * factor;
+                       h1 = (uint)a;
+
+                       clo = ((ulong)h1) << 32 | h0;
+
+                       a >>= 32;
+                       a += ((ulong)(uint)cmi) * factor;
+                       h0 = (uint)a;
+
+                       a >>= 32;
+                       a += (cmi >> 32) * factor;
+                       h1 = (uint)a;
+
+                       cmi = ((ulong)h1) << 32 | h0;
+                       a >>= 32;
+                       a += ((ulong)(uint)chi) * factor;
+                       h0 = (uint)a;
+
+                       a >>= 32;
+                       a += (chi >> 32) * factor;
+                       h1 = (uint)a;
+                       chi = ((ulong)h1) << 32 | h0;
+               }
+
+               // From decimal.c
+               private static void Mult128By32 (ref ulong clo, ref ulong chi, uint factor, int roundBit)
+               {
+                       ulong a = 0;
+                       uint h0 = 0;
+                       uint h1 = 0;
+
+                       a = ((ulong)(uint)clo) * factor;
+
+                       if (roundBit != 0)
+                               a += factor / 2;
+
+                       h0 = (uint)a;
+
+                       a >>= 32;
+                       a += (clo >> 32) * factor;
+                       h1 = (uint)a;
+
+                       clo = ((ulong)h1) << 32 | h0;
+
+                       a >>= 32;
+                       a += ((ulong)(uint)chi) * factor;
+                       h0 = (uint)a;
+
+                       a >>= 32;
+                       a += (chi >> 32) * factor;
+                       h1 = (uint)a;
+
+                       chi = ((ulong)h1) << 32 | h0;
+               }
+
+               // From decimal.c
+               private static void Mult128By32To128 (uint xlo, uint xmi, uint xmi2, uint xhi, uint factor, ref ulong clo, ref ulong chi)
+               {
+                       ulong a;
+                       uint h0, h1, h2;
+
+                       a = ((ulong)xlo) * factor;
+                       h0 = (uint)a;
+
+                       a >>= 32;
+                       a += ((ulong)xmi) * factor;
+                       h1 = (uint)a;
+
+                       a >>= 32;
+                       a += ((ulong)xmi2) * factor;
+                       h2 = (uint)a;
+
+                       a >>= 32;
+                       a += ((ulong)xhi) * factor;
+
+                       clo = ((ulong)h1) << 32 | h0;
+                       chi = a | h2;
+               }
+
+               // From decimal.c
+               private static void Add192 (ulong xlo, ulong xmi, ulong xhi, ulong ylo, ulong ymi, ulong yhi, ref ulong clo, ref ulong cmi, ref ulong chi)
+               {
+                       xlo += ylo;
+                       if (xlo < ylo) {
+                               xmi++;
+                               if (xmi == 0)
+                                       xhi++;
+                       }
+
+                       xmi += ymi;
+
+                       if (xmi < ymi)
+                               xmi++;
+
+                       xhi += yhi;
+                       clo = xlo;
+                       cmi = xmi;
+                       chi = xhi;
+               }
+
+               // From decimal.c
+               private static void Sub192 (ulong xlo, ulong xmi, ulong xhi, ulong ylo, ulong ymi, ulong yhi, ref ulong lo, ref ulong mi, ref ulong hi)
+               {
+                       ulong clo = 0;
+                       ulong cmi = 0;
+                       ulong chi = 0;
+
+                       clo = xlo - ylo;
+                       cmi = xmi - ymi;
+                       chi = xhi - yhi;
+
+                       if (xlo < ylo) {
+                               if (cmi == 0)
+                                       chi--;
+                               cmi--;
+                       }
+
+                       if (xmi < ymi)
+                               chi--;
+
+                       lo = clo;
+                       mi = cmi;
+                       hi = chi;
                }
 
-               [MonoTODO]
                public static SybaseDecimal Truncate (SybaseDecimal n, int position)
                {
-                       throw new NotImplementedException ();
+                       return new SybaseDecimal ((byte) n.Precision, (byte) position, n.IsPositive, n.Data);
                }
 
                public static SybaseDecimal operator + (SybaseDecimal x, SybaseDecimal y)
@@ -377,10 +946,9 @@ namespace Mono.Data.SybaseTypes {
                                return new SybaseDecimal (resultPrecision, x.Scale, x.IsPositive, resultBits);
                }
 
-               [MonoTODO]
                public static SybaseDecimal operator / (SybaseDecimal x, SybaseDecimal y)
                {
-                       throw new NotImplementedException ();
+                       return DecimalDiv (x, y);
                }
 
                public static SybaseBoolean operator == (SybaseDecimal x, SybaseDecimal y)
index de880819f6ef044d07ad9e5d04007e0a33b39e05..ed883e2cd1b9bff3e41f2cbfd192c7cbdcf55732 100644 (file)
@@ -4,7 +4,10 @@
 // Author:
 //   Tim Coleman <tim@timcoleman.com>
 //
-// (C) Copyright Tim Coleman, 2002
+// Based on System.Data.SqlTypes.SqlDouble
+//
+// (C) Ximian, Inc. 2002-2003
+// (C) Copyright Tim Coleman, 2002-2003
 //
 
 using Mono.Data.SybaseClient;
@@ -20,8 +23,8 @@ namespace Mono.Data.SybaseTypes {
 
                private bool notNull;
 
-               public static readonly SybaseDouble MaxValue = new SybaseDouble (1.7976931348623157e308);
-               public static readonly SybaseDouble MinValue = new SybaseDouble (-1.7976931348623157e308);
+               public static readonly SybaseDouble MaxValue = new SybaseDouble (1.7976931348623157E+308);
+               public static readonly SybaseDouble MinValue = new SybaseDouble (-1.7976931348623157E+308);
                public static readonly SybaseDouble Null;
                public static readonly SybaseDouble Zero = new SybaseDouble (0);
 
index 81fa78de5a2dbebb71974bac1b5dd5985e9c8bc5..90cb326869e5ff05abcf30f6f1d47f58394dfd97 100644 (file)
@@ -4,7 +4,10 @@
 // Author:
 //   Tim Coleman <tim@timcoleman.com>
 //
-// (C) Copyright 2002 Tim Coleman
+// Based on System.Data.SqlTypes.SqlMoney
+//
+// (C) Ximian, Inc. 2002-2003
+// (C) Copyright Tim Coleman, 2002-2003
 //
 
 using Mono.Data.SybaseClient;
@@ -58,7 +61,6 @@ namespace Mono.Data.SybaseTypes {
 
                #region Properties
 
-               [MonoTODO]
                public bool IsNull { 
                        get { return !notNull; }
                }
index d6d28ed249c15948e733cbac0e01996ab4f69002..d49cffac0d3f90786ec3cf5914b6d87b231f19f7 100644 (file)
@@ -4,13 +4,17 @@
 // Author:
 //   Tim Coleman (tim@timcoleman.com)
 //
-// (C) Copyright Tim Coleman, 2002
+// Based on System.Data.SqlTypes.SqlString
+//
+// (C) Ximian, Inc. 2002-2003
+// (C) Copyright Tim Coleman, 2002-2003
 //
 
 using Mono.Data.SybaseClient;
 using System;
 using System.Data.SqlTypes;
 using System.Globalization;
+using System.Text;
 
 namespace Mono.Data.SybaseTypes {
        public struct SybaseString : INullable, IComparable 
@@ -21,11 +25,14 @@ namespace Mono.Data.SybaseTypes {
 
                private bool notNull;
 
-               public static readonly int BinarySort;
-               public static readonly int IgnoreCase;
-               public static readonly int IgnoreKanaType;
-               public static readonly int IgnoreNonSpace;
-               public static readonly int IgnoreWidth;
+               private CultureInfo cultureInfo;
+               private SybaseCompareOptions compareOptions;
+
+               public static readonly int BinarySort = 0x8000;
+               public static readonly int IgnoreCase = 0x1;
+               public static readonly int IgnoreKanaType = 0x8;
+               public static readonly int IgnoreNonSpace = 0x2;
+               public static readonly int IgnoreWidth = 0x10;
                public static readonly SybaseString Null;
 
                #endregion // Fields
@@ -36,55 +43,72 @@ namespace Mono.Data.SybaseTypes {
                public SybaseString (string data) 
                {
                        this.value = data;
-                       notNull = true;
+                       this.cultureInfo = CultureInfo.CurrentCulture;
+                       this.compareOptions = SybaseCompareOptions.None;
+                       this.notNull = true;
                }
 
                // init with a string data and locale id values.
-               [MonoTODO]
                public SybaseString (string data, int lcid) 
+                       : this (data, lcid, SybaseCompareOptions.None)
                {
-                       throw new NotImplementedException ();
                }
 
                // init with locale id, compare options, 
                // and an array of bytes data
-               [MonoTODO]
                public SybaseString (int lcid, SybaseCompareOptions compareOptions, byte[] data) 
+                       : this (lcid, compareOptions, data, true)
                {
-                       throw new NotImplementedException ();
                }
 
                // init with string data, locale id, and compare options
-               [MonoTODO]
                public SybaseString (string data, int lcid, SybaseCompareOptions compareOptions) 
                {
-                       throw new NotImplementedException ();
+                       this.value = data;
+                       this.cultureInfo = new CultureInfo (lcid);
+                       this.compareOptions = compareOptions;
+                       this.notNull = true;
                }
 
                // init with locale id, compare options, array of bytes data,
                // and whether unicode is encoded or not
-               [MonoTODO]
                public SybaseString (int lcid, SybaseCompareOptions compareOptions, byte[] data, bool fUnicode) 
                {
-                       throw new NotImplementedException ();
+                       Encoding encoding;
+                       if (fUnicode)
+                               encoding = new UnicodeEncoding ();
+                       else
+                               encoding = new ASCIIEncoding ();
+
+                       this.value = encoding.GetString (data);
+                       this.cultureInfo = new CultureInfo (lcid);
+                       this.compareOptions = compareOptions;
+                       this.notNull = true;
                }
 
                // init with locale id, compare options, array of bytes data,
                // starting index in the byte array, 
                // and number of bytes to copy
-               [MonoTODO]
                public SybaseString (int lcid, SybaseCompareOptions compareOptions, byte[] data, int index, int count) 
+                       : this (lcid, compareOptions, data, index, count, true)
                {
-                       throw new NotImplementedException ();
                }
 
                // init with locale id, compare options, array of bytes data,
                // starting index in the byte array, number of byte to copy,
                // and whether unicode is encoded or not
-               [MonoTODO]
                public SybaseString (int lcid, SybaseCompareOptions compareOptions, byte[] data, int index, int count, bool fUnicode) 
                {
-                       throw new NotImplementedException ();
+                       Encoding encoding;
+                       if (fUnicode)
+                               encoding = new UnicodeEncoding ();
+                       else
+                               encoding = new ASCIIEncoding ();
+
+                       this.value = encoding.GetString (data, index, count);
+                       this.cultureInfo = new CultureInfo (lcid);
+                       this.compareOptions = compareOptions;
+                       this.notNull = true;
                }
 
                #endregion // Constructors
@@ -93,15 +117,11 @@ namespace Mono.Data.SybaseTypes {
                #region Public Properties
 
                public CompareInfo CompareInfo {
-                       [MonoTODO]
-                       get { throw new NotImplementedException ();
-                       }
+                       get { return cultureInfo.CompareInfo; }
                }
 
                public CultureInfo CultureInfo {
-                       [MonoTODO]
-                       get { throw new NotImplementedException ();
-                       }
+                       get { return cultureInfo; }
                }
 
                public bool IsNull {
@@ -110,40 +130,45 @@ namespace Mono.Data.SybaseTypes {
 
                // geographics location and language (locale id)
                public int LCID {
-                       [MonoTODO]
-                       get { throw new NotImplementedException ();
-                       }
+                       get { return cultureInfo.LCID; }
                }
        
                public SybaseCompareOptions SybaseCompareOptions {
-                       [MonoTODO]
-                       get { throw new NotImplementedException ();
-                       }
+                       get { return compareOptions; }
                }
 
-                public string Value {
-                        get {
-                                if (this.IsNull)
-                                        throw new SybaseNullValueException ("The property contains Null.");
-                                else
-                                        return value;
-                        }
-                }
+               public string Value {
+                       get {
+                               if (this.IsNull)
+                                       throw new SybaseNullValueException ("The property contains Null.");
+                               else
+                                       return value;
+                       }
+               }
 
                #endregion // Public Properties
 
                #region Public Methods
 
-               [MonoTODO]
                public SybaseString Clone() 
                {
-                       throw new NotImplementedException ();
+                       return new SybaseString (value, LCID, SybaseCompareOptions);
                }
 
-               [MonoTODO]
                public static CompareOptions CompareOptionsFromSybaseCompareOptions (SybaseCompareOptions compareOptions) 
                {
-                       throw new NotImplementedException ();
+                       CompareOptions options = CompareOptions.None;
+                       if ((compareOptions & SybaseCompareOptions.IgnoreCase) != 0)
+                               options |= CompareOptions.IgnoreCase;
+                       if ((compareOptions & SybaseCompareOptions.IgnoreKanaType) != 0)
+                               options |= CompareOptions.IgnoreKanaType;
+                       if ((compareOptions & SybaseCompareOptions.IgnoreNonSpace) != 0)
+                               options |= CompareOptions.IgnoreNonSpace;
+                       if ((compareOptions & SybaseCompareOptions.IgnoreWidth) != 0)
+                               options |= CompareOptions.IgnoreWidth;
+                       if ((compareOptions & SybaseCompareOptions.BinarySort) != 0)
+                               throw new ArgumentOutOfRangeException ();
+                       return options;
                }
 
                // **********************************
@@ -180,22 +205,33 @@ namespace Mono.Data.SybaseTypes {
                        return (x == y);
                }
 
-               [MonoTODO]
                public override int GetHashCode() 
                {
-                       throw new NotImplementedException ();
+                       int result = 10;
+                       for (int i = 0; i < value.Length; i += 1)
+                               result = 91 * result + (int) (value [i] ^ (value [i] >> 32));
+                       result = 91 * result + LCID.GetHashCode ();
+                       result = 91 * result + (int) compareOptions;
+                       return result;
                }
 
-               [MonoTODO]
                public byte[] GetNonUnicodeBytes() 
                {
-                       throw new NotImplementedException ();
+                       return GetBytes (new ASCIIEncoding ());
                }
 
-               [MonoTODO]
                public byte[] GetUnicodeBytes() 
                {
-                       throw new NotImplementedException ();
+                       return GetBytes (new UnicodeEncoding ());
+               }
+
+               private byte[] GetBytes (Encoding encoding)
+               {
+                       int blen = encoding.GetByteCount (value);
+                       int clen = value.Length;
+                       byte[] bytes = new byte [blen];
+                       encoding.GetBytes (value, 0, clen, bytes, 0);
+                       return bytes;
                }
 
                public static SybaseBoolean GreaterThan(SybaseString x, SybaseString y)