5 // Miguel de Icaza (miguel@ximian.com)
7 // (C) Ximian, Inc. http://www.ximian.com
10 using System.Globalization;
11 using System.Threading;
16 public struct Int64 : IComparable, IFormattable, IConvertible {
18 public const long MaxValue = 0x7fffffffffffffff;
19 public const long MinValue = -9223372036854775808;
23 public int CompareTo (object v)
28 if (!(v is System.Int64))
29 throw new ArgumentException (Locale.GetText ("Value is not a System.Int64"));
31 if (value == (long) v)
40 public override bool Equals (object o)
42 if (!(o is System.Int64))
45 return ((long) o) == value;
48 public override int GetHashCode ()
50 return (int)(value & 0xffffffff) ^ (int)(value >> 32);
53 public static long Parse (string s)
59 bool digits_seen = false;
62 throw new ArgumentNullException (Locale.GetText ("s is null"));
67 for (i = 0; i < len; i++){
69 if (!Char.IsWhiteSpace (c))
74 throw new FormatException ();
87 if (c >= '0' && c <= '9'){
88 val = checked (val * 10 + (c - '0') * sign);
91 if (Char.IsWhiteSpace (c)){
92 for (i++; i < len; i++){
93 if (!Char.IsWhiteSpace (s [i]))
94 throw new FormatException ();
98 throw new FormatException ();
102 throw new FormatException ();
107 public static long Parse (string s, IFormatProvider fp)
109 return Parse (s, NumberStyles.Integer, fp);
112 public static long Parse (string s, NumberStyles style)
114 return Parse (s, style, null);
117 private delegate bool IsAnything (Char c);
119 private static void CheckStyle (NumberStyles style)
121 if ((style & NumberStyles.AllowHexSpecifier) != 0 &&
122 ((style | ~NumberStyles.AllowLeadingWhite) != 0 ||
123 (style | ~NumberStyles.AllowTrailingWhite) != 0))
124 throw new ArgumentException (
125 "With AllowHexSpecifier only " +
126 "AllowLeadingWhite and AllowTrailingWhite " +
130 private static int JumpOverWhite (int pos, string s, bool excp)
132 while (pos < s.Length && Char.IsWhiteSpace (s [pos]))
135 if (excp && pos >= s.Length)
136 throw new FormatException ("Input string was not in the correct format.");
141 private static void FindSign (ref int pos, string s, NumberFormatInfo nfi,
142 ref bool foundSign, ref bool negative)
144 if ((pos + nfi.NegativeSign.Length) <= s.Length &&
145 s.Substring (pos, nfi.NegativeSign.Length) == nfi.NegativeSign) {
148 pos += nfi.NegativeSign.Length;
150 else if ((pos + nfi.PositiveSign.Length) < s.Length &&
151 s.Substring (pos, nfi.PositiveSign.Length) == nfi.PositiveSign) {
153 pos += nfi.PositiveSign.Length;
158 private static void FindCurrency (ref int pos,
160 NumberFormatInfo nfi,
161 ref bool foundCurrency)
163 if ((pos + nfi.CurrencySymbol.Length) <= s.Length &&
164 s.Substring (pos, nfi.CurrencySymbol.Length) == nfi.CurrencySymbol) {
165 foundCurrency = true;
166 pos += nfi.CurrencySymbol.Length;
170 private static bool FindOther (ref int pos,
174 if ((pos + other.Length) <= s.Length &&
175 s.Substring (pos, other.Length) == other) {
183 public static long Parse (string s, NumberStyles style, IFormatProvider fp)
186 throw new ArgumentNullException ();
189 throw new FormatException ("Input string was not " +
190 "in the correct format.");
192 NumberFormatInfo nfi;
194 Type typeNFI = typeof (System.Globalization.NumberFormatInfo);
195 nfi = (NumberFormatInfo) fp.GetFormat (typeNFI);
198 nfi = Thread.CurrentThread.CurrentCulture.NumberFormat;
202 bool AllowCurrencySymbol = (style & NumberStyles.AllowCurrencySymbol) != 0;
203 bool AllowExponent = (style & NumberStyles.AllowExponent) != 0;
204 bool AllowHexSpecifier = (style & NumberStyles.AllowHexSpecifier) != 0;
205 bool AllowThousands = (style & NumberStyles.AllowThousands) != 0;
206 bool AllowDecimalPoint = (style & NumberStyles.AllowDecimalPoint) != 0;
207 bool AllowParentheses = (style & NumberStyles.AllowParentheses) != 0;
208 bool AllowTrailingSign = (style & NumberStyles.AllowTrailingSign) != 0;
209 bool AllowLeadingSign = (style & NumberStyles.AllowLeadingSign) != 0;
210 bool AllowTrailingWhite = (style & NumberStyles.AllowTrailingWhite) != 0;
211 bool AllowLeadingWhite = (style & NumberStyles.AllowLeadingWhite) != 0;
215 if (AllowLeadingWhite)
216 pos = JumpOverWhite (pos, s, true);
218 bool foundOpenParentheses = false;
219 bool negative = false;
220 bool foundSign = false;
221 bool foundCurrency = false;
224 if (AllowParentheses && s [pos] == '(') {
225 foundOpenParentheses = true;
227 negative = true; // MS always make the number negative when there parentheses
228 // even when NumberFormatInfo.NumberNegativePattern != 0!!!
230 if (AllowLeadingWhite)
231 pos = JumpOverWhite (pos, s, true);
233 if (s.Substring (pos, nfi.NegativeSign.Length) == nfi.NegativeSign)
234 throw new FormatException ("Input string was not in the correct " +
236 if (s.Substring (pos, nfi.PositiveSign.Length) == nfi.PositiveSign)
237 throw new FormatException ("Input string was not in the correct " +
241 if (AllowLeadingSign && !foundSign) {
243 FindSign (ref pos, s, nfi, ref foundSign, ref negative);
245 if (AllowLeadingWhite)
246 pos = JumpOverWhite (pos, s, true);
247 if (AllowCurrencySymbol) {
248 FindCurrency (ref pos, s, nfi,
250 if (foundCurrency && AllowLeadingWhite)
251 pos = JumpOverWhite (pos, s, true);
256 if (AllowCurrencySymbol && !foundCurrency) {
258 FindCurrency (ref pos, s, nfi, ref foundCurrency);
260 if (AllowLeadingWhite)
261 pos = JumpOverWhite (pos, s, true);
263 if (!foundSign && AllowLeadingSign) {
264 FindSign (ref pos, s, nfi, ref foundSign,
266 if (foundSign && AllowLeadingWhite)
267 pos = JumpOverWhite (pos, s, true);
273 IsAnything validDigit;
274 if (AllowHexSpecifier)
275 validDigit = new IsAnything (Char.IsNumber);
277 validDigit = new IsAnything (Char.IsDigit);
281 bool decimalPointFound = false;
288 if (!validDigit (s [pos])) {
289 if (AllowThousands &&
290 FindOther (ref pos, s, nfi.NumberGroupSeparator))
293 if (!decimalPointFound && AllowDecimalPoint &&
294 FindOther (ref pos, s, nfi.NumberDecimalSeparator)) {
295 decimalPointFound = true;
301 else if (AllowHexSpecifier) {
302 hexDigit = s [pos++];
303 if (Char.IsDigit (hexDigit))
304 digitValue = (int) (hexDigit - '0');
305 else if (Char.IsLower (hexDigit))
306 digitValue = (int) (hexDigit - 'a');
308 digitValue = (int) (hexDigit - 'A');
310 number = checked (number * 16 - digitValue);
312 else if (decimalPointFound) {
314 // Allows decimal point as long as it's only
315 // followed by zeroes.
316 if (s [pos++] != '0')
317 throw new OverflowException ("Value too large or too " +
324 // Calculations done as negative
325 // (abs (MinValue) > abs (MaxValue))
328 (long) (s [pos++] - '0')
330 } catch (OverflowException) {
331 throw new OverflowException ("Value too large or too " +
335 } while (pos < s.Length);
339 throw new FormatException ("Input string was not in the correct format.");
341 if (AllowTrailingSign && !foundSign) {
343 FindSign (ref pos, s, nfi, ref foundSign, ref negative);
345 if (AllowTrailingWhite)
346 pos = JumpOverWhite (pos, s, true);
347 if (AllowCurrencySymbol)
348 FindCurrency (ref pos, s, nfi,
353 if (AllowCurrencySymbol && !foundCurrency) {
355 FindCurrency (ref pos, s, nfi, ref foundCurrency);
357 if (AllowTrailingWhite)
358 pos = JumpOverWhite (pos, s, true);
359 if (!foundSign && AllowTrailingSign)
360 FindSign (ref pos, s, nfi, ref foundSign,
365 if (AllowTrailingWhite && pos < s.Length)
366 pos = JumpOverWhite (pos, s, false);
368 if (foundOpenParentheses) {
369 if (pos >= s.Length || s [pos++] != ')')
370 throw new FormatException ("Input string was not in the correct " +
372 if (AllowTrailingWhite && pos < s.Length)
373 pos = JumpOverWhite (pos, s, false);
377 throw new FormatException ("Input string was not in the correct format.");
386 public override string ToString ()
388 return ToString (null, null);
391 public string ToString (IFormatProvider fp)
393 return ToString (null, fp);
396 public string ToString (string format)
398 return ToString (format, null);
401 public string ToString (string format, IFormatProvider fp)
403 NumberFormatInfo nfi = NumberFormatInfo.GetInstance( fp );
405 if ( format == null )
408 return IntegerFormatter.NumberToString (format, nfi, value);
411 // =========== IConvertible Methods =========== //
413 public TypeCode GetTypeCode ()
415 return TypeCode.Int64;
418 public bool ToBoolean (IFormatProvider provider)
420 return System.Convert.ToBoolean (value);
423 public byte ToByte (IFormatProvider provider)
425 return System.Convert.ToByte (value);
428 public char ToChar (IFormatProvider provider)
430 return System.Convert.ToChar (value);
433 public DateTime ToDateTime (IFormatProvider provider)
435 return System.Convert.ToDateTime (value);
438 public decimal ToDecimal (IFormatProvider provider)
440 return System.Convert.ToDecimal (value);
443 public double ToDouble (IFormatProvider provider)
445 return System.Convert.ToDouble (value);
448 public short ToInt16 (IFormatProvider provider)
450 return System.Convert.ToInt16 (value);
453 public int ToInt32 (IFormatProvider provider)
455 return System.Convert.ToInt32 (value);
458 public long ToInt64 (IFormatProvider provider)
460 return System.Convert.ToInt64 (value);
463 [CLSCompliant (false)]
464 public sbyte ToSByte (IFormatProvider provider)
466 return System.Convert.ToSByte (value);
469 public float ToSingle (IFormatProvider provider)
471 return System.Convert.ToSingle (value);
474 public object ToType (Type conversionType, IFormatProvider provider)
476 return System.Convert.ToType (value, conversionType, provider);
479 [CLSCompliant (false)]
480 public ushort ToUInt16 (IFormatProvider provider)
482 return System.Convert.ToUInt16 (value);
485 [CLSCompliant (false)]
486 public uint ToUInt32 (IFormatProvider provider)
488 return System.Convert.ToUInt32 (value);
491 [CLSCompliant (false)]
492 public ulong ToUInt64 (IFormatProvider provider)
494 return System.Convert.ToUInt64 (value);