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