//
// System.UInt32.cs
//
-// Author:
+// Authors:
// Miguel de Icaza (miguel@ximian.com)
+// Marek Safar (marek.safar@gmail.com)
//
// (C) Ximian, Inc. http://www.ximian.com
// Copyright (C) 2004 Novell (http://www.novell.com)
+// Copyright (C) 2012 Xamarin Inc (http://www.xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
{
[Serializable]
[CLSCompliant (false)]
-#if NET_2_0
[System.Runtime.InteropServices.ComVisible (true)]
-#endif
- public struct UInt32 : IFormattable, IConvertible, IComparable
-#if NET_2_0
- , IComparable<UInt32>, IEquatable <UInt32>
-#endif
+ public struct UInt32 : IFormattable, IConvertible, IComparable, IComparable<UInt32>, IEquatable <UInt32>
{
public const uint MaxValue = 0xffffffff;
public const uint MinValue = 0;
if (!(value is System.UInt32))
throw new ArgumentException (Locale.GetText ("Value is not a System.UInt32."));
- if (this.m_value == (uint) value)
- return 0;
+ uint val = (uint) value;
- if (this.m_value < (uint) value)
- return -1;
+ if (m_value == val)
+ return 0;
- return 1;
+ return (m_value < val) ? -1 : 1;
}
public override bool Equals (object obj)
return (int) m_value;
}
-#if NET_2_0
public int CompareTo (uint value)
{
if (m_value == value)
return -1;
}
- public bool Equals (uint value)
+ public bool Equals (uint obj)
{
- return value == m_value;
+ return obj == m_value;
}
-#endif
internal static bool Parse (string s, bool tryParse, out uint result, out Exception exc)
{
if (c >= '0' && c <= '9') {
uint d = (uint) (c - '0');
- val = checked (val * 10 + d);
- digits_seen = true;
- }
- else {
- if (Char.IsWhiteSpace (c)) {
- for (i++; i < len; i++) {
- if (!Char.IsWhiteSpace (s [i])) {
- if (!tryParse)
- exc = Int32.GetFormatException ();
- return false;
- }
- }
- break;
- } else {
+ if ((val > MaxValue/10) || (val == (MaxValue / 10) && d > (MaxValue % 10))){
if (!tryParse)
- exc = Int32.GetFormatException ();
+ exc = new OverflowException (Locale.GetText ("Value is too large"));
return false;
}
+ val = (val * 10) + d;
+ digits_seen = true;
+ } else if (!Int32.ProcessTrailingWhitespace (tryParse, s, i, ref exc)){
+ return false;
}
}
if (!digits_seen) {
return false;
}
- NumberFormatInfo nfi;
+ NumberFormatInfo nfi = null;
if (provider != null) {
Type typeNFI = typeof (NumberFormatInfo);
nfi = (NumberFormatInfo) provider.GetFormat (typeNFI);
}
- else
+ if (nfi == null)
nfi = Thread.CurrentThread.CurrentCulture.NumberFormat;
if (!Int32.CheckStyle (style, tryParse, ref exc))
bool AllowLeadingSign = (style & NumberStyles.AllowLeadingSign) != 0;
bool AllowTrailingWhite = (style & NumberStyles.AllowTrailingWhite) != 0;
bool AllowLeadingWhite = (style & NumberStyles.AllowLeadingWhite) != 0;
+ bool AllowExponent = (style & NumberStyles.AllowExponent) != 0;
int pos = 0;
exc = Int32.GetFormatException ();
return false;
}
+
if (s.Substring (pos, nfi.PositiveSign.Length) == nfi.PositiveSign) {
if (!tryParse)
exc = Int32.GetFormatException ();
if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
return false;
if (AllowCurrencySymbol) {
- Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
+ Int32.FindCurrency (ref pos, s, nfi,
+ ref foundCurrency);
if (foundCurrency && AllowLeadingWhite &&
!Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
return false;
return false;
if (foundCurrency) {
if (!foundSign && AllowLeadingSign) {
- Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
+ Int32.FindSign (ref pos, s, nfi, ref foundSign,
+ ref negative);
if (foundSign && AllowLeadingWhite &&
!Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
return false;
uint number = 0;
int nDigits = 0;
- bool decimalPointFound = false;
+ int decimalPointPos = -1;
uint digitValue;
char hexDigit;
do {
if (!Int32.ValidDigit (s [pos], AllowHexSpecifier)) {
- if (AllowThousands && Int32.FindOther (ref pos, s, nfi.NumberGroupSeparator))
+ if (AllowThousands &&
+ (Int32.FindOther (ref pos, s, nfi.NumberGroupSeparator)
+ || Int32.FindOther (ref pos, s, nfi.CurrencyGroupSeparator)))
continue;
- else
- if (!decimalPointFound && AllowDecimalPoint &&
- Int32.FindOther (ref pos, s, nfi.NumberDecimalSeparator)) {
- decimalPointFound = true;
+
+ if (AllowDecimalPoint && decimalPointPos < 0 &&
+ (Int32.FindOther (ref pos, s, nfi.NumberDecimalSeparator)
+ || Int32.FindOther (ref pos, s, nfi.CurrencyDecimalSeparator))) {
+ decimalPointPos = nDigits;
continue;
}
+
break;
}
- else if (AllowHexSpecifier) {
- nDigits++;
+
+ nDigits++;
+
+ if (AllowHexSpecifier) {
hexDigit = s [pos++];
if (Char.IsDigit (hexDigit))
digitValue = (uint) (hexDigit - '0');
else
digitValue = (uint) (hexDigit - 'A' + 10);
- 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') {
- if (!tryParse)
- exc = new OverflowException (Locale.GetText ("Value too large or too small."));
- return false;
- }
+ if (tryParse){
+ ulong l = number * 16 + digitValue;
+
+ if (l > MaxValue)
+ return false;
+ number = (uint) l;
+ } else
+ number = checked (number * 16 + digitValue);
+
+ continue;
}
- 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);
return false;
}
+ int exponent = 0;
+ if (AllowExponent)
+ if (Int32.FindExponent (ref pos, s, ref exponent, tryParse, ref exc) && exc != null)
+ return false;
+
if (AllowTrailingSign && !foundSign) {
// Sign + Currency
Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
- if (foundSign) {
+ if (foundSign && pos < s.Length) {
if (AllowTrailingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
return false;
- if (AllowCurrencySymbol)
- Int32. FindCurrency (ref pos, s, nfi, ref foundCurrency);
}
}
if (AllowCurrencySymbol && !foundCurrency) {
+ if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite (ref pos, s, false, tryParse, ref exc))
+ return false;
+
// Currency + sign
Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
- if (foundCurrency) {
+ if (foundCurrency && pos < s.Length) {
if (AllowTrailingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
return false;
if (!foundSign && AllowTrailingSign)
- Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
+ Int32.FindSign (ref pos, s, nfi, ref foundSign,
+ ref negative);
}
}
return false;
}
- result = number;
+ 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 < MinValue || res > MaxValue) {
+ if (!tryParse)
+ exc = new OverflowException ("Value too large or too small.");
+ return false;
+ }
+ number = (uint)res;
+ }
+
+ result = number;
return true;
}
}
[CLSCompliant (false)]
- public static uint Parse (string s, NumberStyles style, IFormatProvider fp)
+ public static uint Parse (string s, NumberStyles style, IFormatProvider provider)
{
Exception exc;
uint res;
- if (!Parse (s, style, fp, false, out res, out exc))
+ if (!Parse (s, style, provider, false, out res, out exc))
throw exc;
return res;
return Parse (s, style, null);
}
-#if NET_2_0
[CLSCompliant (false)]
public static bool TryParse (string s, out uint result)
{
return true;
}
-#endif
public override string ToString ()
{
- return NumberFormatter.FormatGeneral (new NumberFormatter.NumberStore (m_value));
+ return NumberFormatter.NumberToString (m_value, null);
}
- public string ToString (IFormatProvider fp)
+ public string ToString (IFormatProvider provider)
{
- return NumberFormatter.FormatGeneral (new NumberFormatter.NumberStore (m_value), fp);
+ return NumberFormatter.NumberToString (m_value, provider);
}
public string ToString (string format)
return ToString (format, null);
}
- public string ToString (string format, IFormatProvider fp)
+ public string ToString (string format, IFormatProvider provider)
{
- NumberFormatInfo nfi = NumberFormatInfo.GetInstance (fp);
- return NumberFormatter.NumberToString (format, m_value, nfi);
+ return NumberFormatter.NumberToString (format, m_value, provider);
}
// =========== IConvertible Methods =========== //
return System.Convert.ToSingle (m_value);
}
- object IConvertible.ToType (Type conversionType, IFormatProvider provider)
+ object IConvertible.ToType (Type targetType, IFormatProvider provider)
{
- return System.Convert.ToType (m_value, conversionType, provider);
+ if (targetType == null)
+ throw new ArgumentNullException ("targetType");
+ return System.Convert.ToType (m_value, targetType, provider, false);
}
ushort IConvertible.ToUInt16 (IFormatProvider provider)