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 ()
//
using System.Globalization;
+using System.Threading;
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 ()
//
using System.Globalization;
+using System.Threading;
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 ()
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 ()