2002-04-09 Gonzalo Paniagua Javier <gonzalo@ximian.com>
authorGonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Mon, 8 Apr 2002 20:26:36 +0000 (20:26 -0000)
committerGonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Mon, 8 Apr 2002 20:26:36 +0000 (20:26 -0000)
* SByte.cs:
* Int16.cs:
* Int32.cs:
* Int64.cs: added complex Parse ().

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

mcs/class/corlib/System/Int16.cs
mcs/class/corlib/System/Int32.cs
mcs/class/corlib/System/Int64.cs
mcs/class/corlib/System/SByte.cs

index 185c29273f91ce5a3136f3c773588e70719d69d0..9b03f15f59fef974672f365687830eae042528a4 100644 (file)
@@ -114,10 +114,13 @@ namespace System {
                        return Parse (s, style, null);
                }
 
-               [MonoTODO]
                public static short Parse (string s, NumberStyles style, IFormatProvider fp)
                {
-                       throw new NotImplementedException ();
+                       int tmpResult = Int32.Parse (s, style, fp);
+                       if (tmpResult > Int16.MaxValue || tmpResult < Int16.MinValue)
+                               throw new OverflowException ("Value too large or too small.");
+
+                       return (short) tmpResult;
                }
 
                public override string ToString ()
index 20a6aa38cf31d345b37abffcacd3b57fce444ff9..e04679b4e6ac39152084ef8ecdf1ce26dd0e1ef6 100644 (file)
@@ -8,6 +8,7 @@
 //
 
 using System.Globalization;
+using System.Threading;
 
 namespace System {
        
@@ -112,12 +113,273 @@ namespace System {
                        return Parse (s, style, null);
                }
 
-               [MonoTODO]
+               private delegate bool IsAnything (Char c);
+
+               private static void CheckStyle (NumberStyles style)
+               {
+                       if ((style & NumberStyles.AllowHexSpecifier) != 0 &&
+                           ((style | ~NumberStyles.AllowLeadingWhite) != 0 || 
+                            (style | ~NumberStyles.AllowTrailingWhite) != 0))
+                               throw new ArgumentException (
+                                       "With AllowHexSpecifier only " + 
+                                       "AllowLeadingWhite and AllowTrailingWhite " + 
+                                       "are permitted.");
+               }
+               
+               private static int JumpOverWhite (int pos, string s, bool excp)
+               {
+                       while (pos < s.Length && Char.IsWhiteSpace (s [pos]))
+                               pos++;
+
+                       if (excp && pos >= s.Length)
+                               throw new FormatException ("Input string was not in the correct format.");
+
+                       return pos;
+               }
+
+               private static void FindSign (ref int pos, string s, NumberFormatInfo nfi, 
+                                     ref bool foundSign, ref bool negative)
+               {
+                       if ((pos + nfi.NegativeSign.Length) <= s.Length &&
+                            s.Substring (pos, nfi.NegativeSign.Length) == nfi.NegativeSign) {
+                               negative = true;
+                               foundSign = true;
+                               pos += nfi.NegativeSign.Length;
+                       } 
+                       else if ((pos + nfi.PositiveSign.Length) < s.Length &&
+                            s.Substring (pos, nfi.PositiveSign.Length) == nfi.PositiveSign) {
+                               negative = false;
+                               pos += nfi.PositiveSign.Length;
+                               foundSign = true;
+                       } 
+               }
+
+               private static void FindCurrency (ref int pos,
+                                                string s, 
+                                                NumberFormatInfo nfi,
+                                                ref bool foundCurrency)
+               {
+                       if ((pos + nfi.CurrencySymbol.Length) <= s.Length &&
+                            s.Substring (pos, nfi.CurrencySymbol.Length) == nfi.CurrencySymbol) {
+                               foundCurrency = true;
+                               pos += nfi.CurrencySymbol.Length;
+                       } 
+               }
+
+               private static bool FindOther (ref int pos,
+                                             string s, 
+                                             string other)
+               {
+                       if ((pos + other.Length) <= s.Length &&
+                            s.Substring (pos, other.Length) == other) {
+                               pos += other.Length;
+                               return true;
+                       } 
+
+                       return false;
+               }
+
                public static int Parse (string s, NumberStyles style, IFormatProvider fp)
                {
-                       // FIXME: Better than nothing ;-)
-                       return Parse (s);
-                       //throw new NotImplementedException ();
+                       if (s == null)
+                               throw new ArgumentNullException ();
+
+                       if (s.Length == 0)
+                               throw new FormatException ("Input string was not " + 
+                                                          "in the correct format.");
+
+                       NumberFormatInfo nfi;
+                       if (fp != null) {
+                               Type typeNFI = Type.GetType ("System.Globalization.NumberFormatInfo");
+                               nfi = (NumberFormatInfo) fp.GetFormat (typeNFI);
+                       }
+                       else
+                               nfi = Thread.CurrentThread.CurrentCulture.NumberFormat;
+
+                       CheckStyle (style);
+
+                       bool AllowCurrencySymbol = (style & NumberStyles.AllowCurrencySymbol) != 0;
+                       bool AllowExponent = (style & NumberStyles.AllowExponent) != 0;
+                       bool AllowHexSpecifier = (style & NumberStyles.AllowHexSpecifier) != 0;
+                       bool AllowThousands = (style & NumberStyles.AllowThousands) != 0;
+                       bool AllowDecimalPoint = (style & NumberStyles.AllowDecimalPoint) != 0;
+                       bool AllowParentheses = (style & NumberStyles.AllowParentheses) != 0;
+                       bool AllowTrailingSign = (style & NumberStyles.AllowTrailingSign) != 0;
+                       bool AllowLeadingSign = (style & NumberStyles.AllowLeadingSign) != 0;
+                       bool AllowTrailingWhite = (style & NumberStyles.AllowTrailingWhite) != 0;
+                       bool AllowLeadingWhite = (style & NumberStyles.AllowLeadingWhite) != 0;
+
+                       int pos = 0;
+
+                       if (AllowLeadingWhite)
+                               pos = JumpOverWhite (pos, s, true);
+
+                       bool foundOpenParentheses = false;
+                       bool negative = false;
+                       bool foundSign = false;
+                       bool foundCurrency = false;
+
+                       // Pre-number stuff
+                       if (AllowParentheses && s [pos] == '(') {
+                               foundOpenParentheses = true;
+                               foundSign = true;
+                               negative = true; // MS always make the number negative when there parentheses
+                                                // even when NumberFormatInfo.NumberNegativePattern != 0!!!
+                               pos++;
+                               if (AllowLeadingWhite)
+                                       pos = JumpOverWhite (pos, s, true);
+
+                               if (s.Substring (pos, nfi.NegativeSign.Length) == nfi.NegativeSign)
+                                       throw new FormatException ("Input string was not in the correct " +
+                                                                  "format.");
+                               if (s.Substring (pos, nfi.PositiveSign.Length) == nfi.PositiveSign)
+                                       throw new FormatException ("Input string was not in the correct " +
+                                                                  "format.");
+                       }
+
+                       if (AllowLeadingSign && !foundSign) {
+                               // Sign + Currency
+                               FindSign (ref pos, s, nfi, ref foundSign, ref negative);
+                               if (foundSign) {
+                                       if (AllowLeadingWhite)
+                                               pos = JumpOverWhite (pos, s, true);
+                                       if (AllowCurrencySymbol) {
+                                               FindCurrency (ref pos, s, nfi,
+                                                             ref foundCurrency);
+                                               if (foundCurrency && AllowLeadingWhite)
+                                                       pos = JumpOverWhite (pos, s, true);
+                                       }
+                               }
+                       }
+                       
+                       if (AllowCurrencySymbol && !foundCurrency) {
+                               // Currency + sign
+                               FindCurrency (ref pos, s, nfi, ref foundCurrency);
+                               if (foundCurrency) {
+                                       if (AllowLeadingWhite)
+                                               pos = JumpOverWhite (pos, s, true);
+                                       if (foundCurrency) {
+                                               if (!foundSign && AllowLeadingSign) {
+                                                       FindSign (ref pos, s, nfi, ref foundSign,
+                                                                 ref negative);
+                                                       if (foundSign && AllowLeadingWhite)
+                                                               pos = JumpOverWhite (pos, s, true);
+                                               }
+                                       }
+                               }
+                       }
+                       
+                       IsAnything validDigit;
+                       if (AllowHexSpecifier)
+                               validDigit = new IsAnything (Char.IsNumber);
+                       else
+                               validDigit = new IsAnything (Char.IsDigit);
+                       
+                       int number = 0;
+                       int nDigits = 0;
+                       bool decimalPointFound = false;
+                       int digitValue;
+                       char hexDigit;
+                               
+                       // Number stuff
+                       do {
+
+                               if (!validDigit (s [pos])) {
+                                       if (AllowThousands &&
+                                           FindOther (ref pos, s, nfi.NumberGroupSeparator))
+                                           continue;
+                                       else
+                                       if (!decimalPointFound && AllowDecimalPoint &&
+                                           FindOther (ref pos, s, nfi.NumberDecimalSeparator)) {
+                                           decimalPointFound = true;
+                                           continue;
+                                       }
+
+                                       break;
+                               }
+                               else if (AllowHexSpecifier) {
+                                       hexDigit = s [pos++];
+                                       if (Char.IsDigit (hexDigit))
+                                               digitValue = (int) (hexDigit - '0');
+                                       else if (Char.IsLower (hexDigit))
+                                               digitValue = (int) (hexDigit - 'a');
+                                       else
+                                               digitValue = (int) (hexDigit - 'A');
+
+                                       number = checked (number * 16 - digitValue);
+                               }
+                               else if (decimalPointFound) {
+                                       nDigits++;
+                                       // Allows decimal point as long as it's only 
+                                       // followed by zeroes.
+                                       if (s [pos++] != '0')
+                                               throw new FormatException ("Input string was not in the " + 
+                                                                          "correct format.");
+                               }
+                               else {
+                                       nDigits++;
+
+                                       try {
+                                               // Calculations done as negative
+                                               // (abs (MinValue) > abs (MaxValue))
+                                               number = checked (
+                                                       number * 10 - 
+                                                       (int) (s [pos++] - '0')
+                                                       );
+                                       } catch (OverflowException) {
+                                               throw new OverflowException ("Value too large or too " +
+                                                                            "small.");
+                                       }
+                               }
+                       } while (pos < s.Length);
+
+                       // Post number stuff
+                       if (nDigits == 0)
+                               throw new FormatException ("Input string was not in the correct format.");
+
+                       if (AllowTrailingSign && !foundSign) {
+                               // Sign + Currency
+                               FindSign (ref pos, s, nfi, ref foundSign, ref negative);
+                               if (foundSign) {
+                                       if (AllowTrailingWhite)
+                                               pos = JumpOverWhite (pos, s, true);
+                                       if (AllowCurrencySymbol)
+                                               FindCurrency (ref pos, s, nfi,
+                                                             ref foundCurrency);
+                               }
+                       }
+                       
+                       if (AllowCurrencySymbol && !foundCurrency) {
+                               // Currency + sign
+                               FindCurrency (ref pos, s, nfi, ref foundCurrency);
+                               if (foundCurrency) {
+                                       if (AllowTrailingWhite)
+                                               pos = JumpOverWhite (pos, s, true);
+                                       if (!foundSign && AllowTrailingSign)
+                                               FindSign (ref pos, s, nfi, ref foundSign,
+                                                         ref negative);
+                               }
+                       }
+                       
+                       if (AllowTrailingWhite && pos < s.Length)
+                               pos = JumpOverWhite (pos, s, false);
+
+                       if (foundOpenParentheses) {
+                               if (pos >= s.Length || s [pos++] != ')')
+                                       throw new FormatException ("Input string was not in the correct " +
+                                                                  "format.");
+                               if (AllowTrailingWhite && pos < s.Length)
+                                       pos = JumpOverWhite (pos, s, false);
+                       }
+
+                       if (pos < s.Length)
+                               throw new FormatException ("Input string was not in the correct format.");
+
+                       
+                       if (!negative)
+                               number = -number;
+
+                       return number;
                }
 
                public override string ToString ()
index 61c4e1dd43807da4d7b77d313aa80b90cae07436..962a1503689bb23d546e8d65ae3eed2b665242b9 100644 (file)
@@ -8,6 +8,7 @@
 //
 
 using System.Globalization;
+using System.Threading;
 
 namespace System {
        
@@ -113,13 +114,273 @@ namespace System {
                        return Parse (s, style, null);
                }
 
-               [MonoTODO]
+               private delegate bool IsAnything (Char c);
+
+               private static void CheckStyle (NumberStyles style)
+               {
+                       if ((style & NumberStyles.AllowHexSpecifier) != 0 &&
+                           ((style | ~NumberStyles.AllowLeadingWhite) != 0 || 
+                            (style | ~NumberStyles.AllowTrailingWhite) != 0))
+                               throw new ArgumentException (
+                                       "With AllowHexSpecifier only " + 
+                                       "AllowLeadingWhite and AllowTrailingWhite " + 
+                                       "are permitted.");
+               }
+               
+               private static int JumpOverWhite (int pos, string s, bool excp)
+               {
+                       while (pos < s.Length && Char.IsWhiteSpace (s [pos]))
+                               pos++;
+
+                       if (excp && pos >= s.Length)
+                               throw new FormatException ("Input string was not in the correct format.");
+
+                       return pos;
+               }
+
+               private static void FindSign (ref int pos, string s, NumberFormatInfo nfi, 
+                                     ref bool foundSign, ref bool negative)
+               {
+                       if ((pos + nfi.NegativeSign.Length) <= s.Length &&
+                            s.Substring (pos, nfi.NegativeSign.Length) == nfi.NegativeSign) {
+                               negative = true;
+                               foundSign = true;
+                               pos += nfi.NegativeSign.Length;
+                       } 
+                       else if ((pos + nfi.PositiveSign.Length) < s.Length &&
+                            s.Substring (pos, nfi.PositiveSign.Length) == nfi.PositiveSign) {
+                               negative = false;
+                               pos += nfi.PositiveSign.Length;
+                               foundSign = true;
+                       } 
+               }
+
+               private static void FindCurrency (ref int pos,
+                                                string s, 
+                                                NumberFormatInfo nfi,
+                                                ref bool foundCurrency)
+               {
+                       if ((pos + nfi.CurrencySymbol.Length) <= s.Length &&
+                            s.Substring (pos, nfi.CurrencySymbol.Length) == nfi.CurrencySymbol) {
+                               foundCurrency = true;
+                               pos += nfi.CurrencySymbol.Length;
+                       } 
+               }
+
+               private static bool FindOther (ref int pos,
+                                             string s, 
+                                             string other)
+               {
+                       if ((pos + other.Length) <= s.Length &&
+                            s.Substring (pos, other.Length) == other) {
+                               pos += other.Length;
+                               return true;
+                       } 
+
+                       return false;
+               }
+
                public static long Parse (string s, NumberStyles style, IFormatProvider fp)
                {
-                       // TODO: Implement me
-                       // throw new NotImplementedException ();
-                       // good enough for now
-                       return Parse (s);
+                       if (s == null)
+                               throw new ArgumentNullException ();
+
+                       if (s.Length == 0)
+                               throw new FormatException ("Input string was not " + 
+                                                          "in the correct format.");
+
+                       NumberFormatInfo nfi;
+                       if (fp != null) {
+                               Type typeNFI = Type.GetType ("System.Globalization.NumberFormatInfo");
+                               nfi = (NumberFormatInfo) fp.GetFormat (typeNFI);
+                       }
+                       else
+                               nfi = Thread.CurrentThread.CurrentCulture.NumberFormat;
+
+                       CheckStyle (style);
+
+                       bool AllowCurrencySymbol = (style & NumberStyles.AllowCurrencySymbol) != 0;
+                       bool AllowExponent = (style & NumberStyles.AllowExponent) != 0;
+                       bool AllowHexSpecifier = (style & NumberStyles.AllowHexSpecifier) != 0;
+                       bool AllowThousands = (style & NumberStyles.AllowThousands) != 0;
+                       bool AllowDecimalPoint = (style & NumberStyles.AllowDecimalPoint) != 0;
+                       bool AllowParentheses = (style & NumberStyles.AllowParentheses) != 0;
+                       bool AllowTrailingSign = (style & NumberStyles.AllowTrailingSign) != 0;
+                       bool AllowLeadingSign = (style & NumberStyles.AllowLeadingSign) != 0;
+                       bool AllowTrailingWhite = (style & NumberStyles.AllowTrailingWhite) != 0;
+                       bool AllowLeadingWhite = (style & NumberStyles.AllowLeadingWhite) != 0;
+
+                       int pos = 0;
+
+                       if (AllowLeadingWhite)
+                               pos = JumpOverWhite (pos, s, true);
+
+                       bool foundOpenParentheses = false;
+                       bool negative = false;
+                       bool foundSign = false;
+                       bool foundCurrency = false;
+
+                       // Pre-number stuff
+                       if (AllowParentheses && s [pos] == '(') {
+                               foundOpenParentheses = true;
+                               foundSign = true;
+                               negative = true; // MS always make the number negative when there parentheses
+                                                // even when NumberFormatInfo.NumberNegativePattern != 0!!!
+                               pos++;
+                               if (AllowLeadingWhite)
+                                       pos = JumpOverWhite (pos, s, true);
+
+                               if (s.Substring (pos, nfi.NegativeSign.Length) == nfi.NegativeSign)
+                                       throw new FormatException ("Input string was not in the correct " +
+                                                                  "format.");
+                               if (s.Substring (pos, nfi.PositiveSign.Length) == nfi.PositiveSign)
+                                       throw new FormatException ("Input string was not in the correct " +
+                                                                  "format.");
+                       }
+
+                       if (AllowLeadingSign && !foundSign) {
+                               // Sign + Currency
+                               FindSign (ref pos, s, nfi, ref foundSign, ref negative);
+                               if (foundSign) {
+                                       if (AllowLeadingWhite)
+                                               pos = JumpOverWhite (pos, s, true);
+                                       if (AllowCurrencySymbol) {
+                                               FindCurrency (ref pos, s, nfi,
+                                                             ref foundCurrency);
+                                               if (foundCurrency && AllowLeadingWhite)
+                                                       pos = JumpOverWhite (pos, s, true);
+                                       }
+                               }
+                       }
+                       
+                       if (AllowCurrencySymbol && !foundCurrency) {
+                               // Currency + sign
+                               FindCurrency (ref pos, s, nfi, ref foundCurrency);
+                               if (foundCurrency) {
+                                       if (AllowLeadingWhite)
+                                               pos = JumpOverWhite (pos, s, true);
+                                       if (foundCurrency) {
+                                               if (!foundSign && AllowLeadingSign) {
+                                                       FindSign (ref pos, s, nfi, ref foundSign,
+                                                                 ref negative);
+                                                       if (foundSign && AllowLeadingWhite)
+                                                               pos = JumpOverWhite (pos, s, true);
+                                               }
+                                       }
+                               }
+                       }
+                       
+                       IsAnything validDigit;
+                       if (AllowHexSpecifier)
+                               validDigit = new IsAnything (Char.IsNumber);
+                       else
+                               validDigit = new IsAnything (Char.IsDigit);
+                       
+                       long number = 0;
+                       int nDigits = 0;
+                       bool decimalPointFound = false;
+                       int digitValue;
+                       char hexDigit;
+                               
+                       // Number stuff
+                       do {
+
+                               if (!validDigit (s [pos])) {
+                                       if (AllowThousands &&
+                                           FindOther (ref pos, s, nfi.NumberGroupSeparator))
+                                           continue;
+                                       else
+                                       if (!decimalPointFound && AllowDecimalPoint &&
+                                           FindOther (ref pos, s, nfi.NumberDecimalSeparator)) {
+                                           decimalPointFound = true;
+                                           continue;
+                                       }
+
+                                       break;
+                               }
+                               else if (AllowHexSpecifier) {
+                                       hexDigit = s [pos++];
+                                       if (Char.IsDigit (hexDigit))
+                                               digitValue = (int) (hexDigit - '0');
+                                       else if (Char.IsLower (hexDigit))
+                                               digitValue = (int) (hexDigit - 'a');
+                                       else
+                                               digitValue = (int) (hexDigit - 'A');
+
+                                       number = checked (number * 16 - digitValue);
+                               }
+                               else if (decimalPointFound) {
+                                       nDigits++;
+                                       // Allows decimal point as long as it's only 
+                                       // followed by zeroes.
+                                       if (s [pos++] != '0')
+                                               throw new FormatException ("Input string was not in the " + 
+                                                                          "correct format.");
+                               }
+                               else {
+                                       nDigits++;
+
+                                       try {
+                                               // Calculations done as negative
+                                               // (abs (MinValue) > abs (MaxValue))
+                                               number = checked (
+                                                       number * 10 - 
+                                                       (long) (s [pos++] - '0')
+                                                       );
+                                       } catch (OverflowException) {
+                                               throw new OverflowException ("Value too large or too " +
+                                                                            "small.");
+                                       }
+                               }
+                       } while (pos < s.Length);
+
+                       // Post number stuff
+                       if (nDigits == 0)
+                               throw new FormatException ("Input string was not in the correct format.");
+
+                       if (AllowTrailingSign && !foundSign) {
+                               // Sign + Currency
+                               FindSign (ref pos, s, nfi, ref foundSign, ref negative);
+                               if (foundSign) {
+                                       if (AllowTrailingWhite)
+                                               pos = JumpOverWhite (pos, s, true);
+                                       if (AllowCurrencySymbol)
+                                               FindCurrency (ref pos, s, nfi,
+                                                             ref foundCurrency);
+                               }
+                       }
+                       
+                       if (AllowCurrencySymbol && !foundCurrency) {
+                               // Currency + sign
+                               FindCurrency (ref pos, s, nfi, ref foundCurrency);
+                               if (foundCurrency) {
+                                       if (AllowTrailingWhite)
+                                               pos = JumpOverWhite (pos, s, true);
+                                       if (!foundSign && AllowTrailingSign)
+                                               FindSign (ref pos, s, nfi, ref foundSign,
+                                                         ref negative);
+                               }
+                       }
+                       
+                       if (AllowTrailingWhite && pos < s.Length)
+                               pos = JumpOverWhite (pos, s, false);
+
+                       if (foundOpenParentheses) {
+                               if (pos >= s.Length || s [pos++] != ')')
+                                       throw new FormatException ("Input string was not in the correct " +
+                                                                  "format.");
+                               if (AllowTrailingWhite && pos < s.Length)
+                                       pos = JumpOverWhite (pos, s, false);
+                       }
+
+                       if (pos < s.Length)
+                               throw new FormatException ("Input string was not in the correct format.");
+
+                       
+                       if (!negative)
+                               number = -number;
+
+                       return number;
                }
 
                public override string ToString ()
index 51b8202e5a6e99b59d3d53bada6ec1851c521cd8..48c89062317c670c06b0b44f70de2f1b77fe1e55 100644 (file)
@@ -119,11 +119,13 @@ namespace System {
                        return Parse (s, style, null);
                }
 
-               [MonoTODO]
                public static sbyte Parse (string s, NumberStyles style, IFormatProvider fp)
                {
-                       // TODO: Implement me
-                       throw new NotImplementedException ();
+                       int tmpResult = Int32.Parse (s, style, fp);
+                       if (tmpResult > SByte.MaxValue || tmpResult < SByte.MinValue)
+                               throw new OverflowException ("Value too large or too small.");
+
+                       return (sbyte) tmpResult;
                }
 
                public override string ToString ()