5 // Miguel de Icaza (miguel@ximian.com)
7 // (C) Ximian, Inc. http://www.ximian.com
10 using System.Globalization;
11 using System.Threading;
17 public struct UInt64 : IComparable, IFormattable, IConvertible {
18 public const ulong MaxValue = 0xffffffffffffffff;
19 public const ulong MinValue = 0;
23 public int CompareTo (object v)
28 if (!(v is System.UInt64))
29 throw new ArgumentException (Locale.GetText ("Value is not a System.UInt64"));
31 if (value == (ulong) v)
34 if (value < (ulong) v)
40 public override bool Equals (object o)
42 if (!(o is System.UInt64))
45 return ((ulong) o) == value;
48 public override int GetHashCode ()
50 return (int)(value & 0xffffffff) ^ (int)(value >> 32);
54 public static ulong Parse (string s)
56 return Parse (s, NumberStyles.Integer, null);
60 public static ulong Parse (string s, IFormatProvider fp)
62 return Parse (s, NumberStyles.Integer, fp);
66 public static ulong Parse (string s, NumberStyles style)
68 return Parse (s, style, null);
71 private static void CheckStyle (NumberStyles style)
73 if ((style & NumberStyles.AllowHexSpecifier) != 0) {
74 NumberStyles ne = style ^ NumberStyles.AllowHexSpecifier;
75 if ((ne & NumberStyles.AllowLeadingWhite) != 0)
76 ne ^= NumberStyles.AllowLeadingWhite;
77 if ((ne & NumberStyles.AllowTrailingWhite) != 0)
78 ne ^= NumberStyles.AllowTrailingWhite;
80 throw new ArgumentException (
81 "With AllowHexSpecifier only " +
82 "AllowLeadingWhite and AllowTrailingWhite " +
87 private static int JumpOverWhite (int pos, string s, bool excp)
89 while (pos < s.Length && Char.IsWhiteSpace (s [pos]))
92 if (excp && pos >= s.Length)
93 throw new FormatException ("Input string was not in the correct format.");
98 private static void FindSign (ref int pos, string s, NumberFormatInfo nfi,
99 ref bool foundSign, ref bool negative)
101 if ((pos + nfi.NegativeSign.Length) <= s.Length &&
102 s.Substring (pos, nfi.NegativeSign.Length) == nfi.NegativeSign) {
105 pos += nfi.NegativeSign.Length;
107 else if ((pos + nfi.PositiveSign.Length) < s.Length &&
108 s.Substring (pos, nfi.PositiveSign.Length) == nfi.PositiveSign) {
110 pos += nfi.PositiveSign.Length;
115 private static void FindCurrency (ref int pos,
117 NumberFormatInfo nfi,
118 ref bool foundCurrency)
120 if ((pos + nfi.CurrencySymbol.Length) <= s.Length &&
121 s.Substring (pos, nfi.CurrencySymbol.Length) == nfi.CurrencySymbol) {
122 foundCurrency = true;
123 pos += nfi.CurrencySymbol.Length;
127 private static bool FindOther (ref int pos,
131 if ((pos + other.Length) <= s.Length &&
132 s.Substring (pos, other.Length) == other) {
140 private static bool ValidDigit (char e, bool allowHex)
143 return Char.IsDigit (e) || (e >= 'A' && e <= 'F') || (e >= 'a' && e <= 'f');
145 return Char.IsDigit (e);
148 [CLSCompliant(false)]
149 public static ulong Parse (string s, NumberStyles style, IFormatProvider fp)
152 throw new ArgumentNullException ();
155 throw new FormatException ("Input string was not in the correct format.");
157 NumberFormatInfo nfi;
159 Type typeNFI = typeof (System.Globalization.NumberFormatInfo);
160 nfi = (NumberFormatInfo) fp.GetFormat (typeNFI);
163 nfi = Thread.CurrentThread.CurrentCulture.NumberFormat;
167 bool AllowCurrencySymbol = (style & NumberStyles.AllowCurrencySymbol) != 0;
168 bool AllowExponent = (style & NumberStyles.AllowExponent) != 0;
169 bool AllowHexSpecifier = (style & NumberStyles.AllowHexSpecifier) != 0;
170 bool AllowThousands = (style & NumberStyles.AllowThousands) != 0;
171 bool AllowDecimalPoint = (style & NumberStyles.AllowDecimalPoint) != 0;
172 bool AllowParentheses = (style & NumberStyles.AllowParentheses) != 0;
173 bool AllowTrailingSign = (style & NumberStyles.AllowTrailingSign) != 0;
174 bool AllowLeadingSign = (style & NumberStyles.AllowLeadingSign) != 0;
175 bool AllowTrailingWhite = (style & NumberStyles.AllowTrailingWhite) != 0;
176 bool AllowLeadingWhite = (style & NumberStyles.AllowLeadingWhite) != 0;
180 if (AllowLeadingWhite)
181 pos = JumpOverWhite (pos, s, true);
183 bool foundOpenParentheses = false;
184 bool negative = false;
185 bool foundSign = false;
186 bool foundCurrency = false;
189 if (AllowParentheses && s [pos] == '(') {
190 foundOpenParentheses = true;
192 negative = true; // MS always make the number negative when there parentheses
193 // even when NumberFormatInfo.NumberNegativePattern != 0!!!
195 if (AllowLeadingWhite)
196 pos = JumpOverWhite (pos, s, true);
198 if (s.Substring (pos, nfi.NegativeSign.Length) == nfi.NegativeSign)
199 throw new FormatException ("Input string was not in the correct format.");
200 if (s.Substring (pos, nfi.PositiveSign.Length) == nfi.PositiveSign)
201 throw new FormatException ("Input string was not in the correct format.");
204 if (AllowLeadingSign && !foundSign) {
206 FindSign (ref pos, s, nfi, ref foundSign, ref negative);
208 if (AllowLeadingWhite)
209 pos = JumpOverWhite (pos, s, true);
210 if (AllowCurrencySymbol) {
211 FindCurrency (ref pos, s, nfi,
213 if (foundCurrency && AllowLeadingWhite)
214 pos = JumpOverWhite (pos, s, true);
219 if (AllowCurrencySymbol && !foundCurrency) {
221 FindCurrency (ref pos, s, nfi, ref foundCurrency);
223 if (AllowLeadingWhite)
224 pos = JumpOverWhite (pos, s, true);
226 if (!foundSign && AllowLeadingSign) {
227 FindSign (ref pos, s, nfi, ref foundSign,
229 if (foundSign && AllowLeadingWhite)
230 pos = JumpOverWhite (pos, s, true);
238 bool decimalPointFound = false;
243 // Just the same as Int32, but this one adds instead of substract
246 if (!ValidDigit (s [pos], AllowHexSpecifier)) {
247 if (AllowThousands &&
248 FindOther (ref pos, s, nfi.NumberGroupSeparator))
251 if (!decimalPointFound && AllowDecimalPoint &&
252 FindOther (ref pos, s, nfi.NumberDecimalSeparator)) {
253 decimalPointFound = true;
259 else if (AllowHexSpecifier) {
261 hexDigit = s [pos++];
262 if (Char.IsDigit (hexDigit))
263 digitValue = (ulong) (hexDigit - '0');
264 else if (Char.IsLower (hexDigit))
265 digitValue = (ulong) (hexDigit - 'a' + 10);
267 digitValue = (ulong) (hexDigit - 'A' + 10);
269 number = checked (number * 16 + digitValue);
271 else if (decimalPointFound) {
273 // Allows decimal point as long as it's only
274 // followed by zeroes.
275 if (s [pos++] != '0')
276 throw new OverflowException ("Value too large or too small.");
284 (ulong) (s [pos++] - '0')
286 } catch (OverflowException) {
287 throw new OverflowException ("Value too large or too small.");
290 } while (pos < s.Length);
294 throw new FormatException ("Input string was not in the correct format.");
296 if (AllowTrailingSign && !foundSign) {
298 FindSign (ref pos, s, nfi, ref foundSign, ref negative);
300 if (AllowTrailingWhite)
301 pos = JumpOverWhite (pos, s, true);
302 if (AllowCurrencySymbol)
303 FindCurrency (ref pos, s, nfi,
308 if (AllowCurrencySymbol && !foundCurrency) {
310 FindCurrency (ref pos, s, nfi, ref foundCurrency);
312 if (AllowTrailingWhite)
313 pos = JumpOverWhite (pos, s, true);
314 if (!foundSign && AllowTrailingSign)
315 FindSign (ref pos, s, nfi, ref foundSign,
320 if (AllowTrailingWhite && pos < s.Length)
321 pos = JumpOverWhite (pos, s, false);
323 if (foundOpenParentheses) {
324 if (pos >= s.Length || s [pos++] != ')')
325 throw new FormatException ("Input string was not in the correct " +
327 if (AllowTrailingWhite && pos < s.Length)
328 pos = JumpOverWhite (pos, s, false);
332 throw new FormatException ("Input string was not in the correct format.");
335 throw new OverflowException ( "Value too large or too small.");
340 public override string ToString ()
342 return ToString (null, null);
345 public string ToString (IFormatProvider fp)
347 return ToString (null, fp);
350 public string ToString (string format)
352 return ToString (format, null);
355 public string ToString (string format, IFormatProvider fp)
357 NumberFormatInfo nfi = NumberFormatInfo.GetInstance( fp );
359 if ( format == null )
362 return IntegerFormatter.NumberToString(format, nfi, value);
365 // =========== IConvertible Methods =========== //
367 public TypeCode GetTypeCode ()
369 return TypeCode.UInt64;
371 public bool ToBoolean (IFormatProvider provider)
373 return System.Convert.ToBoolean (value);
375 public byte ToByte (IFormatProvider provider)
377 return System.Convert.ToByte (value);
379 public char ToChar (IFormatProvider provider)
381 return System.Convert.ToChar (value);
383 DateTime IConvertible.ToDateTime (IFormatProvider provider)
385 throw new NotImplementedException ();
387 public decimal ToDecimal (IFormatProvider provider)
389 return System.Convert.ToDecimal (value);
391 public double ToDouble (IFormatProvider provider)
393 return System.Convert.ToDouble (value);
395 public short ToInt16 (IFormatProvider provider)
397 return System.Convert.ToInt16 (value);
399 public int ToInt32 (IFormatProvider provider)
401 return System.Convert.ToInt32 (value);
403 public long ToInt64 (IFormatProvider provider)
405 return System.Convert.ToInt64 (value);
407 [CLSCompliant(false)]
408 public sbyte ToSByte (IFormatProvider provider)
410 return System.Convert.ToSByte (value);
412 public float ToSingle (IFormatProvider provider)
414 return System.Convert.ToSingle (value);
416 object IConvertible.ToType (Type conversionType, IFormatProvider provider)
418 throw new NotImplementedException ();
420 [CLSCompliant(false)]
421 public ushort ToUInt16 (IFormatProvider provider)
423 return System.Convert.ToUInt16 (value);
425 [CLSCompliant(false)]
426 public uint ToUInt32 (IFormatProvider provider)
428 return System.Convert.ToUInt32 (value);
430 [CLSCompliant(false)]
431 public ulong ToUInt64 (IFormatProvider provider)