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