5 // Miguel de Icaza (miguel@ximian.com)
6 // Marek Safar (marek.safar@gmail.com)
8 // (C) Ximian, Inc. http://www.ximian.com
9 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
10 // Copyright (C) 2012 Xamarin Inc (http://www.xamarin.com)
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System.Globalization;
33 using System.Threading;
38 [System.Runtime.InteropServices.ComVisible (true)]
39 public struct Int64 : IFormattable, IConvertible, IComparable, IComparable<Int64>, IEquatable <Int64>
42 public const long MaxValue = 0x7fffffffffffffff;
43 public const long MinValue = -9223372036854775808;
45 internal long m_value;
47 public int CompareTo (object value)
52 if (!(value is System.Int64))
53 throw new ArgumentException (Locale.GetText ("Value is not a System.Int64"));
55 long lValue = (long) value;
57 if (m_value == lValue)
60 return (m_value < lValue) ? -1 : 1;
63 public override bool Equals (object obj)
65 if (!(obj is System.Int64))
68 return ((long) obj) == m_value;
71 public override int GetHashCode ()
73 return (int)(m_value & 0xffffffff) ^ (int)(m_value >> 32);
76 public int CompareTo (long value)
86 public bool Equals (long obj)
88 return obj == m_value;
91 internal static bool Parse (string s, bool tryParse, out long result, out Exception exc)
96 bool digits_seen = false;
100 NumberFormatInfo nfi = Thread.CurrentThread.CurrentCulture.NumberFormat;
104 exc = new ArgumentNullException ("s");
111 for (i = 0; i < len; i++){
113 if (!Char.IsWhiteSpace (c))
119 exc = Int32.GetFormatException ();
123 if (String.Compare (s, i, nfi.PositiveSign, 0, nfi.PositiveSign.Length) == 0)
124 i += nfi.PositiveSign.Length;
125 else if (String.Compare (s, i, nfi.NegativeSign, 0, nfi.NegativeSign.Length) == 0) {
127 i += nfi.NegativeSign.Length;
130 for (; i < len; i++){
133 if (c >= '0' && c <= '9'){
134 byte d = (byte) (c - '0');
136 if (val > (MaxValue/10))
139 if (val == (MaxValue/10)){
140 if ((d > (MaxValue % 10)) && (sign == 1 || (d > ((MaxValue % 10) + 1))))
143 val = (val * sign * 10) - d;
145 val = (val * 10) + d;
147 if (Int32.ProcessTrailingWhitespace (tryParse, s, i + 1, ref exc)){
156 } else if (!Int32.ProcessTrailingWhitespace (tryParse, s, i, ref exc))
161 exc = Int32.GetFormatException ();
174 exc = new OverflowException ("Value is too large");
178 public static long Parse (string s, IFormatProvider provider)
180 return Parse (s, NumberStyles.Integer, provider);
183 public static long Parse (string s, NumberStyles style)
185 return Parse (s, style, null);
188 internal static bool Parse (string s, NumberStyles style, IFormatProvider fp, bool tryParse, out long result, out Exception exc)
195 exc = new ArgumentNullException ("s");
201 exc = Int32.GetFormatException ();
205 NumberFormatInfo nfi = null;
207 Type typeNFI = typeof (System.Globalization.NumberFormatInfo);
208 nfi = (NumberFormatInfo) fp.GetFormat (typeNFI);
211 nfi = Thread.CurrentThread.CurrentCulture.NumberFormat;
213 if (!Int32.CheckStyle (style, tryParse, ref exc))
216 bool AllowCurrencySymbol = (style & NumberStyles.AllowCurrencySymbol) != 0;
217 bool AllowHexSpecifier = (style & NumberStyles.AllowHexSpecifier) != 0;
218 bool AllowThousands = (style & NumberStyles.AllowThousands) != 0;
219 bool AllowDecimalPoint = (style & NumberStyles.AllowDecimalPoint) != 0;
220 bool AllowParentheses = (style & NumberStyles.AllowParentheses) != 0;
221 bool AllowTrailingSign = (style & NumberStyles.AllowTrailingSign) != 0;
222 bool AllowLeadingSign = (style & NumberStyles.AllowLeadingSign) != 0;
223 bool AllowTrailingWhite = (style & NumberStyles.AllowTrailingWhite) != 0;
224 bool AllowLeadingWhite = (style & NumberStyles.AllowLeadingWhite) != 0;
225 bool AllowExponent = (style & NumberStyles.AllowExponent) != 0;
229 if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
232 bool foundOpenParentheses = false;
233 bool negative = false;
234 bool foundSign = false;
235 bool foundCurrency = false;
238 if (AllowParentheses && s [pos] == '(') {
239 foundOpenParentheses = true;
241 negative = true; // MS always make the number negative when there parentheses
242 // even when NumberFormatInfo.NumberNegativePattern != 0!!!
244 if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
247 if (s.Substring (pos, nfi.NegativeSign.Length) == nfi.NegativeSign) {
249 exc = Int32.GetFormatException ();
253 if (s.Substring (pos, nfi.PositiveSign.Length) == nfi.PositiveSign) {
255 exc = Int32.GetFormatException ();
260 if (AllowLeadingSign && !foundSign) {
262 Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
264 if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
266 if (AllowCurrencySymbol) {
267 Int32.FindCurrency (ref pos, s, nfi,
269 if (foundCurrency && AllowLeadingWhite &&
270 !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
276 if (AllowCurrencySymbol && !foundCurrency) {
278 Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
280 if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
283 if (!foundSign && AllowLeadingSign) {
284 Int32.FindSign (ref pos, s, nfi, ref foundSign,
286 if (foundSign && AllowLeadingWhite &&
287 !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
296 bool decimalPointFound = false;
304 if (!Int32.ValidDigit (s [pos], AllowHexSpecifier)) {
305 if (AllowThousands &&
306 (Int32.FindOther (ref pos, s, nfi.NumberGroupSeparator)
307 || Int32.FindOther (ref pos, s, nfi.CurrencyGroupSeparator)))
310 if (!decimalPointFound && AllowDecimalPoint &&
311 (Int32.FindOther (ref pos, s, nfi.NumberDecimalSeparator)
312 || Int32.FindOther (ref pos, s, nfi.CurrencyDecimalSeparator))) {
313 decimalPointFound = true;
319 if (AllowHexSpecifier) {
321 hexDigit = s [pos++];
322 if (Char.IsDigit (hexDigit))
323 digitValue = (int) (hexDigit - '0');
324 else if (Char.IsLower (hexDigit))
325 digitValue = (int) (hexDigit - 'a' + 10);
327 digitValue = (int) (hexDigit - 'A' + 10);
329 ulong unumber = (ulong)number;
331 // IMPROVME: We could avoid catching OverflowException
333 number = (long)checked(unumber * 16ul + (ulong)digitValue);
334 } catch (OverflowException e){
340 else if (decimalPointFound) {
342 // Allows decimal point as long as it's only
343 // followed by zeroes.
344 if (s [pos++] != '0') {
346 exc = new OverflowException ("Value too large or too " +
355 // Calculations done as negative
356 // (abs (MinValue) > abs (MaxValue))
359 (long) (s [pos++] - '0')
361 } catch (OverflowException) {
363 exc = new OverflowException ("Value too large or too " +
368 } while (pos < s.Length);
373 exc = Int32.GetFormatException ();
378 if (Int32.FindExponent (ref pos, s, ref exponent, tryParse, ref exc) && exc != null)
381 if (AllowTrailingSign && !foundSign) {
383 Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
384 if (foundSign && pos < s.Length) {
385 if (AllowTrailingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
390 if (AllowCurrencySymbol && !foundCurrency) {
391 if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite (ref pos, s, false, tryParse, ref exc))
395 Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
396 if (foundCurrency && pos < s.Length) {
397 if (AllowTrailingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
399 if (!foundSign && AllowTrailingSign)
400 Int32.FindSign (ref pos, s, nfi, ref foundSign,
405 if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite (ref pos, s, false, tryParse, ref exc))
408 if (foundOpenParentheses) {
409 if (pos >= s.Length || s [pos++] != ')') {
411 exc = Int32.GetFormatException ();
414 if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite (ref pos, s, false, tryParse, ref exc))
418 if (pos < s.Length && s [pos] != '\u0000') {
420 exc = Int32.GetFormatException ();
424 if (!negative && !AllowHexSpecifier){
426 number = checked (-number);
427 } catch (OverflowException e){
434 // result *= 10^exponent
436 // Reduce the risk of throwing an overflow exc
437 double res = checked (Math.Pow (10, exponent) * number);
438 if (res < Int32.MinValue || res > Int32.MaxValue) {
440 exc = new OverflowException ("Value too large or too small.");
451 public static long Parse (string s)
456 if (!Parse (s, false, out res, out exc))
462 public static long Parse (string s, NumberStyles style, IFormatProvider provider)
467 if (!Parse (s, style, provider, false, out res, out exc))
473 public static bool TryParse (string s, out long result)
476 if (!Parse (s, true, out result, out exc)) {
484 public static bool TryParse (string s, NumberStyles style, IFormatProvider provider, out long result)
487 if (!Parse (s, style, provider, true, out result, out exc)) {
495 public override string ToString ()
497 return NumberFormatter.NumberToString (m_value, null);
500 public string ToString (IFormatProvider provider)
502 return NumberFormatter.NumberToString (m_value, provider);
505 public string ToString (string format)
507 return ToString (format, null);
510 public string ToString (string format, IFormatProvider provider)
512 return NumberFormatter.NumberToString (format, m_value, provider);
515 // =========== IConvertible Methods =========== //
517 public TypeCode GetTypeCode ()
519 return TypeCode.Int64;
522 bool IConvertible.ToBoolean (IFormatProvider provider)
524 return System.Convert.ToBoolean (m_value);
527 byte IConvertible.ToByte (IFormatProvider provider)
529 return System.Convert.ToByte (m_value);
532 char IConvertible.ToChar (IFormatProvider provider)
534 return System.Convert.ToChar (m_value);
537 DateTime IConvertible.ToDateTime (IFormatProvider provider)
539 return System.Convert.ToDateTime (m_value);
542 decimal IConvertible.ToDecimal (IFormatProvider provider)
544 return System.Convert.ToDecimal (m_value);
547 double IConvertible.ToDouble (IFormatProvider provider)
549 return System.Convert.ToDouble (m_value);
552 short IConvertible.ToInt16 (IFormatProvider provider)
554 return System.Convert.ToInt16 (m_value);
557 int IConvertible.ToInt32 (IFormatProvider provider)
559 return System.Convert.ToInt32 (m_value);
562 long IConvertible.ToInt64 (IFormatProvider provider)
567 sbyte IConvertible.ToSByte (IFormatProvider provider)
569 return System.Convert.ToSByte (m_value);
572 float IConvertible.ToSingle (IFormatProvider provider)
574 return System.Convert.ToSingle (m_value);
577 object IConvertible.ToType (Type targetType, IFormatProvider provider)
579 if (targetType == null)
580 throw new ArgumentNullException ("targetType");
581 return System.Convert.ToType (m_value, targetType, provider, false);
584 ushort IConvertible.ToUInt16 (IFormatProvider provider)
586 return System.Convert.ToUInt16 (m_value);
589 uint IConvertible.ToUInt32 (IFormatProvider provider)
591 return System.Convert.ToUInt32 (m_value);
594 ulong IConvertible.ToUInt64 (IFormatProvider provider)
596 return System.Convert.ToUInt64 (m_value);