5 // Miguel de Icaza (miguel@ximian.com)
7 // (C) Ximian, Inc. http://www.ximian.com
8 // Copyright (C) 2004 Novell (http://www.novell.com)
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System.Globalization;
31 using System.Threading;
36 [CLSCompliant (false)]
38 [System.Runtime.InteropServices.ComVisible (true)]
40 public struct UInt32 : IFormattable, IConvertible, IComparable
42 , IComparable<UInt32>, IEquatable <UInt32>
45 public const uint MaxValue = 0xffffffff;
46 public const uint MinValue = 0;
48 internal uint m_value;
50 public int CompareTo (object value)
55 if (!(value is System.UInt32))
56 throw new ArgumentException (Locale.GetText ("Value is not a System.UInt32."));
58 if (this.m_value == (uint) value)
61 if (this.m_value < (uint) value)
67 public override bool Equals (object obj)
69 if (!(obj is System.UInt32))
72 return ((uint) obj) == m_value;
75 public override int GetHashCode ()
81 public int CompareTo (uint value)
91 public bool Equals (uint value)
93 return value == m_value;
97 internal static bool Parse (string s, bool tryParse, out uint result, out Exception exc)
102 bool digits_seen = false;
103 bool has_negative_sign = false;
110 exc = new ArgumentNullException ("s");
117 for (i = 0; i < len; i++) {
119 if (!Char.IsWhiteSpace (c))
125 exc = Int32.GetFormatException ();
134 has_negative_sign = true;
137 for (; i < len; i++) {
140 if (c >= '0' && c <= '9') {
141 uint d = (uint) (c - '0');
143 if ((val > MaxValue/10) || (val == (MaxValue / 10) && d > (MaxValue % 10))){
145 exc = new OverflowException (Locale.GetText ("Value is too large"));
148 val = (val * 10) + d;
150 } else if (!Int32.ProcessTrailingWhitespace (tryParse, s, i, ref exc)){
156 exc = Int32.GetFormatException ();
160 // -0 is legal but other negative values are not
161 if (has_negative_sign && (val > 0)) {
163 exc = new OverflowException (
164 Locale.GetText ("Negative number"));
172 internal static bool Parse (string s, NumberStyles style, IFormatProvider provider, bool tryParse, out uint result, out Exception exc)
179 exc = new ArgumentNullException ("s");
185 exc = Int32.GetFormatException ();
189 NumberFormatInfo nfi;
190 if (provider != null) {
191 Type typeNFI = typeof (NumberFormatInfo);
192 nfi = (NumberFormatInfo) provider.GetFormat (typeNFI);
195 nfi = Thread.CurrentThread.CurrentCulture.NumberFormat;
197 if (!Int32.CheckStyle (style, tryParse, ref exc))
200 bool AllowCurrencySymbol = (style & NumberStyles.AllowCurrencySymbol) != 0;
201 bool AllowHexSpecifier = (style & NumberStyles.AllowHexSpecifier) != 0;
202 bool AllowThousands = (style & NumberStyles.AllowThousands) != 0;
203 bool AllowDecimalPoint = (style & NumberStyles.AllowDecimalPoint) != 0;
204 bool AllowParentheses = (style & NumberStyles.AllowParentheses) != 0;
205 bool AllowTrailingSign = (style & NumberStyles.AllowTrailingSign) != 0;
206 bool AllowLeadingSign = (style & NumberStyles.AllowLeadingSign) != 0;
207 bool AllowTrailingWhite = (style & NumberStyles.AllowTrailingWhite) != 0;
208 bool AllowLeadingWhite = (style & NumberStyles.AllowLeadingWhite) != 0;
212 if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
215 bool foundOpenParentheses = false;
216 bool negative = false;
217 bool foundSign = false;
218 bool foundCurrency = false;
221 if (AllowParentheses && s [pos] == '(') {
222 foundOpenParentheses = true;
224 negative = true; // MS always make the number negative when there parentheses
225 // even when NumberFormatInfo.NumberNegativePattern != 0!!!
227 if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
230 if (s.Substring (pos, nfi.NegativeSign.Length) == nfi.NegativeSign) {
232 exc = Int32.GetFormatException ();
235 if (s.Substring (pos, nfi.PositiveSign.Length) == nfi.PositiveSign) {
237 exc = Int32.GetFormatException ();
242 if (AllowLeadingSign && !foundSign) {
244 Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
246 if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
248 if (AllowCurrencySymbol) {
249 Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
250 if (foundCurrency && AllowLeadingWhite &&
251 !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
257 if (AllowCurrencySymbol && !foundCurrency) {
259 Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
261 if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
264 if (!foundSign && AllowLeadingSign) {
265 Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
266 if (foundSign && AllowLeadingWhite &&
267 !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
276 bool decimalPointFound = false;
281 // Just the same as Int32, but this one adds instead of substract
284 if (!Int32.ValidDigit (s [pos], AllowHexSpecifier)) {
285 if (AllowThousands && Int32.FindOther (ref pos, s, nfi.NumberGroupSeparator))
288 if (!decimalPointFound && AllowDecimalPoint &&
289 Int32.FindOther (ref pos, s, nfi.NumberDecimalSeparator)) {
290 decimalPointFound = true;
295 else if (AllowHexSpecifier) {
297 hexDigit = s [pos++];
298 if (Char.IsDigit (hexDigit))
299 digitValue = (uint) (hexDigit - '0');
300 else if (Char.IsLower (hexDigit))
301 digitValue = (uint) (hexDigit - 'a' + 10);
303 digitValue = (uint) (hexDigit - 'A' + 10);
306 ulong l = number * 16 + digitValue;
312 number = checked (number * 16 + digitValue);
314 else if (decimalPointFound) {
316 // Allows decimal point as long as it's only
317 // followed by zeroes.
318 if (s [pos++] != '0') {
320 exc = new OverflowException (Locale.GetText ("Value too large or too small."));
328 number = checked (number * 10 + (uint) (s [pos++] - '0'));
330 catch (OverflowException) {
332 exc = new OverflowException (Locale.GetText ("Value too large or too small."));
336 } while (pos < s.Length);
341 exc = Int32.GetFormatException ();
345 if (AllowTrailingSign && !foundSign) {
347 Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
349 if (AllowTrailingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
351 if (AllowCurrencySymbol)
352 Int32. FindCurrency (ref pos, s, nfi, ref foundCurrency);
356 if (AllowCurrencySymbol && !foundCurrency) {
358 Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
360 if (AllowTrailingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
362 if (!foundSign && AllowTrailingSign)
363 Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
367 if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite (ref pos, s, false, tryParse, ref exc))
370 if (foundOpenParentheses) {
371 if (pos >= s.Length || s [pos++] != ')') {
373 exc = Int32.GetFormatException ();
376 if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite (ref pos, s, false, tryParse, ref exc))
380 if (pos < s.Length && s [pos] != '\u0000') {
382 exc = Int32.GetFormatException ();
386 // -0 is legal but other negative values are not
387 if (negative && (number > 0)) {
389 exc = new OverflowException (
390 Locale.GetText ("Negative number"));
399 [CLSCompliant (false)]
400 public static uint Parse (string s)
405 if (!Parse (s, false, out res, out exc))
411 [CLSCompliant (false)]
412 public static uint Parse (string s, NumberStyles style, IFormatProvider fp)
417 if (!Parse (s, style, fp, false, out res, out exc))
423 [CLSCompliant (false)]
424 public static uint Parse (string s, IFormatProvider provider)
426 return Parse (s, NumberStyles.Integer, provider);
429 [CLSCompliant (false)]
430 public static uint Parse (string s, NumberStyles style)
432 return Parse (s, style, null);
436 [CLSCompliant (false)]
437 public static bool TryParse (string s, out uint result)
440 if (!Parse (s, true, out result, out exc)) {
448 [CLSCompliant (false)]
449 public static bool TryParse (string s, NumberStyles style, IFormatProvider provider, out uint result)
452 if (!Parse (s, style, provider, true, out result, out exc)) {
461 public override string ToString ()
463 return NumberFormatter.FormatGeneral (new NumberFormatter.NumberStore (m_value));
466 public string ToString (IFormatProvider fp)
468 return NumberFormatter.FormatGeneral (new NumberFormatter.NumberStore (m_value), fp);
471 public string ToString (string format)
473 return ToString (format, null);
476 public string ToString (string format, IFormatProvider fp)
478 NumberFormatInfo nfi = NumberFormatInfo.GetInstance (fp);
479 return NumberFormatter.NumberToString (format, m_value, nfi);
482 // =========== IConvertible Methods =========== //
483 public TypeCode GetTypeCode ()
485 return TypeCode.UInt32;
488 bool IConvertible.ToBoolean (IFormatProvider provider)
490 return System.Convert.ToBoolean (m_value);
493 byte IConvertible.ToByte (IFormatProvider provider)
495 return System.Convert.ToByte (m_value);
498 char IConvertible.ToChar (IFormatProvider provider)
500 return System.Convert.ToChar (m_value);
503 DateTime IConvertible.ToDateTime (IFormatProvider provider)
505 return System.Convert.ToDateTime (m_value);
508 decimal IConvertible.ToDecimal (IFormatProvider provider)
510 return System.Convert.ToDecimal (m_value);
513 double IConvertible.ToDouble (IFormatProvider provider)
515 return System.Convert.ToDouble (m_value);
518 short IConvertible.ToInt16 (IFormatProvider provider)
520 return System.Convert.ToInt16 (m_value);
523 int IConvertible.ToInt32 (IFormatProvider provider)
525 return System.Convert.ToInt32 (m_value);
528 long IConvertible.ToInt64 (IFormatProvider provider)
530 return System.Convert.ToInt64 (m_value);
533 sbyte IConvertible.ToSByte (IFormatProvider provider)
535 return System.Convert.ToSByte (m_value);
538 float IConvertible.ToSingle (IFormatProvider provider)
540 return System.Convert.ToSingle (m_value);
543 object IConvertible.ToType (Type conversionType, IFormatProvider provider)
545 return System.Convert.ToType (m_value, conversionType, provider);
548 ushort IConvertible.ToUInt16 (IFormatProvider provider)
550 return System.Convert.ToUInt16 (m_value);
553 uint IConvertible.ToUInt32 (IFormatProvider provider)
558 ulong IConvertible.ToUInt64 (IFormatProvider provider)
560 return System.Convert.ToUInt64 (m_value);