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
)