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