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 public struct Int64 : IFormattable, IConvertible, IComparable
39 , IComparable<Int64>, IEquatable <Int64>
43 public const long MaxValue = 0x7fffffffffffffff;
44 public const long MinValue = -9223372036854775808;
46 internal long m_value;
48 public int CompareTo (object v)
53 if (!(v is System.Int64))
54 throw new ArgumentException (Locale.GetText ("Value is not a System.Int64"));
56 if (m_value == (long) v)
59 if (m_value < (long) v)
65 public override bool Equals (object o)
67 if (!(o is System.Int64))
70 return ((long) o) == m_value;
73 public override int GetHashCode ()
75 return (int)(m_value & 0xffffffff) ^ (int)(m_value >> 32);
79 public int CompareTo (long value)
89 public bool Equals (long value)
91 return value == m_value;
95 internal static bool Parse (string s, bool tryParse, out long result, out Exception exc)
101 bool digits_seen = false;
108 exc = new ArgumentNullException ("s");
115 for (i = 0; i < len; i++){
117 if (!Char.IsWhiteSpace (c))
123 exc = Int32.GetFormatException ();
135 for (; i < len; i++){
138 if (c >= '0' && c <= '9'){
139 val = checked (val * 10 + (c - '0') * sign);
142 if (Char.IsWhiteSpace (c)){
143 for (i++; i < len; i++){
144 if (!Char.IsWhiteSpace (s [i])) {
146 exc = Int32.GetFormatException ();
153 exc = Int32.GetFormatException ();
160 exc = Int32.GetFormatException ();
168 public static long Parse (string s, IFormatProvider fp)
170 return Parse (s, NumberStyles.Integer, fp);
173 public static long Parse (string s, NumberStyles style)
175 return Parse (s, style, null);
178 internal static bool Parse (string s, NumberStyles style, IFormatProvider fp, bool tryParse, out long result, out Exception exc)
185 exc = new ArgumentNullException ("s");
191 exc = new FormatException ("Input string was not " +
192 "in the correct format: s.Length==0.");
196 NumberFormatInfo nfi;
198 Type typeNFI = typeof (System.Globalization.NumberFormatInfo);
199 nfi = (NumberFormatInfo) fp.GetFormat (typeNFI);
202 nfi = Thread.CurrentThread.CurrentCulture.NumberFormat;
204 if (!Int32.CheckStyle (style, tryParse, ref exc))
207 bool AllowCurrencySymbol = (style & NumberStyles.AllowCurrencySymbol) != 0;
208 bool AllowHexSpecifier = (style & NumberStyles.AllowHexSpecifier) != 0;
209 bool AllowThousands = (style & NumberStyles.AllowThousands) != 0;
210 bool AllowDecimalPoint = (style & NumberStyles.AllowDecimalPoint) != 0;
211 bool AllowParentheses = (style & NumberStyles.AllowParentheses) != 0;
212 bool AllowTrailingSign = (style & NumberStyles.AllowTrailingSign) != 0;
213 bool AllowLeadingSign = (style & NumberStyles.AllowLeadingSign) != 0;
214 bool AllowTrailingWhite = (style & NumberStyles.AllowTrailingWhite) != 0;
215 bool AllowLeadingWhite = (style & NumberStyles.AllowLeadingWhite) != 0;
219 if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
222 bool foundOpenParentheses = false;
223 bool negative = false;
224 bool foundSign = false;
225 bool foundCurrency = false;
228 if (AllowParentheses && s [pos] == '(') {
229 foundOpenParentheses = true;
231 negative = true; // MS always make the number negative when there parentheses
232 // even when NumberFormatInfo.NumberNegativePattern != 0!!!
234 if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
237 if (s.Substring (pos, nfi.NegativeSign.Length) == nfi.NegativeSign) {
239 exc = new FormatException ("Input string was not in the correct " +
240 "format: Has Negative Sign.");
243 if (s.Substring (pos, nfi.PositiveSign.Length) == nfi.PositiveSign) {
245 exc = new FormatException ("Input string was not in the correct " +
246 "format: Has Positive Sign.");
251 if (AllowLeadingSign && !foundSign) {
253 Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
255 if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
257 if (AllowCurrencySymbol) {
258 Int32.FindCurrency (ref pos, s, nfi,
260 if (foundCurrency && AllowLeadingWhite &&
261 !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
267 if (AllowCurrencySymbol && !foundCurrency) {
269 Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
271 if (AllowLeadingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
274 if (!foundSign && AllowLeadingSign) {
275 Int32.FindSign (ref pos, s, nfi, ref foundSign,
277 if (foundSign && AllowLeadingWhite &&
278 !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
287 bool decimalPointFound = false;
294 if (!Int32.ValidDigit (s [pos], AllowHexSpecifier)) {
295 if (AllowThousands &&
296 (Int32.FindOther (ref pos, s, nfi.NumberGroupSeparator)
297 || Int32.FindOther (ref pos, s, nfi.CurrencyGroupSeparator)))
300 if (!decimalPointFound && AllowDecimalPoint &&
301 (Int32.FindOther (ref pos, s, nfi.NumberDecimalSeparator)
302 || Int32.FindOther (ref pos, s, nfi.CurrencyDecimalSeparator))) {
303 decimalPointFound = true;
309 else if (AllowHexSpecifier) {
311 hexDigit = s [pos++];
312 if (Char.IsDigit (hexDigit))
313 digitValue = (int) (hexDigit - '0');
314 else if (Char.IsLower (hexDigit))
315 digitValue = (int) (hexDigit - 'a' + 10);
317 digitValue = (int) (hexDigit - 'A' + 10);
319 ulong unumber = (ulong)number;
320 number = (long)checked(unumber * 16ul + (ulong)digitValue);
322 else if (decimalPointFound) {
324 // Allows decimal point as long as it's only
325 // followed by zeroes.
326 if (s [pos++] != '0') {
328 exc = new OverflowException ("Value too large or too " +
337 // Calculations done as negative
338 // (abs (MinValue) > abs (MaxValue))
341 (long) (s [pos++] - '0')
343 } catch (OverflowException) {
345 exc = new OverflowException ("Value too large or too " +
350 } while (pos < s.Length);
355 exc = new FormatException ("Input string was not in the correct format: nDigits == 0.");
359 if (AllowTrailingSign && !foundSign) {
361 Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
363 if (AllowTrailingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
365 if (AllowCurrencySymbol)
366 Int32.FindCurrency (ref pos, s, nfi,
371 if (AllowCurrencySymbol && !foundCurrency) {
373 if (nfi.CurrencyPositivePattern == 3 && s[pos++] != ' ')
377 throw new FormatException ("Input string was not in the correct format: no space between number and currency symbol.");
379 Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
380 if (foundCurrency && pos < s.Length) {
381 if (AllowTrailingWhite && !Int32.JumpOverWhite (ref pos, s, true, tryParse, ref exc))
383 if (!foundSign && AllowTrailingSign)
384 Int32.FindSign (ref pos, s, nfi, ref foundSign,
389 if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite (ref pos, s, false, tryParse, ref exc))
392 if (foundOpenParentheses) {
393 if (pos >= s.Length || s [pos++] != ')') {
395 exc = new FormatException ("Input string was not in the correct " +
396 "format: No room for close parens.");
399 if (AllowTrailingWhite && pos < s.Length && !Int32.JumpOverWhite (ref pos, s, false, tryParse, ref exc))
403 if (pos < s.Length && s [pos] != '\u0000') {
405 exc = new FormatException ("Input string was not in the correct format: Did not parse entire string. pos = "
406 + pos + " s.Length = " + s.Length);
411 if (!negative && !AllowHexSpecifier)
412 number = checked (-number);
418 public static long Parse (string s)
423 if (!Parse (s, false, out res, out exc))
429 public static long Parse (string s, NumberStyles style, IFormatProvider fp)
434 if (!Parse (s, style, fp, false, out res, out exc))
441 public static bool TryParse (string s, out long result)
444 if (!Parse (s, true, out result, out exc)) {
452 public static bool TryParse (string s, NumberStyles style, IFormatProvider provider, out long result)
455 if (!Parse (s, style, provider, true, out result, out exc)) {
464 public override string ToString ()
466 return NumberFormatter.FormatGeneral (new NumberFormatter.NumberStore (m_value));
469 public string ToString (IFormatProvider fp)
471 return NumberFormatter.FormatGeneral (new NumberFormatter.NumberStore (m_value), fp);
474 public string ToString (string format)
476 return ToString (format, null);
479 public string ToString (string format, IFormatProvider fp)
481 NumberFormatInfo nfi = NumberFormatInfo.GetInstance( fp );
482 return NumberFormatter.NumberToString (format, m_value, nfi);
485 // =========== IConvertible Methods =========== //
487 public TypeCode GetTypeCode ()
489 return TypeCode.Int64;
492 bool IConvertible.ToBoolean (IFormatProvider provider)
494 return System.Convert.ToBoolean (m_value);
497 byte IConvertible.ToByte (IFormatProvider provider)
499 return System.Convert.ToByte (m_value);
502 char IConvertible.ToChar (IFormatProvider provider)
504 return System.Convert.ToChar (m_value);
507 DateTime IConvertible.ToDateTime (IFormatProvider provider)
509 return System.Convert.ToDateTime (m_value);
512 decimal IConvertible.ToDecimal (IFormatProvider provider)
514 return System.Convert.ToDecimal (m_value);
517 double IConvertible.ToDouble (IFormatProvider provider)
519 return System.Convert.ToDouble (m_value);
522 short IConvertible.ToInt16 (IFormatProvider provider)
524 return System.Convert.ToInt16 (m_value);
527 int IConvertible.ToInt32 (IFormatProvider provider)
529 return System.Convert.ToInt32 (m_value);
532 long IConvertible.ToInt64 (IFormatProvider provider)
534 return System.Convert.ToInt64 (m_value);
537 sbyte IConvertible.ToSByte (IFormatProvider provider)
539 return System.Convert.ToSByte (m_value);
542 float IConvertible.ToSingle (IFormatProvider provider)
544 return System.Convert.ToSingle (m_value);
547 object IConvertible.ToType (Type conversionType, IFormatProvider provider)
549 return System.Convert.ToType (m_value, conversionType, provider);
552 ushort IConvertible.ToUInt16 (IFormatProvider provider)
554 return System.Convert.ToUInt16 (m_value);
557 uint IConvertible.ToUInt32 (IFormatProvider provider)
559 return System.Convert.ToUInt32 (m_value);
562 ulong IConvertible.ToUInt64 (IFormatProvider provider)
564 return System.Convert.ToUInt64 (m_value);