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