5 // Miguel de Icaza (miguel@ximian.com)
7 // (C) Ximian, Inc. http://www.ximian.com
8 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
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:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
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;
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)
50 if (!(value is System.UInt64))
51 throw new ArgumentException (Locale.GetText ("Value is not a System.UInt64."));
53 ulong int64 = (ulong) value;
58 return (m_value < int64) ? -1 : 1;
61 public override bool Equals (object obj)
63 if (!(obj is System.UInt64))
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)
84 public bool Equals (ulong obj)
86 return obj == m_value;
89 [CLSCompliant (false)]
90 public static ulong Parse (string s)
95 if (!Parse (s, false, out result, out exc))
101 internal static bool Parse (string s, bool tryParse, out ulong result, out Exception exc)
106 bool digits_seen = false;
107 bool has_negative_sign = false;
114 exc = new ArgumentNullException ("s");
121 for (i = 0; i < len; i++) {
123 if (!Char.IsWhiteSpace (c))
129 exc = Int32.GetFormatException ();
135 else if (s [i] == '-') {
137 has_negative_sign = true;
140 // Actual number stuff
141 for (; i < len; i++) {
144 if (c >= '0' && c <= '9') {
145 uint d = (uint) (c - '0');
147 if (val > MaxValue / 10 || (val == MaxValue / 10 && d > MaxValue % 10)) {
149 exc = new OverflowException ("Value is too large.");
153 val = (val * 10) + d;
155 } else if (!Int32.ProcessTrailingWhitespace (tryParse, s, i, ref exc))
161 exc = Int32.GetFormatException ();
165 if (has_negative_sign && val > 0) {
167 exc = new OverflowException ("Negative number.");
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)
194 exc = new ArgumentNullException ("s");
200 exc = Int32.GetFormatException ();
204 NumberFormatInfo nfi = null;
205 if (provider != null) {
206 Type typeNFI = typeof (NumberFormatInfo);
207 nfi = (NumberFormatInfo) provider.GetFormat (typeNFI);
210 nfi = Thread.CurrentThread.CurrentCulture.NumberFormat;
212 if (!Int32.CheckStyle (style, tryParse, ref exc))
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;
227 if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
230 bool foundOpenParentheses = false;
231 bool negative = false;
232 bool foundSign = false;
233 bool foundCurrency = false;
236 if (AllowParentheses && s [pos] == '(') {
237 foundOpenParentheses = true;
239 negative = true; // MS always make the number negative when there parentheses
240 // even when NumberFormatInfo.NumberNegativePattern != 0!!!
242 if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
245 if (s.Substring (pos, nfi.NegativeSign.Length) == nfi.NegativeSign) {
247 exc = Int32.GetFormatException ();
250 if (s.Substring (pos, nfi.PositiveSign.Length) == nfi.PositiveSign) {
252 exc = Int32.GetFormatException ();
257 if (AllowLeadingSign && !foundSign) {
259 Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
261 if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
263 if (AllowCurrencySymbol) {
264 Int32.FindCurrency (ref pos, s, nfi,
266 if (foundCurrency && AllowLeadingWhite &&
267 !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
273 if (AllowCurrencySymbol && !foundCurrency) {
275 Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
277 if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
280 if (!foundSign && AllowLeadingSign) {
281 Int32.FindSign (ref pos, s, nfi, ref foundSign,
283 if (foundSign && AllowLeadingWhite &&
284 !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
293 bool decimalPointFound = false;
298 // Just the same as Int32, but this one adds instead of substract
301 if (!Int32.ValidDigit (s [pos], AllowHexSpecifier)) {
302 if (AllowThousands && Int32.FindOther (ref pos, s, nfi.NumberGroupSeparator))
305 if (!decimalPointFound && AllowDecimalPoint &&
306 Int32.FindOther (ref pos, s, nfi.NumberDecimalSeparator)) {
307 decimalPointFound = true;
312 else if (AllowHexSpecifier) {
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);
320 digitValue = (ulong) (hexDigit - 'A' + 10);
323 // Any number above 32 will do
324 bool can_overflow = number > 0xffff;
326 number = number * 16 + digitValue;
328 if (can_overflow && number < 16)
331 number = checked (number * 16 + digitValue);
333 else if (decimalPointFound) {
335 // Allows decimal point as long as it's only
336 // followed by zeroes.
337 if (s [pos++] != '0') {
339 exc = new OverflowException (Locale.GetText ("Value too large or too small."));
347 number = checked (number * 10 + (ulong) (s [pos++] - '0'));
349 catch (OverflowException) {
351 exc = new OverflowException (Locale.GetText ("Value too large or too small."));
355 } while (pos < s.Length);
360 exc = Int32.GetFormatException ();
364 if (AllowTrailingSign && !foundSign) {
366 Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
368 if (AllowTrailingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
370 if (AllowCurrencySymbol)
371 Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
375 if (AllowCurrencySymbol && !foundCurrency) {
377 Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
379 if (AllowTrailingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
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))
389 if (foundOpenParentheses) {
390 if (pos >= s.Length || s [pos++] != ')') {
392 exc = Int32.GetFormatException ();
395 if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite (ref pos, s, false, tryParse, ref exc))
399 if (pos < s.Length && s [pos] != '\u0000') {
401 exc = Int32.GetFormatException ();
405 // -0 is legal but other negative values are not
406 if (negative && (number > 0)) {
408 exc = new OverflowException (
409 Locale.GetText ("Negative number"));
417 [CLSCompliant (false)]
418 public static ulong Parse (string s, NumberStyles style, IFormatProvider provider)
423 if (!Parse (s, style, provider, false, out res, out exc))
430 [CLSCompliant (false)]
431 public static bool TryParse (string s, out ulong result)
434 if (!Parse (s, true, out result, out exc)) {
442 [CLSCompliant (false)]
443 public static bool TryParse (string s, NumberStyles style, IFormatProvider provider, out ulong result)
446 if (!Parse (s, style, provider, true, out result, out exc)) {
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)