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
,
39 IComparable
, IComparable
<Int64
>
45 public const long MaxValue
= 0x7fffffffffffffff;
46 public const long MinValue
= -9223372036854775808;
48 internal long m_value
;
50 public int CompareTo (object v
)
55 if (!(v
is System
.Int64
))
56 throw new ArgumentException (Locale
.GetText ("Value is not a System.Int64"));
58 if (m_value
== (long) v
)
61 if (m_value
< (long) v
)
67 public override bool Equals (object o
)
69 if (!(o
is System
.Int64
))
72 return ((long) o
) == m_value
;
75 public override int GetHashCode ()
77 return (int)(m_value
& 0xffffffff) ^
(int)(m_value
>> 32);
81 public int CompareTo (long value)
91 public bool Equals (long value)
93 return value == m_value
;
97 internal static bool Parse (string s
, bool tryParse
, out long result
)
103 bool digits_seen
= false;
111 throw new ArgumentNullException ("s");
116 for (i
= 0; i
< len
; i
++){
118 if (!Char
.IsWhiteSpace (c
))
126 throw new FormatException ();
136 for (; i
< len
; i
++){
139 if (c
>= '0' && c
<= '9'){
140 val
= checked (val
* 10 + (c
- '0') * sign
);
143 if (Char
.IsWhiteSpace (c
)){
144 for (i
++; i
< len
; i
++){
145 if (!Char
.IsWhiteSpace (s
[i
]))
149 throw new FormatException ();
156 throw new FormatException ();
163 throw new FormatException ();
169 public static long Parse (string s
, IFormatProvider fp
)
171 return Parse (s
, NumberStyles
.Integer
, fp
);
174 public static long Parse (string s
, NumberStyles style
)
176 return Parse (s
, style
, null);
179 internal static bool Parse (string s
, NumberStyles style
, IFormatProvider fp
, bool tryParse
, out long result
)
187 throw new ArgumentNullException ();
193 throw new FormatException ("Input string was not " +
194 "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 Int32
.CheckStyle (style
);
206 bool AllowCurrencySymbol
= (style
& NumberStyles
.AllowCurrencySymbol
) != 0;
207 bool AllowHexSpecifier
= (style
& NumberStyles
.AllowHexSpecifier
) != 0;
208 bool AllowThousands
= (style
& NumberStyles
.AllowThousands
) != 0;
209 bool AllowDecimalPoint
= (style
& NumberStyles
.AllowDecimalPoint
) != 0;
210 bool AllowParentheses
= (style
& NumberStyles
.AllowParentheses
) != 0;
211 bool AllowTrailingSign
= (style
& NumberStyles
.AllowTrailingSign
) != 0;
212 bool AllowLeadingSign
= (style
& NumberStyles
.AllowLeadingSign
) != 0;
213 bool AllowTrailingWhite
= (style
& NumberStyles
.AllowTrailingWhite
) != 0;
214 bool AllowLeadingWhite
= (style
& NumberStyles
.AllowLeadingWhite
) != 0;
218 if (AllowLeadingWhite
)
219 pos
= Int32
.JumpOverWhite (pos
, s
, true);
221 bool foundOpenParentheses
= false;
222 bool negative
= false;
223 bool foundSign
= false;
224 bool foundCurrency
= false;
227 if (AllowParentheses
&& s
[pos
] == '(') {
228 foundOpenParentheses
= true;
230 negative
= true; // MS always make the number negative when there parentheses
231 // even when NumberFormatInfo.NumberNegativePattern != 0!!!
233 if (AllowLeadingWhite
)
234 pos
= Int32
.JumpOverWhite (pos
, s
, true);
236 if (s
.Substring (pos
, nfi
.NegativeSign
.Length
) == nfi
.NegativeSign
)
240 throw new FormatException ("Input string was not in the correct " +
241 "format: Has Negative Sign.");
242 if (s
.Substring (pos
, nfi
.PositiveSign
.Length
) == nfi
.PositiveSign
)
246 throw new FormatException ("Input string was not in the correct " +
247 "format: Has Positive Sign.");
250 if (AllowLeadingSign
&& !foundSign
) {
252 Int32
.FindSign (ref pos
, s
, nfi
, ref foundSign
, ref negative
);
254 if (AllowLeadingWhite
)
255 pos
= Int32
.JumpOverWhite (pos
, s
, true);
256 if (AllowCurrencySymbol
) {
257 Int32
.FindCurrency (ref pos
, s
, nfi
,
259 if (foundCurrency
&& AllowLeadingWhite
)
260 pos
= Int32
.JumpOverWhite (pos
, s
, true);
265 if (AllowCurrencySymbol
&& !foundCurrency
) {
267 Int32
.FindCurrency (ref pos
, s
, nfi
, ref foundCurrency
);
269 if (AllowLeadingWhite
)
270 pos
= Int32
.JumpOverWhite (pos
, s
, true);
272 if (!foundSign
&& AllowLeadingSign
) {
273 Int32
.FindSign (ref pos
, s
, nfi
, ref foundSign
,
275 if (foundSign
&& AllowLeadingWhite
)
276 pos
= Int32
.JumpOverWhite (pos
, s
, true);
284 bool decimalPointFound
= false;
291 if (!Int32
.ValidDigit (s
[pos
], AllowHexSpecifier
)) {
292 if (AllowThousands
&&
293 (Int32
.FindOther (ref pos
, s
, nfi
.NumberGroupSeparator
)
294 || Int32
.FindOther (ref pos
, s
, nfi
.CurrencyGroupSeparator
)))
297 if (!decimalPointFound
&& AllowDecimalPoint
&&
298 (Int32
.FindOther (ref pos
, s
, nfi
.NumberDecimalSeparator
)
299 || Int32
.FindOther (ref pos
, s
, nfi
.CurrencyDecimalSeparator
))) {
300 decimalPointFound
= true;
306 else if (AllowHexSpecifier
) {
308 hexDigit
= s
[pos
++];
309 if (Char
.IsDigit (hexDigit
))
310 digitValue
= (int) (hexDigit
- '0');
311 else if (Char
.IsLower (hexDigit
))
312 digitValue
= (int) (hexDigit
- 'a' + 10);
314 digitValue
= (int) (hexDigit
- 'A' + 10);
316 ulong unumber
= (ulong)number
;
317 number
= (long)checked(unumber
* 16ul + (ulong)digitValue
);
319 else if (decimalPointFound
) {
321 // Allows decimal point as long as it's only
322 // followed by zeroes.
323 if (s
[pos
++] != '0')
327 throw new OverflowException ("Value too large or too " +
334 // Calculations done as negative
335 // (abs (MinValue) > abs (MaxValue))
338 (long) (s
[pos
++] - '0')
340 } catch (OverflowException
) {
344 throw new OverflowException ("Value too large or too " +
348 } while (pos
< s
.Length
);
355 throw new FormatException ("Input string was not in the correct format: nDigits == 0.");
357 if (AllowTrailingSign
&& !foundSign
) {
359 Int32
.FindSign (ref pos
, s
, nfi
, ref foundSign
, ref negative
);
361 if (AllowTrailingWhite
)
362 pos
= Int32
.JumpOverWhite (pos
, s
, true);
363 if (AllowCurrencySymbol
)
364 Int32
.FindCurrency (ref pos
, s
, nfi
,
369 if (AllowCurrencySymbol
&& !foundCurrency
) {
371 if (nfi
.CurrencyPositivePattern
== 3 && s
[pos
++] != ' ')
375 throw new FormatException ("Input string was not in the correct format: no space between number and currency symbol.");
377 Int32
.FindCurrency (ref pos
, s
, nfi
, ref foundCurrency
);
378 if (foundCurrency
&& pos
< s
.Length
) {
379 if (AllowTrailingWhite
)
380 pos
= Int32
.JumpOverWhite (pos
, s
, true);
381 if (!foundSign
&& AllowTrailingSign
)
382 Int32
.FindSign (ref pos
, s
, nfi
, ref foundSign
,
387 if (AllowTrailingWhite
&& pos
< s
.Length
)
388 pos
= Int32
.JumpOverWhite (pos
, s
, false);
390 if (foundOpenParentheses
) {
391 if (pos
>= s
.Length
|| s
[pos
++] != ')')
395 throw new FormatException ("Input string was not in the correct " +
396 "format: No room for close parens.");
397 if (AllowTrailingWhite
&& pos
< s
.Length
)
398 pos
= Int32
.JumpOverWhite (pos
, s
, false);
401 if (pos
< s
.Length
&& s
[pos
] != '\u0000')
405 throw new FormatException ("Input string was not in the correct format: Did not parse entire string. pos = "
406 + pos
+ " s.Length = " + s
.Length
);
409 if (!negative
&& !AllowHexSpecifier
)
416 public static long Parse (string s
) {
419 Parse (s
, false, out res
);
424 public static long Parse (string s
, NumberStyles style
, IFormatProvider fp
) {
427 Parse (s
, style
, fp
, false, out res
);
433 public static bool TryParse (string s
, out long result
) {
435 return Parse (s
, true, out result
);
443 public static bool TryParse (string s
, NumberStyles style
, IFormatProvider provider
, out long result
) {
445 return Parse (s
, style
, provider
, true, out result
);
454 public override string ToString ()
456 return ToString (null, null);
459 public string ToString (IFormatProvider fp
)
461 return ToString (null, fp
);
464 public string ToString (string format
)
466 return ToString (format
, null);
469 public string ToString (string format
, IFormatProvider fp
)
471 NumberFormatInfo nfi
= NumberFormatInfo
.GetInstance( fp
);
473 // use "G" when format is null or String.Empty
474 if ((format
== null) || (format
.Length
== 0))
477 return IntegerFormatter
.NumberToString (format
, nfi
, m_value
);
480 // =========== IConvertible Methods =========== //
482 public TypeCode
GetTypeCode ()
484 return TypeCode
.Int64
;
487 bool IConvertible
.ToBoolean (IFormatProvider provider
)
489 return System
.Convert
.ToBoolean (m_value
);
492 byte IConvertible
.ToByte (IFormatProvider provider
)
494 return System
.Convert
.ToByte (m_value
);
497 char IConvertible
.ToChar (IFormatProvider provider
)
499 return System
.Convert
.ToChar (m_value
);
502 DateTime IConvertible
.ToDateTime (IFormatProvider provider
)
504 return System
.Convert
.ToDateTime (m_value
);
507 decimal IConvertible
.ToDecimal (IFormatProvider provider
)
509 return System
.Convert
.ToDecimal (m_value
);
512 double IConvertible
.ToDouble (IFormatProvider provider
)
514 return System
.Convert
.ToDouble (m_value
);
517 short IConvertible
.ToInt16 (IFormatProvider provider
)
519 return System
.Convert
.ToInt16 (m_value
);
522 int IConvertible
.ToInt32 (IFormatProvider provider
)
524 return System
.Convert
.ToInt32 (m_value
);
527 long IConvertible
.ToInt64 (IFormatProvider provider
)
529 return System
.Convert
.ToInt64 (m_value
);
532 sbyte IConvertible
.ToSByte (IFormatProvider provider
)
534 return System
.Convert
.ToSByte (m_value
);
537 float IConvertible
.ToSingle (IFormatProvider provider
)
539 return System
.Convert
.ToSingle (m_value
);
542 object IConvertible
.ToType (Type conversionType
, IFormatProvider provider
)
544 return System
.Convert
.ToType (m_value
, conversionType
, provider
);
547 ushort IConvertible
.ToUInt16 (IFormatProvider provider
)
549 return System
.Convert
.ToUInt16 (m_value
);
552 uint IConvertible
.ToUInt32 (IFormatProvider provider
)
554 return System
.Convert
.ToUInt32 (m_value
);
557 ulong IConvertible
.ToUInt64 (IFormatProvider provider
)
559 return System
.Convert
.ToUInt64 (m_value
);