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'){
143 val = val * 10 + (c - '0') * sign;
151 val = checked (val * 10 + (c - '0') * sign);
154 if (Char.IsWhiteSpace (c)){
155 for (i++; i < len; i++){
156 if (!Char.IsWhiteSpace (s [i])) {
158 exc = Int32.GetFormatException ();
165 exc = Int32.GetFormatException ();
172 exc = Int32.GetFormatException ();
180 public static long Parse (string s, IFormatProvider fp)
182 return Parse (s, NumberStyles.Integer, fp);
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 fp)
461 if (!Parse (s, style, fp, false, out res, out exc))
468 public static bool TryParse (string s, out long result)
471 if (!Parse (s, true, out result, out exc)) {
479 public static bool TryParse (string s, NumberStyles style, IFormatProvider provider, out long result)
482 if (!Parse (s, style, provider, true, out result, out exc)) {
491 public override string ToString ()
493 return NumberFormatter.FormatGeneral (new NumberFormatter.NumberStore (m_value));
496 public string ToString (IFormatProvider fp)
498 return NumberFormatter.FormatGeneral (new NumberFormatter.NumberStore (m_value), fp);
501 public string ToString (string format)
503 return ToString (format, null);
506 public string ToString (string format, IFormatProvider fp)
508 NumberFormatInfo nfi = NumberFormatInfo.GetInstance( fp );
509 return NumberFormatter.NumberToString (format, m_value, nfi);
512 // =========== IConvertible Methods =========== //
514 public TypeCode GetTypeCode ()
516 return TypeCode.Int64;
519 bool IConvertible.ToBoolean (IFormatProvider provider)
521 return System.Convert.ToBoolean (m_value);
524 byte IConvertible.ToByte (IFormatProvider provider)
526 return System.Convert.ToByte (m_value);
529 char IConvertible.ToChar (IFormatProvider provider)
531 return System.Convert.ToChar (m_value);
534 DateTime IConvertible.ToDateTime (IFormatProvider provider)
536 return System.Convert.ToDateTime (m_value);
539 decimal IConvertible.ToDecimal (IFormatProvider provider)
541 return System.Convert.ToDecimal (m_value);
544 double IConvertible.ToDouble (IFormatProvider provider)
546 return System.Convert.ToDouble (m_value);
549 short IConvertible.ToInt16 (IFormatProvider provider)
551 return System.Convert.ToInt16 (m_value);
554 int IConvertible.ToInt32 (IFormatProvider provider)
556 return System.Convert.ToInt32 (m_value);
559 long IConvertible.ToInt64 (IFormatProvider provider)
561 return System.Convert.ToInt64 (m_value);
564 sbyte IConvertible.ToSByte (IFormatProvider provider)
566 return System.Convert.ToSByte (m_value);
569 float IConvertible.ToSingle (IFormatProvider provider)
571 return System.Convert.ToSingle (m_value);
574 object IConvertible.ToType (Type conversionType, IFormatProvider provider)
576 return System.Convert.ToType (m_value, conversionType, provider);
579 ushort IConvertible.ToUInt16 (IFormatProvider provider)
581 return System.Convert.ToUInt16 (m_value);
584 uint IConvertible.ToUInt32 (IFormatProvider provider)
586 return System.Convert.ToUInt32 (m_value);
589 ulong IConvertible.ToUInt64 (IFormatProvider provider)
591 return System.Convert.ToUInt64 (m_value);