5 // Andreas Nahr (ClassDevelopment@A-SoftTech.com)
6 // Miguel de Icaza (miguel@ximian.com)
7 // Jackson Harper (jackson@ximian.com)
9 // (C) Ximian, Inc. http://www.ximian.com
10 // (C) 2004 Novell, Inc (http://www.novell.com)
13 // Note about the ToString()'s. ECMA says there's only a ToString() method,
14 // BUT it is just a wrapper for ToString(null). However there is no other ToString
15 // in the docs. Turning to the NET framework sdk reveals that there is a
16 // ToString(formatprovider) method, as well as a 'static ToString (char c)' method,
17 // which appears to just be a Convert.ToString(char c) type method. ECMA also
18 // doesn't list this class as implementing IFormattable.
21 using System.Globalization;
22 using System.Runtime.CompilerServices;
27 public struct Char : IComparable, IConvertible
29 public const char MaxValue = (char) 0xffff;
30 public const char MinValue = (char) 0;
32 internal char m_value;
37 GetDataTablePointers (out category_data, out numeric_data, out numeric_data_values,
38 out to_lower_data_low, out to_lower_data_high, out to_upper_data_low, out to_upper_data_high);
42 private readonly unsafe static byte *category_data;
43 private readonly unsafe static byte *numeric_data;
44 private readonly unsafe static double *numeric_data_values;
45 private readonly unsafe static ushort *to_lower_data_low;
46 private readonly unsafe static ushort *to_lower_data_high;
47 private readonly unsafe static ushort *to_upper_data_low;
48 private readonly unsafe static ushort *to_upper_data_high;
50 [MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
51 private unsafe static extern void GetDataTablePointers (out byte *category_data,
52 out byte *numeric_data, out double *numeric_data_values,
53 out ushort *to_lower_data_low, out ushort *to_lower_data_high,
54 out ushort *to_upper_data_low, out ushort *to_upper_data_high);
56 public int CompareTo (object v)
61 if (!(v is System.Char))
62 throw new ArgumentException (Locale.GetText ("Value is not a System.Char"));
74 public override bool Equals (object o)
79 return ((Char) o).m_value == m_value;
82 public override int GetHashCode ()
87 public static double GetNumericValue (char c)
89 if (c > (char)0x3289) {
90 if (c >= (char)0xFF10 && c <= (char)0xFF19)
91 return (c - 0xFF10); // Numbers 0-9
93 // Default not set data
98 return numeric_data_values [numeric_data [c]];
104 public static double GetNumericValue (string str, int index)
107 throw new ArgumentNullException ("str");
109 if (index < 0 || index >= str.Length)
110 throw new ArgumentOutOfRangeException (Locale.GetText (
111 "The value of index is less than zero, or greater than or equal to the length of str."));
113 return GetNumericValue (str[index]);
116 public static UnicodeCategory GetUnicodeCategory (char c)
119 return (UnicodeCategory)(category_data [c]);
123 public static UnicodeCategory GetUnicodeCategory (string str, int index)
126 throw new ArgumentNullException ("str");
128 if (index < 0 || index >= str.Length)
129 throw new ArgumentOutOfRangeException (Locale.GetText (
130 "The value of index is less than zero, or greater than or equal to the length of str."));
132 return GetUnicodeCategory (str[index]);
135 public static bool IsControl (char c)
138 return (category_data [c] == (byte)UnicodeCategory.Control);
142 public static bool IsControl (string str, int index)
145 throw new ArgumentNullException ("str");
147 if (index < 0 || index >= str.Length)
148 throw new ArgumentOutOfRangeException (Locale.GetText (
149 "The value of index is less than zero, or greater than or equal to the length of str."));
151 return IsControl (str[index]);
154 public static bool IsDigit (char c)
157 return (category_data [c] == (byte)UnicodeCategory.DecimalDigitNumber);
161 public static bool IsDigit (string str, int index)
164 throw new ArgumentNullException ("str");
166 if (index < 0 || index >= str.Length)
167 throw new ArgumentOutOfRangeException (Locale.GetText (
168 "The value of index is less than zero, or greater than or equal to the length of str."));
170 return IsDigit (str[index]);
173 public static bool IsLetter (char c)
176 UnicodeCategory Category = (UnicodeCategory)category_data [c];
178 case UnicodeCategory.UppercaseLetter:
179 case UnicodeCategory.LowercaseLetter:
180 case UnicodeCategory.TitlecaseLetter:
181 case UnicodeCategory.ModifierLetter:
182 case UnicodeCategory.OtherLetter:
190 public static bool IsLetter (string str, int index)
193 throw new ArgumentNullException ("str");
195 if (index < 0 || index >= str.Length)
196 throw new ArgumentOutOfRangeException (Locale.GetText (
197 "The value of index is less than zero, or greater than or equal to the length of str."));
199 return IsLetter (str[index]);
202 public static bool IsLetterOrDigit (char c)
205 UnicodeCategory Category = (UnicodeCategory)category_data [c];
207 case UnicodeCategory.DecimalDigitNumber:
208 case UnicodeCategory.UppercaseLetter:
209 case UnicodeCategory.LowercaseLetter:
210 case UnicodeCategory.TitlecaseLetter:
211 case UnicodeCategory.ModifierLetter:
212 case UnicodeCategory.OtherLetter:
220 public static bool IsLetterOrDigit (string str, int index)
223 throw new ArgumentNullException ("str");
225 if (index < 0 || index >= str.Length)
226 throw new ArgumentOutOfRangeException (Locale.GetText (
227 "The value of index is less than zero, or greater than or equal to the length of str."));
229 return IsLetterOrDigit (str[index]);
232 public static bool IsLower (char c)
235 return (category_data [c] == (byte)UnicodeCategory.LowercaseLetter);
239 public static bool IsLower (string str, int index)
242 throw new ArgumentNullException ("str");
244 if (index < 0 || index >= str.Length)
245 throw new ArgumentOutOfRangeException (Locale.GetText (
246 "The value of index is less than zero, or greater than or equal to the length of str."));
248 return IsLower (str[index]);
251 public static bool IsNumber (char c)
254 UnicodeCategory Category = (UnicodeCategory)category_data [c];
256 case UnicodeCategory.DecimalDigitNumber:
257 case UnicodeCategory.LetterNumber:
258 case UnicodeCategory.OtherNumber:
266 public static bool IsNumber (string str, int index)
269 throw new ArgumentNullException ("str");
271 if (index < 0 || index >= str.Length)
272 throw new ArgumentOutOfRangeException (Locale.GetText (
273 "The value of index is less than zero, or greater than or equal to the length of str."));
275 return IsNumber (str[index]);
278 public static bool IsPunctuation (char c)
281 UnicodeCategory Category = (UnicodeCategory)category_data [c];
283 case UnicodeCategory.ConnectorPunctuation:
284 case UnicodeCategory.DashPunctuation:
285 case UnicodeCategory.OpenPunctuation:
286 case UnicodeCategory.ClosePunctuation:
287 case UnicodeCategory.InitialQuotePunctuation:
288 case UnicodeCategory.FinalQuotePunctuation:
289 case UnicodeCategory.OtherPunctuation:
297 public static bool IsPunctuation (string str, int index)
300 throw new ArgumentNullException ("str");
302 if (index < 0 || index >= str.Length)
303 throw new ArgumentOutOfRangeException (Locale.GetText (
304 "The value of index is less than zero, or greater than or equal to the length of str."));
306 return IsPunctuation (str[index]);
309 public static bool IsSeparator (char c)
312 UnicodeCategory Category = (UnicodeCategory)category_data [c];
314 case UnicodeCategory.SpaceSeparator:
315 case UnicodeCategory.LineSeparator:
316 case UnicodeCategory.ParagraphSeparator:
324 public static bool IsSeparator (string str, int index)
327 throw new ArgumentNullException ("str");
329 if (index < 0 || index >= str.Length)
330 throw new ArgumentOutOfRangeException (Locale.GetText (
331 "The value of index is less than zero, or greater than or equal to the length of str."));
333 return IsSeparator (str[index]);
336 public static bool IsSurrogate (char c)
339 return (category_data [c] == (byte)UnicodeCategory.Surrogate);
343 public static bool IsSurrogate (string str, int index)
346 throw new ArgumentNullException ("str");
348 if (index < 0 || index >= str.Length)
349 throw new ArgumentOutOfRangeException (Locale.GetText (
350 "The value of index is less than zero, or greater than or equal to the length of str."));
352 return IsSurrogate (str[index]);
355 public static bool IsSymbol (char c)
358 UnicodeCategory Category = (UnicodeCategory)category_data [c];
360 case UnicodeCategory.MathSymbol:
361 case UnicodeCategory.CurrencySymbol:
362 case UnicodeCategory.ModifierSymbol:
363 case UnicodeCategory.OtherSymbol:
371 public static bool IsSymbol (string str, int index)
374 throw new ArgumentNullException ("str");
376 if (index < 0 || index >= str.Length)
377 throw new ArgumentOutOfRangeException (Locale.GetText (
378 "The value of index is less than zero, or greater than or equal to the length of str."));
380 return IsSymbol (str[index]);
383 public static bool IsUpper (char c)
386 return (category_data [c] == (byte)UnicodeCategory.UppercaseLetter);
390 public static bool IsUpper (string str, int index)
393 throw new ArgumentNullException ("str");
395 if (index < 0 || index >= str.Length)
396 throw new ArgumentOutOfRangeException (Locale.GetText (
397 "The value of index is less than zero, or greater than or equal to the length of str."));
399 return IsUpper (str[index]);
402 public static bool IsWhiteSpace (char c)
405 if (category_data [c] == (byte)UnicodeCategory.SpaceSeparator)
414 case (char)0x85: // NEL
415 case (char)0x2028: // Line Separator
416 case (char)0x2029: // Paragraph Separator
424 public static bool IsWhiteSpace (string str, int index)
427 throw new ArgumentNullException ("str");
429 if (index < 0 || index >= str.Length)
430 throw new ArgumentOutOfRangeException (Locale.GetText (
431 "The value of index is less than zero, or greater than or equal to the length of str."));
433 return IsWhiteSpace (str[index]);
436 public static char Parse (string str)
439 throw new ArgumentNullException ("str");
442 throw new FormatException ("string contains more than one character.");
447 [MonoTODO ("Fix FIXME")]
448 public static char ToLower (char c)
450 // FIXME: needs to call line below, but that would probably break a lot of things right now
451 // return InternalToLower (c, CultureInfo.CurrentCulture);
452 return ToLowerInvariant (c);
455 internal static char ToLowerInvariant (char c)
458 if (c <= ((char)0x24cf))
459 return (char) to_lower_data_low [c];
460 if (c >= ((char)0xff41))
461 return (char) to_lower_data_high[c - 0xff41];
466 public static char ToLower (char c, CultureInfo culture)
469 throw new ArgumentNullException ("culture");
470 if (culture.LCID == 0x007F) // Invariant
471 return ToLowerInvariant (c);
473 return InternalToLower (c, culture);
476 [MethodImplAttribute (MethodImplOptions.InternalCall)]
477 private static extern char InternalToLower (char c, CultureInfo culture);
479 [MonoTODO ("Fix FIXME")]
480 public static char ToUpper (char c)
482 // FIXME: needs to call line below, but that would probably break a lot of things right now
483 // return InternalToUpper (c, CultureInfo.CurrentCulture);
484 return ToUpperInvariant (c);
487 internal static char ToUpperInvariant (char c)
490 if (c <= ((char)0x24cf))
491 return (char) to_upper_data_low [c];
492 if (c >= ((char)0xff21))
493 return (char) to_upper_data_high [c - 0xff21];
498 public static char ToUpper (char c, CultureInfo culture)
501 throw new ArgumentNullException ("culture");
502 if (culture.LCID == 0x007F) // Invariant
503 return ToUpperInvariant (c);
505 return InternalToUpper (c, culture);
508 [MethodImplAttribute (MethodImplOptions.InternalCall)]
509 private static extern char InternalToUpper (char c, CultureInfo culture);
511 public override string ToString ()
513 // LAMESPEC: ECMA draft lists this as returning ToString (null),
514 // However it doesn't list another ToString() method.
515 return new String (m_value, 1);
518 public static string ToString(char c)
520 return new String (c, 1);
523 public string ToString (IFormatProvider fp)
525 // LAMESPEC: ECMA draft doesn't say Char implements IFormattable
526 return new String (m_value, 1);
529 // =========== IConvertible Methods =========== //
531 public TypeCode GetTypeCode ()
533 return TypeCode.Char;
536 object IConvertible.ToType (Type conversionType, IFormatProvider provider)
538 return System.Convert.ToType(m_value, conversionType, provider);
541 bool IConvertible.ToBoolean (IFormatProvider provider)
543 throw new InvalidCastException();
546 byte IConvertible.ToByte (IFormatProvider provider)
548 return System.Convert.ToByte(m_value);
551 char IConvertible.ToChar (IFormatProvider provider)
556 DateTime IConvertible.ToDateTime (IFormatProvider provider)
558 throw new InvalidCastException();
561 decimal IConvertible.ToDecimal (IFormatProvider provider)
563 throw new InvalidCastException();
566 double IConvertible.ToDouble (IFormatProvider provider)
568 throw new InvalidCastException();
571 short IConvertible.ToInt16 (IFormatProvider provider)
573 return System.Convert.ToInt16(m_value);
576 int IConvertible.ToInt32 (IFormatProvider provider)
578 return System.Convert.ToInt32(m_value);
581 long IConvertible.ToInt64 (IFormatProvider provider)
583 return System.Convert.ToInt64(m_value);
586 sbyte IConvertible.ToSByte (IFormatProvider provider)
588 return System.Convert.ToSByte(m_value);
591 float IConvertible.ToSingle (IFormatProvider provider)
593 throw new InvalidCastException();
596 string IConvertible.ToString (IFormatProvider provider)
598 return ToString(provider);
601 ushort IConvertible.ToUInt16 (IFormatProvider provider)
603 return System.Convert.ToUInt16(m_value);
606 uint IConvertible.ToUInt32 (IFormatProvider provider)
608 return System.Convert.ToUInt32(m_value);
611 ulong IConvertible.ToUInt64 (IFormatProvider provider)
613 return System.Convert.ToUInt64(m_value);