Add [Category ("NotWorking")] to failing test.
[mono.git] / mcs / class / corlib / System / UInt32.cs
1 //
2 // System.UInt32.cs
3 //
4 // Authors:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //   Marek Safar (marek.safar@gmail.com)
7 //
8 // (C) Ximian, Inc.  http://www.ximian.com
9 // Copyright (C) 2004 Novell (http://www.novell.com)
10 // Copyright (C) 2012 Xamarin Inc (http://www.xamarin.com)
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using System.Globalization;
33 using System.Threading;
34
35 namespace System
36 {
37         [Serializable]
38         [CLSCompliant (false)]
39         [System.Runtime.InteropServices.ComVisible (true)]
40         public struct UInt32 : IFormattable, IConvertible, IComparable, IComparable<UInt32>, IEquatable <UInt32>
41         {
42                 public const uint MaxValue = 0xffffffff;
43                 public const uint MinValue = 0;
44
45                 internal uint m_value;
46
47                 public int CompareTo (object value)
48                 {
49                         if (value == null)
50                                 return 1;
51
52                         if (!(value is System.UInt32))
53                                 throw new ArgumentException (Locale.GetText ("Value is not a System.UInt32."));
54
55                         uint val = (uint) value;
56
57                         if (m_value == val)
58                                 return 0;
59
60                         return (m_value < val) ? -1 : 1;
61                 }
62
63                 public override bool Equals (object obj)
64                 {
65                         if (!(obj is System.UInt32))
66                                 return false;
67
68                         return ((uint) obj) == m_value;
69                 }
70
71                 public override int GetHashCode ()
72                 {
73                         return (int) m_value;
74                 }
75
76                 public int CompareTo (uint value)
77                 {
78                         if (m_value == value)
79                                 return 0;
80                         if (m_value > value)
81                                 return 1;
82                         else
83                                 return -1;
84                 }
85
86                 public bool Equals (uint obj)
87                 {
88                         return obj == m_value;
89                 }
90
91                 internal static bool Parse (string s, bool tryParse, out uint result, out Exception exc)
92                 {
93                         uint val = 0;
94                         int len;
95                         int i;
96                         bool digits_seen = false;
97                         bool has_negative_sign = false;
98
99                         result = 0;
100                         exc = null;
101
102                         if (s == null) {
103                                 if (!tryParse)
104                                         exc = new ArgumentNullException ("s");
105                                 return false;
106                         }
107
108                         len = s.Length;
109
110                         char c;
111                         for (i = 0; i < len; i++) {
112                                 c = s [i];
113                                 if (!Char.IsWhiteSpace (c))
114                                         break;
115                         }
116
117                         if (i == len) {
118                                 if (!tryParse)
119                                         exc = Int32.GetFormatException ();
120                                 return false;
121                         }
122
123                         if (s [i] == '+')
124                                 i++;
125                         else
126                                 if (s[i] == '-') {
127                                         i++;
128                                         has_negative_sign = true;
129                                 }
130
131                         for (; i < len; i++) {
132                                 c = s [i];
133
134                                 if (c >= '0' && c <= '9') {
135                                         uint d = (uint) (c - '0');
136
137                                         if ((val > MaxValue/10) || (val == (MaxValue / 10) && d > (MaxValue % 10))){
138                                                 if (!tryParse)
139                                                         exc = new OverflowException (Locale.GetText ("Value is too large"));
140                                                 return false;
141                                         }
142                                         val = (val * 10) + d;
143                                         digits_seen = true;
144                                 } else if (!Int32.ProcessTrailingWhitespace (tryParse, s, i, ref exc)){
145                                         return false;
146                                 }
147                         }
148                         if (!digits_seen) {
149                                 if (!tryParse)
150                                         exc = Int32.GetFormatException ();
151                                 return false;
152                         }
153
154                         // -0 is legal but other negative values are not
155                         if (has_negative_sign && (val > 0)) {
156                                 if (!tryParse)
157                                         exc = new OverflowException (
158                                             Locale.GetText ("Negative number"));
159                                 return false;
160                         }
161
162                         result = val;
163                         return true;
164                 }
165
166                 internal static bool Parse (string s, NumberStyles style, IFormatProvider provider, bool tryParse, out uint result, out Exception exc)
167                 {
168                         result = 0;
169                         exc = null;
170
171                         if (s == null) {
172                                 if (!tryParse)
173                                         exc = new ArgumentNullException ("s");
174                                 return false;
175                         }
176
177                         if (s.Length == 0) {
178                                 if (!tryParse)
179                                         exc = Int32.GetFormatException ();
180                                 return false;
181                         }
182
183                         NumberFormatInfo nfi = null;
184                         if (provider != null) {
185                                 Type typeNFI = typeof (NumberFormatInfo);
186                                 nfi = (NumberFormatInfo) provider.GetFormat (typeNFI);
187                         }
188                         if (nfi == null)
189                                 nfi = Thread.CurrentThread.CurrentCulture.NumberFormat;
190
191                         if (!Int32.CheckStyle (style, tryParse, ref exc))
192                                 return false;
193
194                         bool AllowCurrencySymbol = (style & NumberStyles.AllowCurrencySymbol) != 0;
195                         bool AllowHexSpecifier = (style & NumberStyles.AllowHexSpecifier) != 0;
196                         bool AllowThousands = (style & NumberStyles.AllowThousands) != 0;
197                         bool AllowDecimalPoint = (style & NumberStyles.AllowDecimalPoint) != 0;
198                         bool AllowParentheses = (style & NumberStyles.AllowParentheses) != 0;
199                         bool AllowTrailingSign = (style & NumberStyles.AllowTrailingSign) != 0;
200                         bool AllowLeadingSign = (style & NumberStyles.AllowLeadingSign) != 0;
201                         bool AllowTrailingWhite = (style & NumberStyles.AllowTrailingWhite) != 0;
202                         bool AllowLeadingWhite = (style & NumberStyles.AllowLeadingWhite) != 0;
203                         bool AllowExponent = (style & NumberStyles.AllowExponent) != 0;
204
205                         int pos = 0;
206
207                         if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
208                                 return false;
209
210                         bool foundOpenParentheses = false;
211                         bool negative = false;
212                         bool foundSign = false;
213                         bool foundCurrency = false;
214
215                         // Pre-number stuff
216                         if (AllowParentheses && s [pos] == '(') {
217                                 foundOpenParentheses = true;
218                                 foundSign = true;
219                                 negative = true; // MS always make the number negative when there parentheses
220                                                  // even when NumberFormatInfo.NumberNegativePattern != 0!!!
221                                 pos++;
222                                 if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
223                                         return false;
224
225                                 if (s.Substring (pos, nfi.NegativeSign.Length) == nfi.NegativeSign) {
226                                         if (!tryParse)
227                                                 exc = Int32.GetFormatException ();
228                                         return false;
229                                 }
230                                 
231                                 if (s.Substring (pos, nfi.PositiveSign.Length) == nfi.PositiveSign) {
232                                         if (!tryParse)
233                                                 exc = Int32.GetFormatException ();
234                                         return false;
235                                 }
236                         }
237
238                         if (AllowLeadingSign && !foundSign) {
239                                 // Sign + Currency
240                                 Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
241                                 if (foundSign) {
242                                         if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
243                                                 return false;
244                                         if (AllowCurrencySymbol) {
245                                                 Int32.FindCurrency (ref pos, s, nfi,
246                                                                     ref foundCurrency);
247                                                 if (foundCurrency && AllowLeadingWhite &&
248                                                                 !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
249                                                         return false;
250                                         }
251                                 }
252                         }
253
254                         if (AllowCurrencySymbol && !foundCurrency) {
255                                 // Currency + sign
256                                 Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
257                                 if (foundCurrency) {
258                                         if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
259                                                 return false;
260                                         if (foundCurrency) {
261                                                 if (!foundSign && AllowLeadingSign) {
262                                                         Int32.FindSign (ref pos, s, nfi, ref foundSign,
263                                                                         ref negative);
264                                                         if (foundSign && AllowLeadingWhite &&
265                                                                         !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
266                                                                 return false;
267                                                 }
268                                         }
269                                 }
270                         }
271
272                         uint number = 0;
273                         int nDigits = 0;
274                         int decimalPointPos = -1;
275                         uint digitValue;
276                         char hexDigit;
277
278                         // Number stuff
279                         // Just the same as Int32, but this one adds instead of substract
280                         while (pos < s.Length) {
281
282                                 if (!Int32.ValidDigit (s [pos], AllowHexSpecifier)) {
283                                         if (AllowThousands &&
284                                             (Int32.FindOther (ref pos, s, nfi.NumberGroupSeparator)
285                                                 || Int32.FindOther (ref pos, s, nfi.CurrencyGroupSeparator)))
286                                                 continue;
287                                         
288                                         if (AllowDecimalPoint && decimalPointPos < 0 &&
289                                             (Int32.FindOther (ref pos, s, nfi.NumberDecimalSeparator)
290                                                 || Int32.FindOther (ref pos, s, nfi.CurrencyDecimalSeparator))) {
291                                                         decimalPointPos = nDigits;
292                                                         continue;
293                                                 }
294
295                                         break;
296                                 }
297
298                                 nDigits++;
299
300                                 if (AllowHexSpecifier) {
301                                         hexDigit = s [pos++];
302                                         if (Char.IsDigit (hexDigit))
303                                                 digitValue = (uint) (hexDigit - '0');
304                                         else if (Char.IsLower (hexDigit))
305                                                 digitValue = (uint) (hexDigit - 'a' + 10);
306                                         else
307                                                 digitValue = (uint) (hexDigit - 'A' + 10);
308
309                                         if (tryParse){
310                                                 ulong l = number * 16 + digitValue;
311
312                                                 if (l > MaxValue)
313                                                         return false;
314                                                 number = (uint) l;
315                                         } else
316                                                 number = checked (number * 16 + digitValue);
317
318                                         continue;
319                                 }
320
321                                 try {
322                                         number = checked (number * 10 + (uint) (s [pos++] - '0'));
323                                 } catch (OverflowException) {
324                                         if (!tryParse)
325                                                 exc = new OverflowException (Locale.GetText ("Value too large or too small."));
326                                         return false;
327                                 }
328                         }
329
330                         // Post number stuff
331                         if (nDigits == 0) {
332                                 if (!tryParse)
333                                         exc = Int32.GetFormatException ();
334                                 return false;
335                         }
336
337                         int exponent = 0;
338                         if (AllowExponent)
339                                 if (Int32.FindExponent (ref pos, s, ref exponent, tryParse, ref exc) && exc != null)
340                                         return false;
341
342                         if (AllowTrailingSign && !foundSign) {
343                                 // Sign + Currency
344                                 Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
345                                 if (foundSign && pos < s.Length) {
346                                         if (AllowTrailingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
347                                                 return false;
348                                 }
349                         }
350
351                         if (AllowCurrencySymbol && !foundCurrency) {
352                                 if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite (ref pos, s, false, tryParse, ref exc))
353                                         return false;
354                                 
355                                 // Currency + sign
356                                 Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
357                                 if (foundCurrency && pos < s.Length) {
358                                         if (AllowTrailingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
359                                                 return false;
360                                         if (!foundSign && AllowTrailingSign)
361                                                 Int32.FindSign (ref pos, s, nfi, ref foundSign,
362                                                                 ref negative);
363                                 }
364                         }
365
366                         if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite (ref pos, s, false, tryParse, ref exc))
367                                 return false;
368
369                         if (foundOpenParentheses) {
370                                 if (pos >= s.Length || s [pos++] != ')') {
371                                         if (!tryParse)
372                                                 exc = Int32.GetFormatException ();
373                                         return false;
374                                 }
375                                 if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite (ref pos, s, false, tryParse, ref exc))
376                                         return false;
377                         }
378
379                         if (pos < s.Length && s [pos] != '\u0000') {
380                                 if (!tryParse)
381                                         exc = Int32.GetFormatException ();
382                                 return false;
383                         }
384
385                         // -0 is legal but other negative values are not
386                         if (negative && (number > 0)) {
387                                 if (!tryParse)
388                                         exc = new OverflowException (
389                                             Locale.GetText ("Negative number"));
390                                 return false;
391                         }
392
393                         if (decimalPointPos >= 0)
394                                 exponent = exponent - nDigits + decimalPointPos;
395                         
396                         if (exponent < 0) {
397                                 //
398                                 // Any non-zero values after decimal point are not allowed
399                                 //
400                                 long remainder;
401                                 number = (uint) Math.DivRem (number, (int) Math.Pow (10, -exponent), out remainder);
402                                 if (remainder != 0) {
403                                         if (!tryParse)
404                                                 exc = new OverflowException ("Value too large or too small.");
405                                         return false;
406                                 }
407                         } else if (exponent > 0) {
408                                 //
409                                 // result *= 10^exponent
410                                 //
411                                 // Reduce the risk of throwing an overflow exc
412                                 //
413                                 double res = checked (Math.Pow (10, exponent) * number);
414                                 if (res < MinValue || res > MaxValue) {
415                                         if (!tryParse)
416                                                 exc = new OverflowException ("Value too large or too small.");
417                                         return false;
418                                 }
419
420                                 number = (uint)res;
421                         }
422
423                         result = number;
424                         return true;
425                 }
426
427                 [CLSCompliant (false)]
428                 public static uint Parse (string s) 
429                 {
430                         Exception exc;
431                         uint res;
432
433                         if (!Parse (s, false, out res, out exc))
434                                 throw exc;
435
436                         return res;
437                 }
438
439                 [CLSCompliant (false)]
440                 public static uint Parse (string s, NumberStyles style, IFormatProvider provider) 
441                 {
442                         Exception exc;
443                         uint res;
444
445                         if (!Parse (s, style, provider, false, out res, out exc))
446                                 throw exc;
447
448                         return res;
449                 }
450
451                 [CLSCompliant (false)]
452                 public static uint Parse (string s, IFormatProvider provider)
453                 {
454                         return Parse (s, NumberStyles.Integer, provider);
455                 }
456
457                 [CLSCompliant (false)]
458                 public static uint Parse (string s, NumberStyles style)
459                 {
460                         return Parse (s, style, null);
461                 }
462
463                 [CLSCompliant (false)]
464                 public static bool TryParse (string s, out uint result) 
465                 {
466                         Exception exc;
467                         if (!Parse (s, true, out result, out exc)) {
468                                 result = 0;
469                                 return false;
470                         }
471
472                         return true;
473                 }
474
475                 [CLSCompliant (false)]
476                 public static bool TryParse (string s, NumberStyles style, IFormatProvider provider, out uint result) 
477                 {
478                         Exception exc;
479                         if (!Parse (s, style, provider, true, out result, out exc)) {
480                                 result = 0;
481                                 return false;
482                         }
483
484                         return true;
485                 }
486
487                 public override string ToString ()
488                 {
489                         return NumberFormatter.NumberToString (m_value, null);
490                 }
491
492                 public string ToString (IFormatProvider provider)
493                 {
494                         return NumberFormatter.NumberToString (m_value, provider);
495                 }
496
497                 public string ToString (string format)
498                 {
499                         return ToString (format, null);
500                 }
501
502                 public string ToString (string format, IFormatProvider provider)
503                 {
504                         return NumberFormatter.NumberToString (format, m_value, provider);
505                 }
506
507                 // =========== IConvertible Methods =========== //
508                 public TypeCode GetTypeCode ()
509                 {
510                         return TypeCode.UInt32;
511                 }
512
513                 bool IConvertible.ToBoolean (IFormatProvider provider)
514                 {
515                         return System.Convert.ToBoolean (m_value);
516                 }
517
518                 byte IConvertible.ToByte (IFormatProvider provider)
519                 {
520                         return System.Convert.ToByte (m_value);
521                 }
522
523                 char IConvertible.ToChar (IFormatProvider provider)
524                 {
525                         return System.Convert.ToChar (m_value);
526                 }
527
528                 DateTime IConvertible.ToDateTime (IFormatProvider provider)
529                 {
530                         return System.Convert.ToDateTime (m_value);
531                 }
532
533                 decimal IConvertible.ToDecimal (IFormatProvider provider)
534                 {
535                         return System.Convert.ToDecimal (m_value);
536                 }
537
538                 double IConvertible.ToDouble (IFormatProvider provider)
539                 {
540                         return System.Convert.ToDouble (m_value);
541                 }
542
543                 short IConvertible.ToInt16 (IFormatProvider provider)
544                 {
545                         return System.Convert.ToInt16 (m_value);
546                 }
547
548                 int IConvertible.ToInt32 (IFormatProvider provider)
549                 {
550                         return System.Convert.ToInt32 (m_value);
551                 }
552
553                 long IConvertible.ToInt64 (IFormatProvider provider)
554                 {
555                         return System.Convert.ToInt64 (m_value);
556                 }
557
558                 sbyte IConvertible.ToSByte (IFormatProvider provider)
559                 {
560                         return System.Convert.ToSByte (m_value);
561                 }
562                 
563                 float IConvertible.ToSingle (IFormatProvider provider)
564                 {
565                         return System.Convert.ToSingle (m_value);
566                 }
567
568                 object IConvertible.ToType (Type targetType, IFormatProvider provider)
569                 {
570                         if (targetType == null)
571                                 throw new ArgumentNullException ("targetType");
572                         return System.Convert.ToType (m_value, targetType, provider, false);
573                 }
574
575                 ushort IConvertible.ToUInt16 (IFormatProvider provider)
576                 {
577                         return System.Convert.ToUInt16 (m_value);
578                 }
579
580                 uint IConvertible.ToUInt32 (IFormatProvider provider)
581                 {
582                         return m_value;
583                 }
584
585                 ulong IConvertible.ToUInt64 (IFormatProvider provider)
586                 {
587                         return System.Convert.ToUInt64 (m_value);
588                 }
589         }
590 }