2004-03-08 Andreas Nahr <ClassDevelopment@A-SoftTech.com>
[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 //
9
10 using System.Globalization;
11 using System.Threading;
12
13 namespace System
14 {
15         [Serializable]
16         [CLSCompliant (false)]
17         public struct UInt32 : IComparable, IFormattable, IConvertible
18         {
19                 public const uint MaxValue = 0xffffffff;
20                 public const uint MinValue = 0;
21
22                 internal uint value;
23
24                 public int CompareTo (object value)
25                 {
26                         if (value == null)
27                                 return 1;
28
29                         if (!(value is System.UInt32))
30                                 throw new ArgumentException (Locale.GetText ("Value is not a System.UInt32."));
31
32                         if (this.value == (uint) value)
33                                 return 0;
34
35                         if (this.value < (uint) value)
36                                 return -1;
37
38                         return 1;
39                 }
40
41                 public override bool Equals (object obj)
42                 {
43                         if (!(obj is System.UInt32))
44                                 return false;
45
46                         return ((uint) obj) == value;
47                 }
48
49                 public override int GetHashCode ()
50                 {
51                         return (int) value;
52                 }
53
54                 [CLSCompliant (false)]
55                 public static uint Parse (string s)
56                 {
57                         uint val = 0;
58                         int len;
59                         int i;
60                         bool digits_seen = false;
61                         bool has_negative_sign = false;
62
63                         if (s == null)
64                                 throw new ArgumentNullException (Locale.GetText ("s is null"));
65
66                         len = s.Length;
67
68                         char c;
69                         for (i = 0; i < len; i++) {
70                                 c = s [i];
71                                 if (!Char.IsWhiteSpace (c))
72                                         break;
73                         }
74
75                         if (i == len)
76                                 throw new FormatException ();
77
78                         if (s [i] == '+')
79                                 i++;
80                         else
81                                 if (s[i] == '-') {
82                                         i++;
83                                         has_negative_sign = true;
84                                 }
85
86                         for (; i < len; i++) {
87                                 c = s [i];
88
89                                 if (c >= '0' && c <= '9') {
90                                         uint d = (uint) (c - '0');
91
92                                         val = checked (val * 10 + d);
93                                         digits_seen = true;
94                                 }
95                                 else {
96                                         if (Char.IsWhiteSpace (c)) {
97                                                 for (i++; i < len; i++) {
98                                                         if (!Char.IsWhiteSpace (s [i]))
99                                                                 throw new FormatException ();
100                                                 }
101                                                 break;
102                                         } else
103                                                 throw new FormatException ();
104                                 }
105                         }
106                         if (!digits_seen)
107                                 throw new FormatException ();
108
109                         if (has_negative_sign)
110                                 throw new OverflowException ();
111
112                         return val;
113                 }
114
115                 [CLSCompliant (false)]
116                 public static uint Parse (string s, IFormatProvider provider)
117                 {
118                         return Parse (s, NumberStyles.Integer, provider);
119                 }
120
121                 [CLSCompliant (false)]
122                 public static uint Parse (string s, NumberStyles style)
123                 {
124                         return Parse (s, style, null);
125                 }
126
127                 [CLSCompliant (false)]
128                 public static uint Parse (string s, NumberStyles style, IFormatProvider provider)
129                 {
130                         if (s == null)
131                                 throw new ArgumentNullException ();
132
133                         if (s.Length == 0)
134                                 throw new FormatException (Locale.GetText ("Input string was not in the correct format."));
135
136                         NumberFormatInfo nfi;
137                         if (provider != null) {
138                                 Type typeNFI = typeof (NumberFormatInfo);
139                                 nfi = (NumberFormatInfo) provider.GetFormat (typeNFI);
140                         }
141                         else
142                                 nfi = Thread.CurrentThread.CurrentCulture.NumberFormat;
143
144                         Int32.CheckStyle (style);
145
146                         bool AllowCurrencySymbol = (style & NumberStyles.AllowCurrencySymbol) != 0;
147                         bool AllowExponent = (style & NumberStyles.AllowExponent) != 0;
148                         bool AllowHexSpecifier = (style & NumberStyles.AllowHexSpecifier) != 0;
149                         bool AllowThousands = (style & NumberStyles.AllowThousands) != 0;
150                         bool AllowDecimalPoint = (style & NumberStyles.AllowDecimalPoint) != 0;
151                         bool AllowParentheses = (style & NumberStyles.AllowParentheses) != 0;
152                         bool AllowTrailingSign = (style & NumberStyles.AllowTrailingSign) != 0;
153                         bool AllowLeadingSign = (style & NumberStyles.AllowLeadingSign) != 0;
154                         bool AllowTrailingWhite = (style & NumberStyles.AllowTrailingWhite) != 0;
155                         bool AllowLeadingWhite = (style & NumberStyles.AllowLeadingWhite) != 0;
156
157                         int pos = 0;
158
159                         if (AllowLeadingWhite)
160                                 pos = Int32.JumpOverWhite (pos, s, true);
161
162                         bool foundOpenParentheses = false;
163                         bool negative = false;
164                         bool foundSign = false;
165                         bool foundCurrency = false;
166
167                         // Pre-number stuff
168                         if (AllowParentheses && s [pos] == '(') {
169                                 foundOpenParentheses = true;
170                                 foundSign = true;
171                                 negative = true; // MS always make the number negative when there parentheses
172                                                  // even when NumberFormatInfo.NumberNegativePattern != 0!!!
173                                 pos++;
174                                 if (AllowLeadingWhite)
175                                         pos = Int32.JumpOverWhite (pos, s, true);
176
177                                 if (s.Substring (pos, nfi.NegativeSign.Length) == nfi.NegativeSign)
178                                         throw new FormatException (Locale.GetText ("Input string was not in the correct format."));
179                                 if (s.Substring (pos, nfi.PositiveSign.Length) == nfi.PositiveSign)
180                                         throw new FormatException (Locale.GetText ("Input string was not in the correct format."));
181                         }
182
183                         if (AllowLeadingSign && !foundSign) {
184                                 // Sign + Currency
185                                 Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
186                                 if (foundSign) {
187                                         if (AllowLeadingWhite)
188                                                 pos = Int32.JumpOverWhite (pos, s, true);
189                                         if (AllowCurrencySymbol) {
190                                                 Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
191                                                 if (foundCurrency && AllowLeadingWhite)
192                                                         pos = Int32.JumpOverWhite (pos, s, true);
193                                         }
194                                 }
195                         }
196
197                         if (AllowCurrencySymbol && !foundCurrency) {
198                                 // Currency + sign
199                                 Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
200                                 if (foundCurrency) {
201                                         if (AllowLeadingWhite)
202                                                 pos = Int32.JumpOverWhite (pos, s, true);
203                                         if (foundCurrency) {
204                                                 if (!foundSign && AllowLeadingSign) {
205                                                         Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
206                                                         if (foundSign && AllowLeadingWhite)
207                                                                 pos = Int32.JumpOverWhite (pos, s, true);
208                                                 }
209                                         }
210                                 }
211                         }
212
213                         uint number = 0;
214                         int nDigits = 0;
215                         bool decimalPointFound = false;
216                         uint digitValue;
217                         char hexDigit;
218
219                         // Number stuff
220                         // Just the same as Int32, but this one adds instead of substract
221                         do {
222
223                                 if (!Int32.ValidDigit (s [pos], AllowHexSpecifier)) {
224                                         if (AllowThousands && Int32.FindOther (ref pos, s, nfi.NumberGroupSeparator))
225                                                 continue;
226                                         else
227                                                 if (!decimalPointFound && AllowDecimalPoint &&
228                                                     Int32.FindOther (ref pos, s, nfi.NumberDecimalSeparator)) {
229                                                         decimalPointFound = true;
230                                                         continue;
231                                                 }
232                                         break;
233                                 }
234                                 else if (AllowHexSpecifier) {
235                                         nDigits++;
236                                         hexDigit = s [pos++];
237                                         if (Char.IsDigit (hexDigit))
238                                                 digitValue = (uint) (hexDigit - '0');
239                                         else if (Char.IsLower (hexDigit))
240                                                 digitValue = (uint) (hexDigit - 'a' + 10);
241                                         else
242                                                 digitValue = (uint) (hexDigit - 'A' + 10);
243
244                                         number = checked (number * 16 + digitValue);
245                                 }
246                                 else if (decimalPointFound) {
247                                         nDigits++;
248                                         // Allows decimal point as long as it's only 
249                                         // followed by zeroes.
250                                         if (s [pos++] != '0')
251                                                 throw new OverflowException (Locale.GetText ("Value too large or too small."));
252                                 }
253                                 else {
254                                         nDigits++;
255
256                                         try {
257                                                 number = checked (number * 10 + (uint) (s [pos++] - '0'));
258                                         }
259                                         catch (OverflowException) {
260                                                 throw new OverflowException (Locale.GetText ("Value too large or too small."));
261                                         }
262                                 }
263                         } while (pos < s.Length);
264
265                         // Post number stuff
266                         if (nDigits == 0)
267                                 throw new FormatException (Locale.GetText ("Input string was not in the correct format."));
268
269                         if (AllowTrailingSign && !foundSign) {
270                                 // Sign + Currency
271                                 Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
272                                 if (foundSign) {
273                                         if (AllowTrailingWhite)
274                                                 pos = Int32.JumpOverWhite (pos, s, true);
275                                         if (AllowCurrencySymbol)
276                                                 Int32. FindCurrency (ref pos, s, nfi, ref foundCurrency);
277                                 }
278                         }
279
280                         if (AllowCurrencySymbol && !foundCurrency) {
281                                 // Currency + sign
282                                 Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
283                                 if (foundCurrency) {
284                                         if (AllowTrailingWhite)
285                                                 pos = Int32.JumpOverWhite (pos, s, true);
286                                         if (!foundSign && AllowTrailingSign)
287                                                 Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
288                                 }
289                         }
290
291                         if (AllowTrailingWhite && pos < s.Length)
292                                 pos = Int32.JumpOverWhite (pos, s, false);
293
294                         if (foundOpenParentheses) {
295                                 if (pos >= s.Length || s [pos++] != ')')
296                                         throw new FormatException (Locale.GetText
297                                                 ("Input string was not in the correct format."));
298                                 if (AllowTrailingWhite && pos < s.Length)
299                                         pos = Int32.JumpOverWhite (pos, s, false);
300                         }
301
302                         if (pos < s.Length && s [pos] != '\u0000')
303                                 throw new FormatException (Locale.GetText ("Input string was not in the correct format."));
304
305                         if (negative)
306                                 throw new OverflowException (Locale.GetText ("Value too large or too small."));
307
308                         return number;
309                 }
310
311                 public override string ToString ()
312                 {
313                         return ToString (null, null);
314                 }
315
316                 public string ToString (IFormatProvider fp)
317                 {
318                         return ToString (null, fp);
319                 }
320
321                 public string ToString (string format)
322                 {
323                         return ToString (format, null);
324                 }
325
326                 public string ToString (string format, IFormatProvider fp)
327                 {
328                         NumberFormatInfo nfi = NumberFormatInfo.GetInstance (fp);
329                         
330                         if (format == null)
331                                 format = "G";
332                         
333                         return IntegerFormatter.NumberToString (format, nfi, value);
334                 }
335
336                 // =========== IConvertible Methods =========== //
337                 public TypeCode GetTypeCode ()
338                 {
339                         return TypeCode.UInt32;
340                 }
341
342                 bool IConvertible.ToBoolean (IFormatProvider provider)
343                 {
344                         return System.Convert.ToBoolean (value);
345                 }
346
347                 byte IConvertible.ToByte (IFormatProvider provider)
348                 {
349                         return System.Convert.ToByte (value);
350                 }
351
352                 char IConvertible.ToChar (IFormatProvider provider)
353                 {
354                         return System.Convert.ToChar (value);
355                 }
356
357                 DateTime IConvertible.ToDateTime (IFormatProvider provider)
358                 {
359                         return System.Convert.ToDateTime (value);
360                 }
361
362                 decimal IConvertible.ToDecimal (IFormatProvider provider)
363                 {
364                         return System.Convert.ToDecimal (value);
365                 }
366
367                 double IConvertible.ToDouble (IFormatProvider provider)
368                 {
369                         return System.Convert.ToDouble (value);
370                 }
371
372                 short IConvertible.ToInt16 (IFormatProvider provider)
373                 {
374                         return System.Convert.ToInt16 (value);
375                 }
376
377                 int IConvertible.ToInt32 (IFormatProvider provider)
378                 {
379                         return System.Convert.ToInt32 (value);
380                 }
381
382                 long IConvertible.ToInt64 (IFormatProvider provider)
383                 {
384                         return System.Convert.ToInt64 (value);
385                 }
386
387                 [CLSCompliant (false)]
388                 sbyte IConvertible.ToSByte (IFormatProvider provider)
389                 {
390                         return System.Convert.ToSByte (value);
391                 }
392                 
393                 float IConvertible.ToSingle (IFormatProvider provider)
394                 {
395                         return System.Convert.ToSingle (value);
396                 }
397
398                 object IConvertible.ToType (Type conversionType, IFormatProvider provider)
399                 {
400                         return System.Convert.ToType (value, conversionType, provider);
401                 }
402
403                 [CLSCompliant (false)]
404                 ushort IConvertible.ToUInt16 (IFormatProvider provider)
405                 {
406                         return System.Convert.ToUInt16 (value);
407                 }
408
409                 [CLSCompliant (false)]
410                 uint IConvertible.ToUInt32 (IFormatProvider provider)
411                 {
412                         return System.Convert.ToUInt32 (value);
413                 }
414
415                 [CLSCompliant (false)]
416                 ulong IConvertible.ToUInt64 (IFormatProvider provider)
417                 {
418                         return System.Convert.ToUInt64 (value);
419                 }
420         }
421 }