5 // Miguel de Icaza (miguel@ximian.com)
7 // (C) Ximian, Inc. http://www.ximian.com
8 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System.Globalization;
31 using System.Threading;
36 [CLSCompliant (false)]
37 public struct UInt64 : IFormattable, IConvertible,
39 IComparable, IComparable<UInt64>
44 public const ulong MaxValue = 0xffffffffffffffff;
45 public const ulong MinValue = 0;
47 internal ulong m_value;
49 public int CompareTo (object value)
54 if (!(value is System.UInt64))
55 throw new ArgumentException (Locale.GetText ("Value is not a System.UInt64."));
57 if (this.m_value == (ulong) value)
60 if (this.m_value < (ulong) value)
66 public override bool Equals (object obj)
68 if (!(obj is System.UInt64))
71 return ((ulong) obj) == m_value;
74 public override int GetHashCode ()
76 return (int)(m_value & 0xffffffff) ^ (int)(m_value >> 32);
80 public int CompareTo (ulong value)
90 public bool Equals (ulong value)
92 return value == m_value;
96 [CLSCompliant (false)]
97 public static ulong Parse (string s)
99 return Parse (s, NumberStyles.Integer, null);
102 [CLSCompliant (false)]
103 public static ulong Parse (string s, IFormatProvider provider)
105 return Parse (s, NumberStyles.Integer, provider);
108 [CLSCompliant (false)]
109 public static ulong Parse (string s, NumberStyles style)
111 return Parse (s, style, null);
114 [CLSCompliant (false)]
115 public static ulong Parse (string s, NumberStyles style, IFormatProvider provider)
118 throw new ArgumentNullException ("s");
121 throw new FormatException (Locale.GetText ("Input string was not in the correct format."));
123 NumberFormatInfo nfi;
124 if (provider != null) {
125 Type typeNFI = typeof (NumberFormatInfo);
126 nfi = (NumberFormatInfo) provider.GetFormat (typeNFI);
129 nfi = Thread.CurrentThread.CurrentCulture.NumberFormat;
131 Int32.CheckStyle (style);
133 bool AllowCurrencySymbol = (style & NumberStyles.AllowCurrencySymbol) != 0;
134 bool AllowHexSpecifier = (style & NumberStyles.AllowHexSpecifier) != 0;
135 bool AllowThousands = (style & NumberStyles.AllowThousands) != 0;
136 bool AllowDecimalPoint = (style & NumberStyles.AllowDecimalPoint) != 0;
137 bool AllowParentheses = (style & NumberStyles.AllowParentheses) != 0;
138 bool AllowTrailingSign = (style & NumberStyles.AllowTrailingSign) != 0;
139 bool AllowLeadingSign = (style & NumberStyles.AllowLeadingSign) != 0;
140 bool AllowTrailingWhite = (style & NumberStyles.AllowTrailingWhite) != 0;
141 bool AllowLeadingWhite = (style & NumberStyles.AllowLeadingWhite) != 0;
145 if (AllowLeadingWhite)
146 pos = Int32.JumpOverWhite (pos, s, true);
148 bool foundOpenParentheses = false;
149 bool negative = false;
150 bool foundSign = false;
151 bool foundCurrency = false;
154 if (AllowParentheses && s [pos] == '(') {
155 foundOpenParentheses = true;
157 negative = true; // MS always make the number negative when there parentheses
158 // even when NumberFormatInfo.NumberNegativePattern != 0!!!
160 if (AllowLeadingWhite)
161 pos = Int32.JumpOverWhite (pos, s, true);
163 if (s.Substring (pos, nfi.NegativeSign.Length) == nfi.NegativeSign)
164 throw new FormatException (Locale.GetText ("Input string was not in the correct format."));
165 if (s.Substring (pos, nfi.PositiveSign.Length) == nfi.PositiveSign)
166 throw new FormatException (Locale.GetText ("Input string was not in the correct format."));
169 if (AllowLeadingSign && !foundSign) {
171 Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
173 if (AllowLeadingWhite)
174 pos = Int32.JumpOverWhite (pos, s, true);
175 if (AllowCurrencySymbol) {
176 Int32.FindCurrency (ref pos, s, nfi,
178 if (foundCurrency && AllowLeadingWhite)
179 pos = Int32.JumpOverWhite (pos, s, true);
184 if (AllowCurrencySymbol && !foundCurrency) {
186 Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
188 if (AllowLeadingWhite)
189 pos = Int32.JumpOverWhite (pos, s, true);
191 if (!foundSign && AllowLeadingSign) {
192 Int32.FindSign (ref pos, s, nfi, ref foundSign,
194 if (foundSign && AllowLeadingWhite)
195 pos = Int32.JumpOverWhite (pos, s, true);
203 bool decimalPointFound = false;
208 // Just the same as Int32, but this one adds instead of substract
211 if (!Int32.ValidDigit (s [pos], AllowHexSpecifier)) {
212 if (AllowThousands && Int32.FindOther (ref pos, s, nfi.NumberGroupSeparator))
215 if (!decimalPointFound && AllowDecimalPoint &&
216 Int32.FindOther (ref pos, s, nfi.NumberDecimalSeparator)) {
217 decimalPointFound = true;
222 else if (AllowHexSpecifier) {
224 hexDigit = s [pos++];
225 if (Char.IsDigit (hexDigit))
226 digitValue = (ulong) (hexDigit - '0');
227 else if (Char.IsLower (hexDigit))
228 digitValue = (ulong) (hexDigit - 'a' + 10);
230 digitValue = (ulong) (hexDigit - 'A' + 10);
232 number = checked (number * 16 + digitValue);
234 else if (decimalPointFound) {
236 // Allows decimal point as long as it's only
237 // followed by zeroes.
238 if (s [pos++] != '0')
239 throw new OverflowException (Locale.GetText ("Value too large or too small."));
245 number = checked (number * 10 + (ulong) (s [pos++] - '0'));
247 catch (OverflowException) {
248 throw new OverflowException (Locale.GetText ("Value too large or too small."));
251 } while (pos < s.Length);
255 throw new FormatException (Locale.GetText ("Input string was not in the correct format."));
257 if (AllowTrailingSign && !foundSign) {
259 Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
261 if (AllowTrailingWhite)
262 pos = Int32.JumpOverWhite (pos, s, true);
263 if (AllowCurrencySymbol)
264 Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
268 if (AllowCurrencySymbol && !foundCurrency) {
270 Int32.FindCurrency (ref pos, s, nfi, ref foundCurrency);
272 if (AllowTrailingWhite)
273 pos = Int32.JumpOverWhite (pos, s, true);
274 if (!foundSign && AllowTrailingSign)
275 Int32.FindSign (ref pos, s, nfi, ref foundSign, ref negative);
279 if (AllowTrailingWhite && pos < s.Length)
280 pos = Int32.JumpOverWhite (pos, s, false);
282 if (foundOpenParentheses) {
283 if (pos >= s.Length || s [pos++] != ')')
284 throw new FormatException (Locale.GetText
285 ("Input string was not in the correct format."));
286 if (AllowTrailingWhite && pos < s.Length)
287 pos = Int32.JumpOverWhite (pos, s, false);
290 if (pos < s.Length && s [pos] != '\u0000')
291 throw new FormatException (Locale.GetText ("Input string was not in the correct format."));
293 // -0 is legal but other negative values are not
294 if (negative && (number > 0)) {
295 throw new OverflowException (
296 Locale.GetText ("Negative number"));
302 public override string ToString ()
304 return ToString (null, null);
307 public string ToString (IFormatProvider provider)
309 return ToString (null, provider);
312 public string ToString (string format)
314 return ToString (format, null);
317 public string ToString (string format, IFormatProvider provider)
319 NumberFormatInfo nfi = NumberFormatInfo.GetInstance (provider);
321 // use "G" when format is null or String.Empty
322 if ((format == null) || (format.Length == 0))
325 return IntegerFormatter.NumberToString (format, nfi, m_value);
328 // =========== IConvertible Methods =========== //
329 public TypeCode GetTypeCode ()
331 return TypeCode.UInt64;
334 bool IConvertible.ToBoolean (IFormatProvider provider)
336 return System.Convert.ToBoolean (m_value);
339 byte IConvertible.ToByte (IFormatProvider provider)
341 return System.Convert.ToByte (m_value);
344 char IConvertible.ToChar (IFormatProvider provider)
346 return System.Convert.ToChar (m_value);
349 DateTime IConvertible.ToDateTime (IFormatProvider provider)
351 return System.Convert.ToDateTime (m_value);
354 decimal IConvertible.ToDecimal (IFormatProvider provider)
356 return System.Convert.ToDecimal (m_value);
359 double IConvertible.ToDouble (IFormatProvider provider)
361 return System.Convert.ToDouble (m_value);
364 short IConvertible.ToInt16 (IFormatProvider provider)
366 return System.Convert.ToInt16 (m_value);
369 int IConvertible.ToInt32 (IFormatProvider provider)
371 return System.Convert.ToInt32 (m_value);
374 long IConvertible.ToInt64 (IFormatProvider provider)
376 return System.Convert.ToInt64 (m_value);
379 sbyte IConvertible.ToSByte(IFormatProvider provider)
381 return System.Convert.ToSByte (m_value);
384 float IConvertible.ToSingle (IFormatProvider provider)
386 return System.Convert.ToSingle (m_value);
389 object IConvertible.ToType (Type conversionType, IFormatProvider provider)
391 return System.Convert.ToType (m_value, conversionType, provider);
394 ushort IConvertible.ToUInt16 (IFormatProvider provider)
396 return System.Convert.ToUInt16 (m_value);
399 uint IConvertible.ToUInt32 (IFormatProvider provider)
401 return System.Convert.ToUInt32 (m_value);
404 ulong IConvertible.ToUInt64 (IFormatProvider provider)