5 // Miguel de Icaza (miguel@ximian.com)
7 // (C) Ximian, Inc. http://www.ximian.com
9 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System
.Globalization
;
32 using System
.Threading
;
38 [System
.Runtime
.InteropServices
.ComVisible (true)]
40 public struct Int64
: IFormattable
, IConvertible
, IComparable
42 , IComparable
<Int64
>, IEquatable
<Int64
>
46 public const long MaxValue
= 0x7fffffffffffffff;
47 public const long MinValue
= -9223372036854775808;
49 internal long m_value
;
51 public int CompareTo (object value)
56 if (!(value is System
.Int64
))
57 throw new ArgumentException (Locale
.GetText ("Value is not a System.Int64"));
59 long lValue
= (long) value;
61 if (m_value
== lValue
)
64 return (m_value
< lValue
) ? -1 : 1;
67 public override bool Equals (object obj
)
69 if (!(obj
is System
.Int64
))
72 return ((long) obj
) == m_value
;
75 public override int GetHashCode ()
77 return (int)(m_value
& 0xffffffff) ^
(int)(m_value
>> 32);
81 public int CompareTo (long value)
91 public bool Equals (long obj
)
93 return obj
== m_value
;
97 internal static bool Parse (string s
, bool tryParse
, out long result
, out Exception exc
)
103 bool digits_seen
= false;
110 exc
= new ArgumentNullException ("s");
117 for (i
= 0; i
< len
; i
++){
119 if (!Char
.IsWhiteSpace (c
))
125 exc
= Int32
.GetFormatException ();
137 for (; i
< len
; i
++){
140 if (c
>= '0' && c
<= '9'){
141 byte d
= (byte) (c
- '0');
143 if (val
> (MaxValue
/10))
146 if (val
== (MaxValue
/10)){
147 if ((d
> (MaxValue
% 10)) && (sign
== 1 || (d
> ((MaxValue
% 10) + 1))))
150 val
= (val
* sign
* 10) - d
;
152 val
= (val
* 10) + d
;
154 if (Int32
.ProcessTrailingWhitespace (tryParse
, s
, i
+ 1, ref exc
)){
164 } else if (!Int32
.ProcessTrailingWhitespace (tryParse
, s
, i
, ref exc
))
170 exc
= Int32
.GetFormatException ();
183 exc
= new OverflowException ("Value is too large");
187 public static long Parse (string s
, IFormatProvider provider
)
189 return Parse (s
, NumberStyles
.Integer
, provider
);
192 public static long Parse (string s
, NumberStyles style
)
194 return Parse (s
, style
, null);
197 internal static bool Parse (string s
, NumberStyles style
, IFormatProvider fp
, bool tryParse
, out long result
, out Exception exc
)
204 exc
= new ArgumentNullException ("s");
210 exc
= new FormatException ("Input string was not " +
211 "in the correct format: s.Length==0.");
215 NumberFormatInfo nfi
;
217 Type typeNFI
= typeof (System
.Globalization
.NumberFormatInfo
);
218 nfi
= (NumberFormatInfo
) fp
.GetFormat (typeNFI
);
221 nfi
= Thread
.CurrentThread
.CurrentCulture
.NumberFormat
;
223 if (!Int32
.CheckStyle (style
, tryParse
, ref exc
))
226 bool AllowCurrencySymbol
= (style
& NumberStyles
.AllowCurrencySymbol
) != 0;
227 bool AllowHexSpecifier
= (style
& NumberStyles
.AllowHexSpecifier
) != 0;
228 bool AllowThousands
= (style
& NumberStyles
.AllowThousands
) != 0;
229 bool AllowDecimalPoint
= (style
& NumberStyles
.AllowDecimalPoint
) != 0;
230 bool AllowParentheses
= (style
& NumberStyles
.AllowParentheses
) != 0;
231 bool AllowTrailingSign
= (style
& NumberStyles
.AllowTrailingSign
) != 0;
232 bool AllowLeadingSign
= (style
& NumberStyles
.AllowLeadingSign
) != 0;
233 bool AllowTrailingWhite
= (style
& NumberStyles
.AllowTrailingWhite
) != 0;
234 bool AllowLeadingWhite
= (style
& NumberStyles
.AllowLeadingWhite
) != 0;
238 if (AllowLeadingWhite
&& !Int32
.JumpOverWhite (ref pos
, s
, true, tryParse
, ref exc
))
241 bool foundOpenParentheses
= false;
242 bool negative
= false;
243 bool foundSign
= false;
244 bool foundCurrency
= false;
247 if (AllowParentheses
&& s
[pos
] == '(') {
248 foundOpenParentheses
= true;
250 negative
= true; // MS always make the number negative when there parentheses
251 // even when NumberFormatInfo.NumberNegativePattern != 0!!!
253 if (AllowLeadingWhite
&& !Int32
.JumpOverWhite (ref pos
, s
, true, tryParse
, ref exc
))
256 if (s
.Substring (pos
, nfi
.NegativeSign
.Length
) == nfi
.NegativeSign
) {
258 exc
= new FormatException ("Input string was not in the correct " +
259 "format: Has Negative Sign.");
262 if (s
.Substring (pos
, nfi
.PositiveSign
.Length
) == nfi
.PositiveSign
) {
264 exc
= new FormatException ("Input string was not in the correct " +
265 "format: Has Positive Sign.");
270 if (AllowLeadingSign
&& !foundSign
) {
272 Int32
.FindSign (ref pos
, s
, nfi
, ref foundSign
, ref negative
);
274 if (AllowLeadingWhite
&& !Int32
.JumpOverWhite (ref pos
, s
, true, tryParse
, ref exc
))
276 if (AllowCurrencySymbol
) {
277 Int32
.FindCurrency (ref pos
, s
, nfi
,
279 if (foundCurrency
&& AllowLeadingWhite
&&
280 !Int32
.JumpOverWhite (ref pos
, s
, true, tryParse
, ref exc
))
286 if (AllowCurrencySymbol
&& !foundCurrency
) {
288 Int32
.FindCurrency (ref pos
, s
, nfi
, ref foundCurrency
);
290 if (AllowLeadingWhite
&& !Int32
.JumpOverWhite (ref pos
, s
, true, tryParse
, ref exc
))
293 if (!foundSign
&& AllowLeadingSign
) {
294 Int32
.FindSign (ref pos
, s
, nfi
, ref foundSign
,
296 if (foundSign
&& AllowLeadingWhite
&&
297 !Int32
.JumpOverWhite (ref pos
, s
, true, tryParse
, ref exc
))
306 bool decimalPointFound
= false;
313 if (!Int32
.ValidDigit (s
[pos
], AllowHexSpecifier
)) {
314 if (AllowThousands
&&
315 (Int32
.FindOther (ref pos
, s
, nfi
.NumberGroupSeparator
)
316 || Int32
.FindOther (ref pos
, s
, nfi
.CurrencyGroupSeparator
)))
319 if (!decimalPointFound
&& AllowDecimalPoint
&&
320 (Int32
.FindOther (ref pos
, s
, nfi
.NumberDecimalSeparator
)
321 || Int32
.FindOther (ref pos
, s
, nfi
.CurrencyDecimalSeparator
))) {
322 decimalPointFound
= true;
328 else if (AllowHexSpecifier
) {
330 hexDigit
= s
[pos
++];
331 if (Char
.IsDigit (hexDigit
))
332 digitValue
= (int) (hexDigit
- '0');
333 else if (Char
.IsLower (hexDigit
))
334 digitValue
= (int) (hexDigit
- 'a' + 10);
336 digitValue
= (int) (hexDigit
- 'A' + 10);
338 ulong unumber
= (ulong)number
;
340 // IMPROVME: We could avoid catching OverflowException
342 number
= (long)checked(unumber
* 16ul + (ulong)digitValue
);
343 } catch (OverflowException e
){
349 else if (decimalPointFound
) {
351 // Allows decimal point as long as it's only
352 // followed by zeroes.
353 if (s
[pos
++] != '0') {
355 exc
= new OverflowException ("Value too large or too " +
364 // Calculations done as negative
365 // (abs (MinValue) > abs (MaxValue))
368 (long) (s
[pos
++] - '0')
370 } catch (OverflowException
) {
372 exc
= new OverflowException ("Value too large or too " +
377 } while (pos
< s
.Length
);
382 exc
= new FormatException ("Input string was not in the correct format: nDigits == 0.");
386 if (AllowTrailingSign
&& !foundSign
) {
388 Int32
.FindSign (ref pos
, s
, nfi
, ref foundSign
, ref negative
);
390 if (AllowTrailingWhite
&& !Int32
.JumpOverWhite (ref pos
, s
, true, tryParse
, ref exc
))
392 if (AllowCurrencySymbol
)
393 Int32
.FindCurrency (ref pos
, s
, nfi
,
398 if (AllowCurrencySymbol
&& !foundCurrency
) {
400 if (nfi
.CurrencyPositivePattern
== 3 && s
[pos
++] != ' ')
404 throw new FormatException ("Input string was not in the correct format: no space between number and currency symbol.");
406 Int32
.FindCurrency (ref pos
, s
, nfi
, ref foundCurrency
);
407 if (foundCurrency
&& pos
< s
.Length
) {
408 if (AllowTrailingWhite
&& !Int32
.JumpOverWhite (ref pos
, s
, true, tryParse
, ref exc
))
410 if (!foundSign
&& AllowTrailingSign
)
411 Int32
.FindSign (ref pos
, s
, nfi
, ref foundSign
,
416 if (AllowTrailingWhite
&& pos
< s
.Length
&& !Int32
.JumpOverWhite (ref pos
, s
, false, tryParse
, ref exc
))
419 if (foundOpenParentheses
) {
420 if (pos
>= s
.Length
|| s
[pos
++] != ')') {
422 exc
= new FormatException ("Input string was not in the correct " +
423 "format: No room for close parens.");
426 if (AllowTrailingWhite
&& pos
< s
.Length
&& !Int32
.JumpOverWhite (ref pos
, s
, false, tryParse
, ref exc
))
430 if (pos
< s
.Length
&& s
[pos
] != '\u0000') {
432 exc
= new FormatException ("Input string was not in the correct format: Did not parse entire string. pos = "
433 + pos
+ " s.Length = " + s
.Length
);
438 if (!negative
&& !AllowHexSpecifier
){
440 number
= checked (-number
);
441 } catch (OverflowException e
){
452 public static long Parse (string s
)
457 if (!Parse (s
, false, out res
, out exc
))
463 public static long Parse (string s
, NumberStyles style
, IFormatProvider provider
)
468 if (!Parse (s
, style
, provider
, false, out res
, out exc
))
475 public static bool TryParse (string s
, out long result
)
478 if (!Parse (s
, true, out result
, out exc
)) {
486 public static bool TryParse (string s
, NumberStyles style
, IFormatProvider provider
, out long result
)
489 if (!Parse (s
, style
, provider
, true, out result
, out exc
)) {
498 public override string ToString ()
500 return NumberFormatter
.NumberToString (m_value
, null);
503 public string ToString (IFormatProvider provider
)
505 return NumberFormatter
.NumberToString (m_value
, provider
);
508 public string ToString (string format
)
510 return ToString (format
, null);
513 public string ToString (string format
, IFormatProvider provider
)
515 return NumberFormatter
.NumberToString (format
, m_value
, provider
);
518 // =========== IConvertible Methods =========== //
520 public TypeCode
GetTypeCode ()
522 return TypeCode
.Int64
;
525 bool IConvertible
.ToBoolean (IFormatProvider provider
)
527 return System
.Convert
.ToBoolean (m_value
);
530 byte IConvertible
.ToByte (IFormatProvider provider
)
532 return System
.Convert
.ToByte (m_value
);
535 char IConvertible
.ToChar (IFormatProvider provider
)
537 return System
.Convert
.ToChar (m_value
);
540 DateTime IConvertible
.ToDateTime (IFormatProvider provider
)
542 return System
.Convert
.ToDateTime (m_value
);
545 decimal IConvertible
.ToDecimal (IFormatProvider provider
)
547 return System
.Convert
.ToDecimal (m_value
);
550 double IConvertible
.ToDouble (IFormatProvider provider
)
552 return System
.Convert
.ToDouble (m_value
);
555 short IConvertible
.ToInt16 (IFormatProvider provider
)
557 return System
.Convert
.ToInt16 (m_value
);
560 int IConvertible
.ToInt32 (IFormatProvider provider
)
562 return System
.Convert
.ToInt32 (m_value
);
565 long IConvertible
.ToInt64 (IFormatProvider provider
)
567 return System
.Convert
.ToInt64 (m_value
);
571 #pragma warning disable 3019
572 [CLSCompliant (false)]
574 sbyte IConvertible
.ToSByte (IFormatProvider provider
)
576 return System
.Convert
.ToSByte (m_value
);
579 #pragma warning restore 3019
582 float IConvertible
.ToSingle (IFormatProvider provider
)
584 return System
.Convert
.ToSingle (m_value
);
587 object IConvertible
.ToType (Type targetType
, IFormatProvider provider
)
589 if (targetType
== null)
590 throw new ArgumentNullException ("targetType");
591 return System
.Convert
.ToType (m_value
, targetType
, provider
, false);
595 #pragma warning disable 3019
596 [CLSCompliant (false)]
598 ushort IConvertible
.ToUInt16 (IFormatProvider provider
)
600 return System
.Convert
.ToUInt16 (m_value
);
603 #pragma warning restore 3019
607 #pragma warning disable 3019
608 [CLSCompliant (false)]
610 uint IConvertible
.ToUInt32 (IFormatProvider provider
)
612 return System
.Convert
.ToUInt32 (m_value
);
615 #pragma warning restore 3019
619 #pragma warning disable 3019
620 [CLSCompliant (false)]
622 ulong IConvertible
.ToUInt64 (IFormatProvider provider
)
624 return System
.Convert
.ToUInt64 (m_value
);
627 #pragma warning restore 3019