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