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 public static long Parse (string s, NumberStyles style, IFormatProvider fp)
120 throw new ArgumentNullException ();
123 throw new FormatException ("Input string was not " +
124 "in the correct format: s.Length==0.");
126 NumberFormatInfo nfi;
128 Type typeNFI = typeof (System.Globalization.NumberFormatInfo);
129 nfi = (NumberFormatInfo) fp.GetFormat (typeNFI);
132 nfi = Thread.CurrentThread.CurrentCulture.NumberFormat;
134 Int32.CheckStyle (style);
136 bool AllowCurrencySymbol = (style & NumberStyles.AllowCurrencySymbol) != 0;
137 bool AllowExponent = (style & NumberStyles.AllowExponent) != 0;
138 bool AllowHexSpecifier = (style & NumberStyles.AllowHexSpecifier) != 0;
139 bool AllowThousands = (style & NumberStyles.AllowThousands) != 0;
140 bool AllowDecimalPoint = (style & NumberStyles.AllowDecimalPoint) != 0;
141 bool AllowParentheses = (style & NumberStyles.AllowParentheses) != 0;
142 bool AllowTrailingSign = (style & NumberStyles.AllowTrailingSign) != 0;
143 bool AllowLeadingSign = (style & NumberStyles.AllowLeadingSign) != 0;
144 bool AllowTrailingWhite = (style & NumberStyles.AllowTrailingWhite) != 0;
145 bool AllowLeadingWhite = (style & NumberStyles.AllowLeadingWhite) != 0;
149 if (AllowLeadingWhite)
150 pos = Int32.JumpOverWhite (pos, s, true);
152 bool foundOpenParentheses = false;
153 bool negative = false;
154 bool foundSign = false;
155 bool foundCurrency = false;
158 if (AllowParentheses && s [pos] == '(') {
159 foundOpenParentheses = true;
161 negative = true; // MS always make the number negative when there parentheses
162 // even when NumberFormatInfo.NumberNegativePattern != 0!!!
164 if (AllowLeadingWhite)
165 pos = Int32.JumpOverWhite (pos, s, true);
167 if (s.Substring (pos, nfi.NegativeSign.Length) == nfi.NegativeSign)
168 throw new FormatException ("Input string was not in the correct " +
169 "format: Has Negative Sign.");
170 if (s.Substring (pos, nfi.PositiveSign.Length) == nfi.PositiveSign)
171 throw new FormatException ("Input string was not in the correct " +
172 "format: Has Positive Sign.");
175 if (AllowLeadingSign && !foundSign) {
177 Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
179 if (AllowLeadingWhite)
180 pos = Int32.JumpOverWhite (pos, s, true);
181 if (AllowCurrencySymbol) {
182 Int32.FindCurrency (ref pos, s, nfi,
184 if (foundCurrency && AllowLeadingWhite)
185 pos = Int32.JumpOverWhite (pos, s, true);
190 if (AllowCurrencySymbol && !foundCurrency) {
192 Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
194 if (AllowLeadingWhite)
195 pos = Int32.JumpOverWhite (pos, s, true);
197 if (!foundSign && AllowLeadingSign) {
198 Int32.FindSign (ref pos, s, nfi, ref foundSign,
200 if (foundSign && AllowLeadingWhite)
201 pos = Int32.JumpOverWhite (pos, s, true);
209 bool decimalPointFound = false;
216 if (!Int32.ValidDigit (s [pos], AllowHexSpecifier)) {
217 if (AllowThousands &&
218 (Int32.FindOther (ref pos, s, nfi.NumberGroupSeparator)
219 || Int32.FindOther (ref pos, s, nfi.CurrencyGroupSeparator)))
222 if (!decimalPointFound && AllowDecimalPoint &&
223 (Int32.FindOther (ref pos, s, nfi.NumberDecimalSeparator)
224 || Int32.FindOther (ref pos, s, nfi.CurrencyDecimalSeparator))) {
225 decimalPointFound = true;
231 else if (AllowHexSpecifier) {
233 hexDigit = s [pos++];
234 if (Char.IsDigit (hexDigit))
235 digitValue = (int) (hexDigit - '0');
236 else if (Char.IsLower (hexDigit))
237 digitValue = (int) (hexDigit - 'a' + 10);
239 digitValue = (int) (hexDigit - 'A' + 10);
241 number = checked (number * 16 - digitValue);
243 else if (decimalPointFound) {
245 // Allows decimal point as long as it's only
246 // followed by zeroes.
247 if (s [pos++] != '0')
248 throw new OverflowException ("Value too large or too " +
255 // Calculations done as negative
256 // (abs (MinValue) > abs (MaxValue))
259 (long) (s [pos++] - '0')
261 } catch (OverflowException) {
262 throw new OverflowException ("Value too large or too " +
266 } while (pos < s.Length);
270 throw new FormatException ("Input string was not in the correct format: nDigits == 0.");
272 if (AllowTrailingSign && !foundSign) {
274 Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
276 if (AllowTrailingWhite)
277 pos = Int32.JumpOverWhite (pos, s, true);
278 if (AllowCurrencySymbol)
279 Int32.FindCurrency (ref pos, s, nfi,
284 if (AllowCurrencySymbol && !foundCurrency) {
286 if (nfi.CurrencyPositivePattern == 3 && s[pos++] != ' ')
287 throw new FormatException ("Input string was not in the correct format: no space between number and currency symbol.");
289 Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
290 if (foundCurrency && pos < s.Length) {
291 if (AllowTrailingWhite)
292 pos = Int32.JumpOverWhite (pos, s, true);
293 if (!foundSign && AllowTrailingSign)
294 Int32.FindSign (ref pos, s, nfi, ref foundSign,
299 if (AllowTrailingWhite && pos < s.Length)
300 pos = Int32.JumpOverWhite (pos, s, false);
302 if (foundOpenParentheses) {
303 if (pos >= s.Length || s [pos++] != ')')
304 throw new FormatException ("Input string was not in the correct " +
305 "format: No room for close parens.");
306 if (AllowTrailingWhite && pos < s.Length)
307 pos = Int32.JumpOverWhite (pos, s, false);
310 if (pos < s.Length && s [pos] != '\u0000')
311 throw new FormatException ("Input string was not in the correct format: Did not parse entire string. pos = "
312 + pos + " s.Length = " + s.Length);
321 public override string ToString ()
323 return ToString (null, null);
326 public string ToString (IFormatProvider fp)
328 return ToString (null, fp);
331 public string ToString (string format)
333 return ToString (format, null);
336 public string ToString (string format, IFormatProvider fp)
338 NumberFormatInfo nfi = NumberFormatInfo.GetInstance( fp );
340 if ( format == null )
343 return IntegerFormatter.NumberToString (format, nfi, value);
346 // =========== IConvertible Methods =========== //
348 public TypeCode GetTypeCode ()
350 return TypeCode.Int64;
353 bool IConvertible.ToBoolean (IFormatProvider provider)
355 return System.Convert.ToBoolean (value);
358 byte IConvertible.ToByte (IFormatProvider provider)
360 return System.Convert.ToByte (value);
363 char IConvertible.ToChar (IFormatProvider provider)
365 return System.Convert.ToChar (value);
368 DateTime IConvertible.ToDateTime (IFormatProvider provider)
370 return System.Convert.ToDateTime (value);
373 decimal IConvertible.ToDecimal (IFormatProvider provider)
375 return System.Convert.ToDecimal (value);
378 double IConvertible.ToDouble (IFormatProvider provider)
380 return System.Convert.ToDouble (value);
383 short IConvertible.ToInt16 (IFormatProvider provider)
385 return System.Convert.ToInt16 (value);
388 int IConvertible.ToInt32 (IFormatProvider provider)
390 return System.Convert.ToInt32 (value);
393 long IConvertible.ToInt64 (IFormatProvider provider)
395 return System.Convert.ToInt64 (value);
398 [CLSCompliant (false)]
399 sbyte IConvertible.ToSByte (IFormatProvider provider)
401 return System.Convert.ToSByte (value);
404 float IConvertible.ToSingle (IFormatProvider provider)
406 return System.Convert.ToSingle (value);
409 object IConvertible.ToType (Type conversionType, IFormatProvider provider)
411 return System.Convert.ToType (value, conversionType, provider);
414 [CLSCompliant (false)]
415 ushort IConvertible.ToUInt16 (IFormatProvider provider)
417 return System.Convert.ToUInt16 (value);
420 [CLSCompliant (false)]
421 uint IConvertible.ToUInt32 (IFormatProvider provider)
423 return System.Convert.ToUInt32 (value);
426 [CLSCompliant (false)]
427 ulong IConvertible.ToUInt64 (IFormatProvider provider)
429 return System.Convert.ToUInt64 (value);