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