NumberFormatInfo nfi = null;
if (provider != null) {
Type typeNFI = typeof (NumberFormatInfo);
- nfi = (NumberFormatInfo) provider.GetFormat (typeNFI);
+ nfi = provider.GetFormat (typeNFI) as NumberFormatInfo;
}
if (nfi == null)
nfi = Thread.CurrentThread.CurrentCulture.NumberFormat;
uint number = 0;
int nDigits = 0;
- bool decimalPointFound = false;
+ int decimalPointPos = -1;
uint digitValue;
char hexDigit;
- int exponent = 0;
// Number stuff
// Just the same as Int32, but this one adds instead of substract
- do {
+ while (pos < s.Length) {
if (!Int32.ValidDigit (s [pos], AllowHexSpecifier)) {
if (AllowThousands &&
(Int32.FindOther (ref pos, s, nfi.NumberGroupSeparator)
|| Int32.FindOther (ref pos, s, nfi.CurrencyGroupSeparator)))
continue;
- else
- if (!decimalPointFound && AllowDecimalPoint &&
+
+ if (AllowDecimalPoint && decimalPointPos < 0 &&
(Int32.FindOther (ref pos, s, nfi.NumberDecimalSeparator)
|| Int32.FindOther (ref pos, s, nfi.CurrencyDecimalSeparator))) {
- decimalPointFound = true;
+ decimalPointPos = nDigits;
continue;
}
break;
}
+
+ nDigits++;
+
if (AllowHexSpecifier) {
- nDigits++;
hexDigit = s [pos++];
if (Char.IsDigit (hexDigit))
digitValue = (uint) (hexDigit - '0');
number = (uint) l;
} else
number = checked (number * 16 + digitValue);
+
+ continue;
}
- else if (decimalPointFound) {
- nDigits++;
- // Allows decimal point as long as it's only
- // followed by zeroes.
- if (s [pos++] != '0') {
- if (!tryParse)
- exc = new OverflowException (Locale.GetText ("Value too large or too small."));
- return false;
- }
- }
- else {
- nDigits++;
- try {
- number = checked (number * 10 + (uint) (s [pos++] - '0'));
- }
- catch (OverflowException) {
- if (!tryParse)
- exc = new OverflowException (Locale.GetText ("Value too large or too small."));
- return false;
- }
+ try {
+ number = checked (number * 10 + (uint) (s [pos++] - '0'));
+ } catch (OverflowException) {
+ if (!tryParse)
+ exc = new OverflowException (Locale.GetText ("Value too large or too small."));
+ return false;
}
- } while (pos < s.Length);
+ }
// Post number stuff
if (nDigits == 0) {
return false;
}
+ int exponent = 0;
if (AllowExponent)
if (Int32.FindExponent (ref pos, s, ref exponent, tryParse, ref exc) && exc != null)
return false;
return false;
}
- // result *= 10^exponent
- if (exponent > 0) {
+ if (decimalPointPos >= 0)
+ exponent = exponent - nDigits + decimalPointPos;
+
+ if (exponent < 0) {
+ //
+ // Any non-zero values after decimal point are not allowed
+ //
+ long remainder;
+ number = (uint) Math.DivRem (number, (int) Math.Pow (10, -exponent), out remainder);
+ if (remainder != 0) {
+ if (!tryParse)
+ exc = new OverflowException ("Value too large or too small.");
+ return false;
+ }
+ } else if (exponent > 0) {
+ //
+ // result *= 10^exponent
+ //
// Reduce the risk of throwing an overflow exc
+ //
double res = checked (Math.Pow (10, exponent) * number);
- if (res < Int32.MinValue || res > Int32.MaxValue) {
+ if (res < MinValue || res > MaxValue) {
if (!tryParse)
exc = new OverflowException ("Value too large or too small.");
return false;
}
- number = (uint) res;
+ number = (uint)res;
}
result = number;
-
return true;
}