move FrameworkName from corlib to System
[mcs.git] / class / corlib / System / UInt64.cs
blob8f138197b259353032f708b6affbcec3f68cdc38
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.
30 using System.Globalization;
31 using System.Threading;
33 namespace System
35 [Serializable]
36 [CLSCompliant (false)]
37 [System.Runtime.InteropServices.ComVisible (true)]
38 public struct UInt64 : IFormattable, IConvertible, IComparable, IComparable<UInt64>, IEquatable <UInt64>
40 public const ulong MaxValue = 0xffffffffffffffff;
41 public const ulong MinValue = 0;
43 internal ulong m_value;
45 public int CompareTo (object value)
47 if (value == null)
48 return 1;
50 if (!(value is System.UInt64))
51 throw new ArgumentException (Locale.GetText ("Value is not a System.UInt64."));
53 ulong int64 = (ulong) value;
55 if (m_value == int64)
56 return 0;
58 return (m_value < int64) ? -1 : 1;
61 public override bool Equals (object obj)
63 if (!(obj is System.UInt64))
64 return false;
66 return ((ulong) obj) == m_value;
69 public override int GetHashCode ()
71 return (int)(m_value & 0xffffffff) ^ (int)(m_value >> 32);
74 public int CompareTo (ulong value)
76 if (m_value == value)
77 return 0;
78 if (m_value > value)
79 return 1;
80 else
81 return -1;
84 public bool Equals (ulong obj)
86 return obj == m_value;
89 [CLSCompliant (false)]
90 public static ulong Parse (string s)
92 Exception exc;
93 ulong result;
95 if (!Parse (s, false, out result, out exc))
96 throw exc;
98 return result;
101 internal static bool Parse (string s, bool tryParse, out ulong result, out Exception exc)
103 ulong val = 0;
104 int len;
105 int i;
106 bool digits_seen = false;
107 bool has_negative_sign = false;
109 exc = null;
110 result = 0;
112 if (s == null) {
113 if (!tryParse)
114 exc = new ArgumentNullException ("s");
115 return false;
118 len = s.Length;
120 char c;
121 for (i = 0; i < len; i++) {
122 c = s [i];
123 if (!Char.IsWhiteSpace (c))
124 break;
127 if (i == len) {
128 if (!tryParse)
129 exc = Int32.GetFormatException ();
130 return false;
133 if (s [i] == '+')
134 i++;
135 else if (s [i] == '-') {
136 i++;
137 has_negative_sign = true;
140 // Actual number stuff
141 for (; i < len; i++) {
142 c = s [i];
144 if (c >= '0' && c <= '9') {
145 uint d = (uint) (c - '0');
147 if (val > MaxValue / 10 || (val == MaxValue / 10 && d > MaxValue % 10)) {
148 if (!tryParse)
149 exc = new OverflowException ("Value is too large.");
150 return false;
153 val = (val * 10) + d;
154 digits_seen = true;
155 } else if (!Int32.ProcessTrailingWhitespace (tryParse, s, i, ref exc))
156 return false;
159 if (!digits_seen) {
160 if (!tryParse)
161 exc = Int32.GetFormatException ();
162 return false;
165 if (has_negative_sign && val > 0) {
166 if (!tryParse)
167 exc = new OverflowException ("Negative number.");
168 return false;
171 result = val;
172 return true;
175 [CLSCompliant (false)]
176 public static ulong Parse (string s, IFormatProvider provider)
178 return Parse (s, NumberStyles.Integer, provider);
181 [CLSCompliant (false)]
182 public static ulong Parse (string s, NumberStyles style)
184 return Parse (s, style, null);
187 internal static bool Parse (string s, NumberStyles style, IFormatProvider provider, bool tryParse, out ulong result, out Exception exc)
189 result = 0;
190 exc = null;
192 if (s == null) {
193 if (!tryParse)
194 exc = new ArgumentNullException ("s");
195 return false;
198 if (s.Length == 0) {
199 if (!tryParse)
200 exc = Int32.GetFormatException ();
201 return false;
204 NumberFormatInfo nfi = null;
205 if (provider != null) {
206 Type typeNFI = typeof (NumberFormatInfo);
207 nfi = (NumberFormatInfo) provider.GetFormat (typeNFI);
209 if (nfi == null)
210 nfi = Thread.CurrentThread.CurrentCulture.NumberFormat;
212 if (!Int32.CheckStyle (style, tryParse, ref exc))
213 return false;
215 bool AllowCurrencySymbol = (style & NumberStyles.AllowCurrencySymbol) != 0;
216 bool AllowHexSpecifier = (style & NumberStyles.AllowHexSpecifier) != 0;
217 bool AllowThousands = (style & NumberStyles.AllowThousands) != 0;
218 bool AllowDecimalPoint = (style & NumberStyles.AllowDecimalPoint) != 0;
219 bool AllowParentheses = (style & NumberStyles.AllowParentheses) != 0;
220 bool AllowTrailingSign = (style & NumberStyles.AllowTrailingSign) != 0;
221 bool AllowLeadingSign = (style & NumberStyles.AllowLeadingSign) != 0;
222 bool AllowTrailingWhite = (style & NumberStyles.AllowTrailingWhite) != 0;
223 bool AllowLeadingWhite = (style & NumberStyles.AllowLeadingWhite) != 0;
225 int pos = 0;
227 if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
228 return false;
230 bool foundOpenParentheses = false;
231 bool negative = false;
232 bool foundSign = false;
233 bool foundCurrency = false;
235 // Pre-number stuff
236 if (AllowParentheses && s [pos] == '(') {
237 foundOpenParentheses = true;
238 foundSign = true;
239 negative = true; // MS always make the number negative when there parentheses
240 // even when NumberFormatInfo.NumberNegativePattern != 0!!!
241 pos++;
242 if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
243 return false;
245 if (s.Substring (pos, nfi.NegativeSign.Length) == nfi.NegativeSign) {
246 if (!tryParse)
247 exc = Int32.GetFormatException ();
248 return false;
250 if (s.Substring (pos, nfi.PositiveSign.Length) == nfi.PositiveSign) {
251 if (!tryParse)
252 exc = Int32.GetFormatException ();
253 return false;
257 if (AllowLeadingSign && !foundSign) {
258 // Sign + Currency
259 Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
260 if (foundSign) {
261 if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
262 return false;
263 if (AllowCurrencySymbol) {
264 Int32.FindCurrency (ref pos, s, nfi,
265 ref foundCurrency);
266 if (foundCurrency && AllowLeadingWhite &&
267 !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
268 return false;
273 if (AllowCurrencySymbol && !foundCurrency) {
274 // Currency + sign
275 Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
276 if (foundCurrency) {
277 if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
278 return false;
279 if (foundCurrency) {
280 if (!foundSign && AllowLeadingSign) {
281 Int32.FindSign (ref pos, s, nfi, ref foundSign,
282 ref negative);
283 if (foundSign && AllowLeadingWhite &&
284 !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
285 return false;
291 ulong number = 0;
292 int nDigits = 0;
293 bool decimalPointFound = false;
294 ulong digitValue;
295 char hexDigit;
297 // Number stuff
298 // Just the same as Int32, but this one adds instead of substract
299 do {
301 if (!Int32.ValidDigit (s [pos], AllowHexSpecifier)) {
302 if (AllowThousands && Int32.FindOther (ref pos, s, nfi.NumberGroupSeparator))
303 continue;
304 else
305 if (!decimalPointFound && AllowDecimalPoint &&
306 Int32.FindOther (ref pos, s, nfi.NumberDecimalSeparator)) {
307 decimalPointFound = true;
308 continue;
310 break;
312 else if (AllowHexSpecifier) {
313 nDigits++;
314 hexDigit = s [pos++];
315 if (Char.IsDigit (hexDigit))
316 digitValue = (ulong) (hexDigit - '0');
317 else if (Char.IsLower (hexDigit))
318 digitValue = (ulong) (hexDigit - 'a' + 10);
319 else
320 digitValue = (ulong) (hexDigit - 'A' + 10);
322 if (tryParse){
323 // Any number above 32 will do
324 bool can_overflow = number > 0xffff;
326 number = number * 16 + digitValue;
328 if (can_overflow && number < 16)
329 return false;
330 } else
331 number = checked (number * 16 + digitValue);
333 else if (decimalPointFound) {
334 nDigits++;
335 // Allows decimal point as long as it's only
336 // followed by zeroes.
337 if (s [pos++] != '0') {
338 if (!tryParse)
339 exc = new OverflowException (Locale.GetText ("Value too large or too small."));
340 return false;
343 else {
344 nDigits++;
346 try {
347 number = checked (number * 10 + (ulong) (s [pos++] - '0'));
349 catch (OverflowException) {
350 if (!tryParse)
351 exc = new OverflowException (Locale.GetText ("Value too large or too small."));
352 return false;
355 } while (pos < s.Length);
357 // Post number stuff
358 if (nDigits == 0) {
359 if (!tryParse)
360 exc = Int32.GetFormatException ();
361 return false;
364 if (AllowTrailingSign && !foundSign) {
365 // Sign + Currency
366 Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
367 if (foundSign) {
368 if (AllowTrailingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
369 return false;
370 if (AllowCurrencySymbol)
371 Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
375 if (AllowCurrencySymbol && !foundCurrency) {
376 // Currency + sign
377 Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
378 if (foundCurrency) {
379 if (AllowTrailingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
380 return false;
381 if (!foundSign && AllowTrailingSign)
382 Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
386 if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite (ref pos, s, false, tryParse, ref exc))
387 return false;
389 if (foundOpenParentheses) {
390 if (pos >= s.Length || s [pos++] != ')') {
391 if (!tryParse)
392 exc = Int32.GetFormatException ();
393 return false;
395 if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite (ref pos, s, false, tryParse, ref exc))
396 return false;
399 if (pos < s.Length && s [pos] != '\u0000') {
400 if (!tryParse)
401 exc = Int32.GetFormatException ();
402 return false;
405 // -0 is legal but other negative values are not
406 if (negative && (number > 0)) {
407 if (!tryParse)
408 exc = new OverflowException (
409 Locale.GetText ("Negative number"));
410 return false;
413 result = number;
414 return true;
417 [CLSCompliant (false)]
418 public static ulong Parse (string s, NumberStyles style, IFormatProvider provider)
420 Exception exc;
421 ulong res;
423 if (!Parse (s, style, provider, false, out res, out exc))
424 throw exc;
426 return res;
430 [CLSCompliant (false)]
431 public static bool TryParse (string s, out ulong result)
433 Exception exc;
434 if (!Parse (s, true, out result, out exc)) {
435 result = 0;
436 return false;
439 return true;
442 [CLSCompliant (false)]
443 public static bool TryParse (string s, NumberStyles style, IFormatProvider provider, out ulong result)
445 Exception exc;
446 if (!Parse (s, style, provider, true, out result, out exc)) {
447 result = 0;
448 return false;
451 return true;
454 public override string ToString ()
456 return NumberFormatter.NumberToString (m_value, null);
459 public string ToString (IFormatProvider provider)
461 return NumberFormatter.NumberToString (m_value, provider);
464 public string ToString (string format)
466 return ToString (format, null);
469 public string ToString (string format, IFormatProvider provider)
471 return NumberFormatter.NumberToString (format, m_value, provider);
474 // =========== IConvertible Methods =========== //
475 public TypeCode GetTypeCode ()
477 return TypeCode.UInt64;
480 bool IConvertible.ToBoolean (IFormatProvider provider)
482 return System.Convert.ToBoolean (m_value);
485 byte IConvertible.ToByte (IFormatProvider provider)
487 return System.Convert.ToByte (m_value);
490 char IConvertible.ToChar (IFormatProvider provider)
492 return System.Convert.ToChar (m_value);
495 DateTime IConvertible.ToDateTime (IFormatProvider provider)
497 return System.Convert.ToDateTime (m_value);
500 decimal IConvertible.ToDecimal (IFormatProvider provider)
502 return System.Convert.ToDecimal (m_value);
505 double IConvertible.ToDouble (IFormatProvider provider)
507 return System.Convert.ToDouble (m_value);
510 short IConvertible.ToInt16 (IFormatProvider provider)
512 return System.Convert.ToInt16 (m_value);
515 int IConvertible.ToInt32 (IFormatProvider provider)
517 return System.Convert.ToInt32 (m_value);
520 long IConvertible.ToInt64 (IFormatProvider provider)
522 return System.Convert.ToInt64 (m_value);
525 sbyte IConvertible.ToSByte(IFormatProvider provider)
527 return System.Convert.ToSByte (m_value);
530 float IConvertible.ToSingle (IFormatProvider provider)
532 return System.Convert.ToSingle (m_value);
535 object IConvertible.ToType (Type targetType, IFormatProvider provider)
537 if (targetType == null)
538 throw new ArgumentNullException ("targetType");
540 return System.Convert.ToType (m_value, targetType, provider, false);
543 ushort IConvertible.ToUInt16 (IFormatProvider provider)
545 return System.Convert.ToUInt16 (m_value);
548 uint IConvertible.ToUInt32 (IFormatProvider provider)
550 return System.Convert.ToUInt32 (m_value);
553 ulong IConvertible.ToUInt64 (IFormatProvider provider)
555 return m_value;