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 v)
56 if (!(v is System.Int64))
57 throw new ArgumentException (Locale.GetText ("Value is not a System.Int64"));
59 long value = (long) v;
64 return (m_value < value) ? -1 : 1;
67 public override bool Equals (object o)
69 if (!(o is System.Int64))
72 return ((long) o) == 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 value)
93 return value == 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 fp)
189 return Parse (s, NumberStyles.Integer, fp);
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 fp)
468 if (!Parse (s, style, fp, 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 fp)
515 return NumberFormatter.NumberToString (format, m_value, fp);
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);
570 sbyte IConvertible.ToSByte (IFormatProvider provider)
572 return System.Convert.ToSByte (m_value);
575 float IConvertible.ToSingle (IFormatProvider provider)
577 return System.Convert.ToSingle (m_value);
580 object IConvertible.ToType (Type conversionType, IFormatProvider provider)
582 return System.Convert.ToType (m_value, conversionType, provider);
585 ushort IConvertible.ToUInt16 (IFormatProvider provider)
587 return System.Convert.ToUInt16 (m_value);
590 uint IConvertible.ToUInt32 (IFormatProvider provider)
592 return System.Convert.ToUInt32 (m_value);
595 ulong IConvertible.ToUInt64 (IFormatProvider provider)
597 return System.Convert.ToUInt64 (m_value);