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;
37 [System.Runtime.InteropServices.ComVisible (true)]
38 public struct Int64 : IFormattable, IConvertible, IComparable, IComparable<Int64>, IEquatable <Int64>
41 public const long MaxValue = 0x7fffffffffffffff;
42 public const long MinValue = -9223372036854775808;
44 internal long m_value;
46 public int CompareTo (object value)
51 if (!(value is System.Int64))
52 throw new ArgumentException (Locale.GetText ("Value is not a System.Int64"));
54 long lValue = (long) value;
56 if (m_value == lValue)
59 return (m_value < lValue) ? -1 : 1;
62 public override bool Equals (object obj)
64 if (!(obj is System.Int64))
67 return ((long) obj) == m_value;
70 public override int GetHashCode ()
72 return (int)(m_value & 0xffffffff) ^ (int)(m_value >> 32);
75 public int CompareTo (long value)
85 public bool Equals (long obj)
87 return obj == m_value;
90 internal static bool Parse (string s, bool tryParse, out long result, out Exception exc)
96 bool digits_seen = false;
103 exc = new ArgumentNullException ("s");
110 for (i = 0; i < len; i++){
112 if (!Char.IsWhiteSpace (c))
118 exc = Int32.GetFormatException ();
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)){
157 } else if (!Int32.ProcessTrailingWhitespace (tryParse, s, i, ref exc))
163 exc = Int32.GetFormatException ();
176 exc = new OverflowException ("Value is too large");
180 public static long Parse (string s, IFormatProvider provider)
182 return Parse (s, NumberStyles.Integer, provider);
185 public static long Parse (string s, NumberStyles style)
187 return Parse (s, style, null);
190 internal static bool Parse (string s, NumberStyles style, IFormatProvider fp, bool tryParse, out long result, out Exception exc)
197 exc = new ArgumentNullException ("s");
203 exc = new FormatException ("Input string was not " +
204 "in the correct format: s.Length==0.");
208 NumberFormatInfo nfi;
210 Type typeNFI = typeof (System.Globalization.NumberFormatInfo);
211 nfi = (NumberFormatInfo) fp.GetFormat (typeNFI);
214 nfi = Thread.CurrentThread.CurrentCulture.NumberFormat;
216 if (!Int32.CheckStyle (style, tryParse, ref exc))
219 bool AllowCurrencySymbol = (style & NumberStyles.AllowCurrencySymbol) != 0;
220 bool AllowHexSpecifier = (style & NumberStyles.AllowHexSpecifier) != 0;
221 bool AllowThousands = (style & NumberStyles.AllowThousands) != 0;
222 bool AllowDecimalPoint = (style & NumberStyles.AllowDecimalPoint) != 0;
223 bool AllowParentheses = (style & NumberStyles.AllowParentheses) != 0;
224 bool AllowTrailingSign = (style & NumberStyles.AllowTrailingSign) != 0;
225 bool AllowLeadingSign = (style & NumberStyles.AllowLeadingSign) != 0;
226 bool AllowTrailingWhite = (style & NumberStyles.AllowTrailingWhite) != 0;
227 bool AllowLeadingWhite = (style & NumberStyles.AllowLeadingWhite) != 0;
231 if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
234 bool foundOpenParentheses = false;
235 bool negative = false;
236 bool foundSign = false;
237 bool foundCurrency = false;
240 if (AllowParentheses && s [pos] == '(') {
241 foundOpenParentheses = true;
243 negative = true; // MS always make the number negative when there parentheses
244 // even when NumberFormatInfo.NumberNegativePattern != 0!!!
246 if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
249 if (s.Substring (pos, nfi.NegativeSign.Length) == nfi.NegativeSign) {
251 exc = new FormatException ("Input string was not in the correct " +
252 "format: Has Negative Sign.");
255 if (s.Substring (pos, nfi.PositiveSign.Length) == nfi.PositiveSign) {
257 exc = new FormatException ("Input string was not in the correct " +
258 "format: Has Positive Sign.");
263 if (AllowLeadingSign && !foundSign) {
265 Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
267 if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
269 if (AllowCurrencySymbol) {
270 Int32.FindCurrency (ref pos, s, nfi,
272 if (foundCurrency && AllowLeadingWhite &&
273 !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
279 if (AllowCurrencySymbol && !foundCurrency) {
281 Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
283 if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
286 if (!foundSign && AllowLeadingSign) {
287 Int32.FindSign (ref pos, s, nfi, ref foundSign,
289 if (foundSign && AllowLeadingWhite &&
290 !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
299 bool decimalPointFound = false;
306 if (!Int32.ValidDigit (s [pos], AllowHexSpecifier)) {
307 if (AllowThousands &&
308 (Int32.FindOther (ref pos, s, nfi.NumberGroupSeparator)
309 || Int32.FindOther (ref pos, s, nfi.CurrencyGroupSeparator)))
312 if (!decimalPointFound && AllowDecimalPoint &&
313 (Int32.FindOther (ref pos, s, nfi.NumberDecimalSeparator)
314 || Int32.FindOther (ref pos, s, nfi.CurrencyDecimalSeparator))) {
315 decimalPointFound = true;
321 else if (AllowHexSpecifier) {
323 hexDigit = s [pos++];
324 if (Char.IsDigit (hexDigit))
325 digitValue = (int) (hexDigit - '0');
326 else if (Char.IsLower (hexDigit))
327 digitValue = (int) (hexDigit - 'a' + 10);
329 digitValue = (int) (hexDigit - 'A' + 10);
331 ulong unumber = (ulong)number;
333 // IMPROVME: We could avoid catching OverflowException
335 number = (long)checked(unumber * 16ul + (ulong)digitValue);
336 } catch (OverflowException e){
342 else if (decimalPointFound) {
344 // Allows decimal point as long as it's only
345 // followed by zeroes.
346 if (s [pos++] != '0') {
348 exc = new OverflowException ("Value too large or too " +
357 // Calculations done as negative
358 // (abs (MinValue) > abs (MaxValue))
361 (long) (s [pos++] - '0')
363 } catch (OverflowException) {
365 exc = new OverflowException ("Value too large or too " +
370 } while (pos < s.Length);
375 exc = new FormatException ("Input string was not in the correct format: nDigits == 0.");
379 if (AllowTrailingSign && !foundSign) {
381 Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
383 if (AllowTrailingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
385 if (AllowCurrencySymbol)
386 Int32.FindCurrency (ref pos, s, nfi,
391 if (AllowCurrencySymbol && !foundCurrency) {
393 if (nfi.CurrencyPositivePattern == 3 && s[pos++] != ' ')
397 throw new FormatException ("Input string was not in the correct format: no space between number and currency symbol.");
399 Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
400 if (foundCurrency && pos < s.Length) {
401 if (AllowTrailingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
403 if (!foundSign && AllowTrailingSign)
404 Int32.FindSign (ref pos, s, nfi, ref foundSign,
409 if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite (ref pos, s, false, tryParse, ref exc))
412 if (foundOpenParentheses) {
413 if (pos >= s.Length || s [pos++] != ')') {
415 exc = new FormatException ("Input string was not in the correct " +
416 "format: No room for close parens.");
419 if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite (ref pos, s, false, tryParse, ref exc))
423 if (pos < s.Length && s [pos] != '\u0000') {
425 exc = new FormatException ("Input string was not in the correct format: Did not parse entire string. pos = "
426 + pos + " s.Length = " + s.Length);
431 if (!negative && !AllowHexSpecifier){
433 number = checked (-number);
434 } catch (OverflowException e){
445 public static long Parse (string s)
450 if (!Parse (s, false, out res, out exc))
456 public static long Parse (string s, NumberStyles style, IFormatProvider provider)
461 if (!Parse (s, style, provider, false, out res, out exc))
467 public static bool TryParse (string s, out long result)
470 if (!Parse (s, true, out result, out exc)) {
478 public static bool TryParse (string s, NumberStyles style, IFormatProvider provider, out long result)
481 if (!Parse (s, style, provider, true, out result, out exc)) {
489 public override string ToString ()
491 return NumberFormatter.NumberToString (m_value, null);
494 public string ToString (IFormatProvider provider)
496 return NumberFormatter.NumberToString (m_value, provider);
499 public string ToString (string format)
501 return ToString (format, null);
504 public string ToString (string format, IFormatProvider provider)
506 return NumberFormatter.NumberToString (format, m_value, provider);
509 // =========== IConvertible Methods =========== //
511 public TypeCode GetTypeCode ()
513 return TypeCode.Int64;
516 bool IConvertible.ToBoolean (IFormatProvider provider)
518 return System.Convert.ToBoolean (m_value);
521 byte IConvertible.ToByte (IFormatProvider provider)
523 return System.Convert.ToByte (m_value);
526 char IConvertible.ToChar (IFormatProvider provider)
528 return System.Convert.ToChar (m_value);
531 DateTime IConvertible.ToDateTime (IFormatProvider provider)
533 return System.Convert.ToDateTime (m_value);
536 decimal IConvertible.ToDecimal (IFormatProvider provider)
538 return System.Convert.ToDecimal (m_value);
541 double IConvertible.ToDouble (IFormatProvider provider)
543 return System.Convert.ToDouble (m_value);
546 short IConvertible.ToInt16 (IFormatProvider provider)
548 return System.Convert.ToInt16 (m_value);
551 int IConvertible.ToInt32 (IFormatProvider provider)
553 return System.Convert.ToInt32 (m_value);
556 long IConvertible.ToInt64 (IFormatProvider provider)
558 return System.Convert.ToInt64 (m_value);
561 sbyte IConvertible.ToSByte (IFormatProvider provider)
563 return System.Convert.ToSByte (m_value);
566 float IConvertible.ToSingle (IFormatProvider provider)
568 return System.Convert.ToSingle (m_value);
571 object IConvertible.ToType (Type targetType, IFormatProvider provider)
573 if (targetType == null)
574 throw new ArgumentNullException ("targetType");
575 return System.Convert.ToType (m_value, targetType, provider, false);
578 ushort IConvertible.ToUInt16 (IFormatProvider provider)
580 return System.Convert.ToUInt16 (m_value);
583 uint IConvertible.ToUInt32 (IFormatProvider provider)
585 return System.Convert.ToUInt32 (m_value);
588 ulong IConvertible.ToUInt64 (IFormatProvider provider)
590 return System.Convert.ToUInt64 (m_value);