remove warning
[mono.git] / mcs / class / corlib / System / UInt32.cs
1 //
2 // System.UInt32.cs
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //
7 // (C) Ximian, Inc.  http://www.ximian.com
8 // Copyright (C) 2004 Novell (http://www.novell.com)
9 //
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:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
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.
28 //
29
30 using System.Globalization;
31 using System.Threading;
32
33 namespace System
34 {
35         [Serializable]
36         [CLSCompliant (false)]
37 #if NET_2_0
38         [System.Runtime.InteropServices.ComVisible (true)]
39 #endif
40         public struct UInt32 : IFormattable, IConvertible, IComparable
41 #if NET_2_0
42                 , IComparable<UInt32>, IEquatable <UInt32>
43 #endif
44         {
45                 public const uint MaxValue = 0xffffffff;
46                 public const uint MinValue = 0;
47
48                 internal uint m_value;
49
50                 public int CompareTo (object value)
51                 {
52                         if (value == null)
53                                 return 1;
54
55                         if (!(value is System.UInt32))
56                                 throw new ArgumentException (Locale.GetText ("Value is not a System.UInt32."));
57
58                         if (this.m_value == (uint) value)
59                                 return 0;
60
61                         if (this.m_value < (uint) value)
62                                 return -1;
63
64                         return 1;
65                 }
66
67                 public override bool Equals (object obj)
68                 {
69                         if (!(obj is System.UInt32))
70                                 return false;
71
72                         return ((uint) obj) == m_value;
73                 }
74
75                 public override int GetHashCode ()
76                 {
77                         return (int) m_value;
78                 }
79
80 #if NET_2_0
81                 public int CompareTo (uint value)
82                 {
83                         if (m_value == value)
84                                 return 0;
85                         if (m_value > value)
86                                 return 1;
87                         else
88                                 return -1;
89                 }
90
91                 public bool Equals (uint value)
92                 {
93                         return value == m_value;
94                 }
95 #endif
96
97                 internal static bool Parse (string s, bool tryParse, out uint result, out Exception exc)
98                 {
99                         uint val = 0;
100                         int len;
101                         int i;
102                         bool digits_seen = false;
103                         bool has_negative_sign = false;
104
105                         result = 0;
106                         exc = null;
107
108                         if (s == null) {
109                                 if (!tryParse)
110                                         exc = new ArgumentNullException ("s");
111                                 return false;
112                         }
113
114                         len = s.Length;
115
116                         char c;
117                         for (i = 0; i < len; i++) {
118                                 c = s [i];
119                                 if (!Char.IsWhiteSpace (c))
120                                         break;
121                         }
122
123                         if (i == len) {
124                                 if (!tryParse)
125                                         exc = Int32.GetFormatException ();
126                                 return false;
127                         }
128
129                         if (s [i] == '+')
130                                 i++;
131                         else
132                                 if (s[i] == '-') {
133                                         i++;
134                                         has_negative_sign = true;
135                                 }
136
137                         for (; i < len; i++) {
138                                 c = s [i];
139
140                                 if (c >= '0' && c <= '9') {
141                                         uint d = (uint) (c - '0');
142
143                                         if ((val > MaxValue/10) || (val == (MaxValue / 10) && d > (MaxValue % 10))){
144                                                 if (!tryParse)
145                                                         exc = new OverflowException (Locale.GetText ("Value is too large"));
146                                                 return false;
147                                         }
148                                         val = (val * 10) + d;
149                                         digits_seen = true;
150                                 } else if (!Int32.ProcessTrailingWhitespace (tryParse, s, i, ref exc)){
151                                         return false;
152                                 }
153                         }
154                         if (!digits_seen) {
155                                 if (!tryParse)
156                                         exc = Int32.GetFormatException ();
157                                 return false;
158                         }
159
160                         // -0 is legal but other negative values are not
161                         if (has_negative_sign && (val > 0)) {
162                                 if (!tryParse)
163                                         exc = new OverflowException (
164                                             Locale.GetText ("Negative number"));
165                                 return false;
166                         }
167
168                         result = val;
169                         return true;
170                 }
171
172                 internal static bool Parse (string s, NumberStyles style, IFormatProvider provider, bool tryParse, out uint result, out Exception exc)
173                 {
174                         result = 0;
175                         exc = null;
176
177                         if (s == null) {
178                                 if (!tryParse)
179                                         exc = new ArgumentNullException ("s");
180                                 return false;
181                         }
182
183                         if (s.Length == 0) {
184                                 if (!tryParse)
185                                         exc = Int32.GetFormatException ();
186                                 return false;
187                         }
188
189                         NumberFormatInfo nfi;
190                         if (provider != null) {
191                                 Type typeNFI = typeof (NumberFormatInfo);
192                                 nfi = (NumberFormatInfo) provider.GetFormat (typeNFI);
193                         }
194                         else
195                                 nfi = Thread.CurrentThread.CurrentCulture.NumberFormat;
196
197                         if (!Int32.CheckStyle (style, tryParse, ref exc))
198                                 return false;
199
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;
209
210                         int pos = 0;
211
212                         if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
213                                 return false;
214
215                         bool foundOpenParentheses = false;
216                         bool negative = false;
217                         bool foundSign = false;
218                         bool foundCurrency = false;
219
220                         // Pre-number stuff
221                         if (AllowParentheses && s [pos] == '(') {
222                                 foundOpenParentheses = true;
223                                 foundSign = true;
224                                 negative = true; // MS always make the number negative when there parentheses
225                                                  // even when NumberFormatInfo.NumberNegativePattern != 0!!!
226                                 pos++;
227                                 if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
228                                         return false;
229
230                                 if (s.Substring (pos, nfi.NegativeSign.Length) == nfi.NegativeSign) {
231                                         if (!tryParse)
232                                                 exc = Int32.GetFormatException ();
233                                         return false;
234                                 }
235                                 if (s.Substring (pos, nfi.PositiveSign.Length) == nfi.PositiveSign) {
236                                         if (!tryParse)
237                                                 exc = Int32.GetFormatException ();
238                                         return false;
239                                 }
240                         }
241
242                         if (AllowLeadingSign && !foundSign) {
243                                 // Sign + Currency
244                                 Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
245                                 if (foundSign) {
246                                         if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
247                                                 return false;
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))
252                                                         return false;
253                                         }
254                                 }
255                         }
256
257                         if (AllowCurrencySymbol && !foundCurrency) {
258                                 // Currency + sign
259                                 Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
260                                 if (foundCurrency) {
261                                         if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
262                                                 return false;
263                                         if (foundCurrency) {
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))
268                                                                 return false;
269                                                 }
270                                         }
271                                 }
272                         }
273
274                         uint number = 0;
275                         int nDigits = 0;
276                         bool decimalPointFound = false;
277                         uint digitValue;
278                         char hexDigit;
279
280                         // Number stuff
281                         // Just the same as Int32, but this one adds instead of substract
282                         do {
283
284                                 if (!Int32.ValidDigit (s [pos], AllowHexSpecifier)) {
285                                         if (AllowThousands && Int32.FindOther (ref pos, s, nfi.NumberGroupSeparator))
286                                                 continue;
287                                         else
288                                                 if (!decimalPointFound && AllowDecimalPoint &&
289                                                     Int32.FindOther (ref pos, s, nfi.NumberDecimalSeparator)) {
290                                                         decimalPointFound = true;
291                                                         continue;
292                                                 }
293                                         break;
294                                 }
295                                 else if (AllowHexSpecifier) {
296                                         nDigits++;
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);
302                                         else
303                                                 digitValue = (uint) (hexDigit - 'A' + 10);
304
305                                         if (tryParse){
306                                                 ulong l = number * 16 + digitValue;
307
308                                                 if (l > MaxValue)
309                                                         return false;
310                                                 number = (uint) l;
311                                         } else
312                                                 number = checked (number * 16 + digitValue);
313                                 }
314                                 else if (decimalPointFound) {
315                                         nDigits++;
316                                         // Allows decimal point as long as it's only 
317                                         // followed by zeroes.
318                                         if (s [pos++] != '0') {
319                                                 if (!tryParse)
320                                                         exc = new OverflowException (Locale.GetText ("Value too large or too small."));
321                                                 return false;
322                                         }
323                                 }
324                                 else {
325                                         nDigits++;
326
327                                         try {
328                                                 number = checked (number * 10 + (uint) (s [pos++] - '0'));
329                                         }
330                                         catch (OverflowException) {
331                                                 if (!tryParse)
332                                                         exc = new OverflowException (Locale.GetText ("Value too large or too small."));
333                                                 return false;
334                                         }
335                                 }
336                         } while (pos < s.Length);
337
338                         // Post number stuff
339                         if (nDigits == 0) {
340                                 if (!tryParse)
341                                         exc = Int32.GetFormatException ();
342                                 return false;
343                         }
344
345                         if (AllowTrailingSign && !foundSign) {
346                                 // Sign + Currency
347                                 Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
348                                 if (foundSign) {
349                                         if (AllowTrailingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
350                                                 return false;
351                                         if (AllowCurrencySymbol)
352                                                 Int32. FindCurrency (ref pos, s, nfi, ref foundCurrency);
353                                 }
354                         }
355
356                         if (AllowCurrencySymbol && !foundCurrency) {
357                                 // Currency + sign
358                                 Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
359                                 if (foundCurrency) {
360                                         if (AllowTrailingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
361                                                 return false;
362                                         if (!foundSign && AllowTrailingSign)
363                                                 Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
364                                 }
365                         }
366
367                         if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite (ref pos, s, false, tryParse, ref exc))
368                                 return false;
369
370                         if (foundOpenParentheses) {
371                                 if (pos >= s.Length || s [pos++] != ')') {
372                                         if (!tryParse)
373                                                 exc = Int32.GetFormatException ();
374                                         return false;
375                                 }
376                                 if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite (ref pos, s, false, tryParse, ref exc))
377                                         return false;
378                         }
379
380                         if (pos < s.Length && s [pos] != '\u0000') {
381                                 if (!tryParse)
382                                         exc = Int32.GetFormatException ();
383                                 return false;
384                         }
385
386                         // -0 is legal but other negative values are not
387                         if (negative && (number > 0)) {
388                                 if (!tryParse)
389                                         exc = new OverflowException (
390                                             Locale.GetText ("Negative number"));
391                                 return false;
392                         }
393
394                         result = number;
395
396                         return true;
397                 }
398
399                 [CLSCompliant (false)]
400                 public static uint Parse (string s) 
401                 {
402                         Exception exc;
403                         uint res;
404
405                         if (!Parse (s, false, out res, out exc))
406                                 throw exc;
407
408                         return res;
409                 }
410
411                 [CLSCompliant (false)]
412                 public static uint Parse (string s, NumberStyles style, IFormatProvider fp) 
413                 {
414                         Exception exc;
415                         uint res;
416
417                         if (!Parse (s, style, fp, false, out res, out exc))
418                                 throw exc;
419
420                         return res;
421                 }
422
423                 [CLSCompliant (false)]
424                 public static uint Parse (string s, IFormatProvider provider)
425                 {
426                         return Parse (s, NumberStyles.Integer, provider);
427                 }
428
429                 [CLSCompliant (false)]
430                 public static uint Parse (string s, NumberStyles style)
431                 {
432                         return Parse (s, style, null);
433                 }
434
435 #if NET_2_0
436                 [CLSCompliant (false)]
437                 public static bool TryParse (string s, out uint result) 
438                 {
439                         Exception exc;
440                         if (!Parse (s, true, out result, out exc)) {
441                                 result = 0;
442                                 return false;
443                         }
444
445                         return true;
446                 }
447
448                 [CLSCompliant (false)]
449                 public static bool TryParse (string s, NumberStyles style, IFormatProvider provider, out uint result) 
450                 {
451                         Exception exc;
452                         if (!Parse (s, style, provider, true, out result, out exc)) {
453                                 result = 0;
454                                 return false;
455                         }
456
457                         return true;
458                 }
459 #endif
460
461                 public override string ToString ()
462                 {
463                         return NumberFormatter.FormatGeneral (new NumberFormatter.NumberStore (m_value));
464                 }
465
466                 public string ToString (IFormatProvider fp)
467                 {
468                         return NumberFormatter.FormatGeneral (new NumberFormatter.NumberStore (m_value), fp);
469                 }
470
471                 public string ToString (string format)
472                 {
473                         return ToString (format, null);
474                 }
475
476                 public string ToString (string format, IFormatProvider fp)
477                 {
478                         NumberFormatInfo nfi = NumberFormatInfo.GetInstance (fp);
479                         return NumberFormatter.NumberToString (format, m_value, nfi);
480                 }
481
482                 // =========== IConvertible Methods =========== //
483                 public TypeCode GetTypeCode ()
484                 {
485                         return TypeCode.UInt32;
486                 }
487
488                 bool IConvertible.ToBoolean (IFormatProvider provider)
489                 {
490                         return System.Convert.ToBoolean (m_value);
491                 }
492
493                 byte IConvertible.ToByte (IFormatProvider provider)
494                 {
495                         return System.Convert.ToByte (m_value);
496                 }
497
498                 char IConvertible.ToChar (IFormatProvider provider)
499                 {
500                         return System.Convert.ToChar (m_value);
501                 }
502
503                 DateTime IConvertible.ToDateTime (IFormatProvider provider)
504                 {
505                         return System.Convert.ToDateTime (m_value);
506                 }
507
508                 decimal IConvertible.ToDecimal (IFormatProvider provider)
509                 {
510                         return System.Convert.ToDecimal (m_value);
511                 }
512
513                 double IConvertible.ToDouble (IFormatProvider provider)
514                 {
515                         return System.Convert.ToDouble (m_value);
516                 }
517
518                 short IConvertible.ToInt16 (IFormatProvider provider)
519                 {
520                         return System.Convert.ToInt16 (m_value);
521                 }
522
523                 int IConvertible.ToInt32 (IFormatProvider provider)
524                 {
525                         return System.Convert.ToInt32 (m_value);
526                 }
527
528                 long IConvertible.ToInt64 (IFormatProvider provider)
529                 {
530                         return System.Convert.ToInt64 (m_value);
531                 }
532
533                 sbyte IConvertible.ToSByte (IFormatProvider provider)
534                 {
535                         return System.Convert.ToSByte (m_value);
536                 }
537                 
538                 float IConvertible.ToSingle (IFormatProvider provider)
539                 {
540                         return System.Convert.ToSingle (m_value);
541                 }
542
543                 object IConvertible.ToType (Type conversionType, IFormatProvider provider)
544                 {
545                         return System.Convert.ToType (m_value, conversionType, provider);
546                 }
547
548                 ushort IConvertible.ToUInt16 (IFormatProvider provider)
549                 {
550                         return System.Convert.ToUInt16 (m_value);
551                 }
552
553                 uint IConvertible.ToUInt32 (IFormatProvider provider)
554                 {
555                         return m_value;
556                 }
557
558                 ulong IConvertible.ToUInt64 (IFormatProvider provider)
559                 {
560                         return System.Convert.ToUInt64 (m_value);
561                 }
562         }
563 }