2002-07-10 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mcs / class / corlib / System / Convert.cs
index d8b86002838c488c3ab34e98e0ba1d6dc9831191..97b7800e9ac89c580fed4f2045261266caffc08a 100644 (file)
@@ -78,7 +78,7 @@ namespace System {
        public sealed class Convert {\r
 \r
                // Fields\r
-               public static readonly object DBNull;\r
+               public static readonly object DBNull = System.DBNull.Value;\r
        \r
                private Convert () {}\r
 \r
@@ -126,9 +126,7 @@ namespace System {
 \r
                public static bool IsDBNull (object value)\r
                {\r
-                       TypeCode tc = Type.GetTypeCode (value.GetType ());\r
-                       \r
-                       if (tc == TypeCode.DBNull)\r
+                       if (value is DBNull)\r
                                return true;\r
                        else\r
                                return false;\r
@@ -707,7 +705,7 @@ namespace System {
 \r
                public static decimal ToDecimal (float value) \r
                {\r
-                       return (decimal) Math.Round (value);                            \r
+                       return (decimal) value;\r
                }\r
 \r
                public static decimal ToDecimal (int value) \r
@@ -781,7 +779,7 @@ namespace System {
        \r
                public static double ToDouble (byte value) \r
                { \r
-                       throw new InvalidCastException ("This conversion is not supported.");\r
+                       return (double) value;\r
                }\r
 \r
                public static double ToDouble (char value)\r
@@ -806,7 +804,7 @@ namespace System {
 \r
                public static double ToDouble (float value) \r
                { \r
-                       return (double) Math.Round (value);       \r
+                       return (double) value;\r
                }\r
 \r
                public static double ToDouble (int value) \r
@@ -968,7 +966,7 @@ namespace System {
                \r
                public static short ToInt16 (string value, int fromBase)\r
                {\r
-                       return (short) ConvertFromBase (value, fromBase);\r
+                       return Convert.ToInt16 (ConvertFromBase (value, fromBase));\r
                }\r
 \r
                [CLSCompliant (false)]\r
@@ -1233,7 +1231,7 @@ namespace System {
                        if (NotValidBase (fromBase))\r
                                throw new ArgumentException ("fromBase is not valid.");\r
                        \r
-                       return (long) ConvertFromBase (value, fromBase);\r
+                       return ConvertFromBase64 (value, fromBase);\r
                }\r
 \r
                [CLSCompliant (false)]\r
@@ -1390,6 +1388,9 @@ namespace System {
                {\r
                        int retVal = ConvertFromBase (value, fromBase);\r
 \r
+                       if (retVal == 255)\r
+                               return (sbyte)-1;\r
+\r
                        if (retVal < (int) SByte.MinValue || retVal > (int) SByte.MaxValue)\r
                                throw new OverflowException ();\r
                        else\r
@@ -1651,7 +1652,7 @@ namespace System {
                        if (NotValidBase (toBase))\r
                                throw new ArgumentException ("toBase is not valid.");\r
                        \r
-                       return ConvertToBase ((int) value, toBase);\r
+                       return ConvertToBase (value, toBase);\r
                }\r
 \r
                public static string ToString (long value, IFormatProvider provider) \r
@@ -2252,23 +2253,63 @@ namespace System {
                        if (NotValidBase (fromBase))\r
                                throw new ArgumentException ("fromBase is not valid.");\r
 \r
-                       \r
                        int chars = 0;\r
                        int result = 0;\r
+                       int digitValue;\r
+\r
+                       foreach (char c in value) {\r
+                               if (Char.IsNumber (c))\r
+                                       digitValue = c - '0';\r
+                               else if (Char.IsLetter (c))\r
+                                       digitValue = Char.ToLower(c) - 'a' + 10;\r
+                               else\r
+                                       throw new FormatException ("This is an invalid string: " + value);\r
+\r
+                               if (digitValue >= fromBase)\r
+                                       throw new FormatException ("the digits are invalid.");\r
+\r
+                               result = (fromBase) * result + digitValue;\r
+                               chars ++;\r
+                       }\r
+\r
+                       if (chars == 0)\r
+                               throw new FormatException ("Could not find any digits.");\r
+\r
+                       if (result > Int32.MaxValue || result < Int32.MinValue)\r
+                               throw new OverflowException ("There is an overflow.");\r
+                       \r
+                       return result;\r
+               }\r
+\r
+               private static long ConvertFromBase64 (string value, int fromBase)\r
+               {\r
+                       if (NotValidBase (fromBase))\r
+                               throw new ArgumentException ("fromBase is not valid.");\r
+\r
+                       int chars = 0;\r
+                       int digitValue;\r
+                       long result = 0;\r
 \r
                        foreach (char c in value) {\r
-                               if (Char.IsLetter (c)) {\r
-                                       result = (fromBase) * result + c - 'a' + 10;\r
-                                       chars ++;\r
-                               } else if (Char.IsNumber (c)) {\r
-                                       result = (fromBase) * result + c - '0';\r
-                                       chars ++;\r
-                               } else\r
+                               if (Char.IsNumber (c))\r
+                                       digitValue = c - '0';\r
+                               else if (Char.IsLetter (c))\r
+                                       digitValue = Char.ToLower(c) - 'a' + 10;\r
+                               else\r
                                        throw new FormatException ("This is an invalid string: " + value);\r
+\r
+                               if (digitValue >= fromBase)\r
+                                       throw new FormatException ("the digits are invalid.");\r
+\r
+                               result = (fromBase) * result + digitValue;\r
+                               chars ++;\r
                        }\r
 \r
                        if (chars == 0)\r
                                throw new FormatException ("Could not find any digits.");\r
+\r
+                       if (result > Int64.MaxValue || result < Int64.MinValue)\r
+                               throw new OverflowException ("There is an overflow.");\r
                        \r
                        return result;\r
                }\r
@@ -2280,6 +2321,14 @@ namespace System {
                        return sb.ToString ();\r
                }\r
 \r
+               private static string ConvertToBase (long value, int toBase)\r
+               {\r
+                       StringBuilder sb = new StringBuilder ();\r
+                       BuildConvertedString64 (sb, value, toBase);\r
+                       return sb.ToString ();\r
+               }\r
+               \r
+\r
                internal static void BuildConvertedString (StringBuilder sb, int value, int toBase)\r
                {\r
                        int divided = value / toBase;\r
@@ -2293,6 +2342,20 @@ namespace System {
                        else\r
                                sb.Append ((char) (reminder + '0'));\r
                }\r
+\r
+               internal static void BuildConvertedString64 (StringBuilder sb, long value, int toBase)\r
+               {\r
+                       long divided = value / toBase;\r
+                       long reminder = value % toBase;         \r
+\r
+                       if (divided > 0)\r
+                               BuildConvertedString64 (sb, divided, toBase);\r
+               \r
+                       if (reminder >= 10)\r
+                               sb.Append ((char) (reminder + 'a' - 10));\r
+                       else\r
+                               sb.Append ((char) (reminder + '0'));\r
+               }\r
                \r
                 // Lookup table for the conversion ToType method. Order\r
                // is important! Used by ToType for comparing the target\r
@@ -2316,6 +2379,7 @@ namespace System {
                        typeof (Double),   // 14 TypeCode.Double\r
                        typeof (Decimal),  // 15 TypeCode.Decimal\r
                        typeof (DateTime), // 16 TypeCode.DateTime\r
+                       null,              // 17 null.\r
                        typeof (String),   // 18 TypeCode.String\r
                };\r
 \r
@@ -2326,21 +2390,23 @@ namespace System {
                internal static object ToType (object value, Type conversionType, \r
                                               IFormatProvider provider) \r
                {\r
+                       if (value == null && conversionType == null)\r
+                               return null;\r
+                       \r
                        if (value == null)\r
-                               throw new ArgumentException (Locale.GetText (\r
-                                       "Invalid conversion from null value"));\r
-\r
+                               throw new NullReferenceException ("Value is null.");\r
+                       \r
                        if (value is IConvertible) {\r
                                IConvertible convertValue = (IConvertible) value;\r
 \r
                                if (conversionType == conversionTable[0]) // 0 Empty\r
-                                       return null;\r
+                                       throw new ArgumentNullException ();\r
                                \r
                                else if (conversionType == conversionTable[1]) // 1 TypeCode.Object\r
                                        return (object) value;\r
                                        \r
-                               // else if (conversionType == conversionTable[2]) // 2 TypeCode.DBNull\r
-                               //      return null;                           // It's not IConvertible\r
+                               else if (conversionType == conversionTable[2]) // 2 TypeCode.DBNull\r
+                                       throw new InvalidCastException ();     // It's not IConvertible\r
                  \r
                                else if (conversionType == conversionTable[3]) // 3 TypeCode.Boolean\r
                                        return (object) convertValue.ToBoolean (provider);\r
@@ -2387,11 +2453,11 @@ namespace System {
                                else if (conversionType == conversionTable[18]) // 18 TypeCode.String\r
                                        return (object) convertValue.ToString (provider);\r
                                else\r
-                                       throw new InvalidCastException (Locale.GetText ("Unknown target conversion type"));\r
+                                       throw new ArgumentException (Locale.GetText ("Unknown target conversion type"));\r
                        } else\r
                                // Not in the conversion table\r
-                               throw new ArgumentException ((Locale.GetText (\r
-                                       "Value is not a convertible object: " + value.GetType().ToString() + " to " + conversionType.ToString())));\r
+                               throw new InvalidCastException ((Locale.GetText (\r
+                                       "Value is not a convertible object: " + value.GetType().ToString() + " to " + conversionType.FullName)));\r
                }\r
        }\r
 }\r