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 if (m_value == (long) v)
62 if (m_value < (long) v)
68 public override bool Equals (object o)
70 if (!(o is System.Int64))
73 return ((long) o) == m_value;
76 public override int GetHashCode ()
78 return (int)(m_value & 0xffffffff) ^ (int)(m_value >> 32);
82 public int CompareTo (long value)
92 public bool Equals (long value)
94 return value == m_value;
98 internal static bool Parse (string s, bool tryParse, out long result, out Exception exc)
104 bool digits_seen = false;
111 exc = new ArgumentNullException ("s");
118 for (i = 0; i < len; i++){
120 if (!Char.IsWhiteSpace (c))
126 exc = Int32.GetFormatException ();
138 for (; i < len; i++){
141 if (c >= '0' && c <= '9'){
142 byte d = (byte) (c - '0');
144 if (val > (MaxValue/10))
147 if (val == (MaxValue/10)){
148 if ((d > (MaxValue % 10)) && (sign == 1 || (d > ((MaxValue % 10) + 1))))
151 val = (val * sign * 10) - d;
153 val = (val * 10) + d;
155 if (Int32.ProcessTrailingWhitespace (tryParse, s, i + 1, ref exc)){
165 } else if (!Int32.ProcessTrailingWhitespace (tryParse, s, i, ref exc))
171 exc = Int32.GetFormatException ();
184 exc = new OverflowException ("Value is too large");
188 public static long Parse (string s, IFormatProvider fp)
190 return Parse (s, NumberStyles.Integer, fp);
193 public static long Parse (string s, NumberStyles style)
195 return Parse (s, style, null);
198 internal static bool Parse (string s, NumberStyles style, IFormatProvider fp, bool tryParse, out long result, out Exception exc)
205 exc = new ArgumentNullException ("s");
211 exc = new FormatException ("Input string was not " +
212 "in the correct format: s.Length==0.");
216 NumberFormatInfo nfi;
218 Type typeNFI = typeof (System.Globalization.NumberFormatInfo);
219 nfi = (NumberFormatInfo) fp.GetFormat (typeNFI);
222 nfi = Thread.CurrentThread.CurrentCulture.NumberFormat;
224 if (!Int32.CheckStyle (style, tryParse, ref exc))
227 bool AllowCurrencySymbol = (style & NumberStyles.AllowCurrencySymbol) != 0;
228 bool AllowHexSpecifier = (style & NumberStyles.AllowHexSpecifier) != 0;
229 bool AllowThousands = (style & NumberStyles.AllowThousands) != 0;
230 bool AllowDecimalPoint = (style & NumberStyles.AllowDecimalPoint) != 0;
231 bool AllowParentheses = (style & NumberStyles.AllowParentheses) != 0;
232 bool AllowTrailingSign = (style & NumberStyles.AllowTrailingSign) != 0;
233 bool AllowLeadingSign = (style & NumberStyles.AllowLeadingSign) != 0;
234 bool AllowTrailingWhite = (style & NumberStyles.AllowTrailingWhite) != 0;
235 bool AllowLeadingWhite = (style & NumberStyles.AllowLeadingWhite) != 0;
239 if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
242 bool foundOpenParentheses = false;
243 bool negative = false;
244 bool foundSign = false;
245 bool foundCurrency = false;
248 if (AllowParentheses && s [pos] == '(') {
249 foundOpenParentheses = true;
251 negative = true; // MS always make the number negative when there parentheses
252 // even when NumberFormatInfo.NumberNegativePattern != 0!!!
254 if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
257 if (s.Substring (pos, nfi.NegativeSign.Length) == nfi.NegativeSign) {
259 exc = new FormatException ("Input string was not in the correct " +
260 "format: Has Negative Sign.");
263 if (s.Substring (pos, nfi.PositiveSign.Length) == nfi.PositiveSign) {
265 exc = new FormatException ("Input string was not in the correct " +
266 "format: Has Positive Sign.");
271 if (AllowLeadingSign && !foundSign) {
273 Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
275 if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
277 if (AllowCurrencySymbol) {
278 Int32.FindCurrency (ref pos, s, nfi,
280 if (foundCurrency && AllowLeadingWhite &&
281 !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
287 if (AllowCurrencySymbol && !foundCurrency) {
289 Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
291 if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
294 if (!foundSign && AllowLeadingSign) {
295 Int32.FindSign (ref pos, s, nfi, ref foundSign,
297 if (foundSign && AllowLeadingWhite &&
298 !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
307 bool decimalPointFound = false;
314 if (!Int32.ValidDigit (s [pos], AllowHexSpecifier)) {
315 if (AllowThousands &&
316 (Int32.FindOther (ref pos, s, nfi.NumberGroupSeparator)
317 || Int32.FindOther (ref pos, s, nfi.CurrencyGroupSeparator)))
320 if (!decimalPointFound && AllowDecimalPoint &&
321 (Int32.FindOther (ref pos, s, nfi.NumberDecimalSeparator)
322 || Int32.FindOther (ref pos, s, nfi.CurrencyDecimalSeparator))) {
323 decimalPointFound = true;
329 else if (AllowHexSpecifier) {
331 hexDigit = s [pos++];
332 if (Char.IsDigit (hexDigit))
333 digitValue = (int) (hexDigit - '0');
334 else if (Char.IsLower (hexDigit))
335 digitValue = (int) (hexDigit - 'a' + 10);
337 digitValue = (int) (hexDigit - 'A' + 10);
339 ulong unumber = (ulong)number;
341 // IMPROVME: We could avoid catching OverflowException
343 number = (long)checked(unumber * 16ul + (ulong)digitValue);
344 } catch (OverflowException e){
350 else if (decimalPointFound) {
352 // Allows decimal point as long as it's only
353 // followed by zeroes.
354 if (s [pos++] != '0') {
356 exc = new OverflowException ("Value too large or too " +
365 // Calculations done as negative
366 // (abs (MinValue) > abs (MaxValue))
369 (long) (s [pos++] - '0')
371 } catch (OverflowException) {
373 exc = new OverflowException ("Value too large or too " +
378 } while (pos < s.Length);
383 exc = new FormatException ("Input string was not in the correct format: nDigits == 0.");
387 if (AllowTrailingSign && !foundSign) {
389 Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
391 if (AllowTrailingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
393 if (AllowCurrencySymbol)
394 Int32.FindCurrency (ref pos, s, nfi,
399 if (AllowCurrencySymbol && !foundCurrency) {
401 if (nfi.CurrencyPositivePattern == 3 && s[pos++] != ' ')
405 throw new FormatException ("Input string was not in the correct format: no space between number and currency symbol.");
407 Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
408 if (foundCurrency && pos < s.Length) {
409 if (AllowTrailingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
411 if (!foundSign && AllowTrailingSign)
412 Int32.FindSign (ref pos, s, nfi, ref foundSign,
417 if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite (ref pos, s, false, tryParse, ref exc))
420 if (foundOpenParentheses) {
421 if (pos >= s.Length || s [pos++] != ')') {
423 exc = new FormatException ("Input string was not in the correct " +
424 "format: No room for close parens.");
427 if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite (ref pos, s, false, tryParse, ref exc))
431 if (pos < s.Length && s [pos] != '\u0000') {
433 exc = new FormatException ("Input string was not in the correct format: Did not parse entire string. pos = "
434 + pos + " s.Length = " + s.Length);
439 if (!negative && !AllowHexSpecifier){
441 number = checked (-number);
442 } catch (OverflowException e){
453 public static long Parse (string s)
458 if (!Parse (s, false, out res, out exc))
464 public static long Parse (string s, NumberStyles style, IFormatProvider fp)
469 if (!Parse (s, style, fp, false, out res, out exc))
476 public static bool TryParse (string s, out long result)
479 if (!Parse (s, true, out result, out exc)) {
487 public static bool TryParse (string s, NumberStyles style, IFormatProvider provider, out long result)
490 if (!Parse (s, style, provider, true, out result, out exc)) {
499 public override string ToString ()
501 return NumberFormatter.FormatGeneral (new NumberFormatter.NumberStore (m_value));
504 public string ToString (IFormatProvider fp)
506 return NumberFormatter.FormatGeneral (new NumberFormatter.NumberStore (m_value), fp);
509 public string ToString (string format)
511 return ToString (format, null);
514 public string ToString (string format, IFormatProvider fp)
516 NumberFormatInfo nfi = NumberFormatInfo.GetInstance( fp );
517 return NumberFormatter.NumberToString (format, m_value, nfi);
520 // =========== IConvertible Methods =========== //
522 public TypeCode GetTypeCode ()
524 return TypeCode.Int64;
527 bool IConvertible.ToBoolean (IFormatProvider provider)
529 return System.Convert.ToBoolean (m_value);
532 byte IConvertible.ToByte (IFormatProvider provider)
534 return System.Convert.ToByte (m_value);
537 char IConvertible.ToChar (IFormatProvider provider)
539 return System.Convert.ToChar (m_value);
542 DateTime IConvertible.ToDateTime (IFormatProvider provider)
544 return System.Convert.ToDateTime (m_value);
547 decimal IConvertible.ToDecimal (IFormatProvider provider)
549 return System.Convert.ToDecimal (m_value);
552 double IConvertible.ToDouble (IFormatProvider provider)
554 return System.Convert.ToDouble (m_value);
557 short IConvertible.ToInt16 (IFormatProvider provider)
559 return System.Convert.ToInt16 (m_value);
562 int IConvertible.ToInt32 (IFormatProvider provider)
564 return System.Convert.ToInt32 (m_value);
567 long IConvertible.ToInt64 (IFormatProvider provider)
569 return System.Convert.ToInt64 (m_value);
572 sbyte IConvertible.ToSByte (IFormatProvider provider)
574 return System.Convert.ToSByte (m_value);
577 float IConvertible.ToSingle (IFormatProvider provider)
579 return System.Convert.ToSingle (m_value);
582 object IConvertible.ToType (Type conversionType, IFormatProvider provider)
584 return System.Convert.ToType (m_value, conversionType, provider);
587 ushort IConvertible.ToUInt16 (IFormatProvider provider)
589 return System.Convert.ToUInt16 (m_value);
592 uint IConvertible.ToUInt32 (IFormatProvider provider)
594 return System.Convert.ToUInt32 (m_value);
597 ulong IConvertible.ToUInt64 (IFormatProvider provider)
599 return System.Convert.ToUInt64 (m_value);