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 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 // Note about the ToString()'s. ECMA says there's only a ToString() method,
33 // BUT it is just a wrapper for ToString(null). However there is no other ToString
34 // in the docs. Turning to the NET framework sdk reveals that there is a
35 // ToString(formatprovider) method, as well as a 'static ToString (char c)' method,
36 // which appears to just be a Convert.ToString(char c) type method. ECMA also
37 // doesn't list this class as implementing IFormattable.
39 using System.Globalization;
40 using System.Runtime.CompilerServices;
42 using System.Runtime.InteropServices;
50 public struct Char : IComparable, IConvertible, IComparable <char>, IEquatable <char>
52 public struct Char : IComparable, IConvertible
55 public const char MaxValue = (char) 0xffff;
56 public const char MinValue = (char) 0;
58 internal char m_value;
63 GetDataTablePointers (out category_data, out numeric_data, out numeric_data_values,
64 out to_lower_data_low, out to_lower_data_high, out to_upper_data_low, out to_upper_data_high);
68 private readonly unsafe static byte *category_data;
69 private readonly unsafe static byte *numeric_data;
70 private readonly unsafe static double *numeric_data_values;
71 private readonly unsafe static ushort *to_lower_data_low;
72 private readonly unsafe static ushort *to_lower_data_high;
73 private readonly unsafe static ushort *to_upper_data_low;
74 private readonly unsafe static ushort *to_upper_data_high;
76 [MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
77 private unsafe static extern void GetDataTablePointers (out byte *category_data,
78 out byte *numeric_data, out double *numeric_data_values,
79 out ushort *to_lower_data_low, out ushort *to_lower_data_high,
80 out ushort *to_upper_data_low, out ushort *to_upper_data_high);
82 public int CompareTo (object v)
87 if (!(v is System.Char))
88 throw new ArgumentException (Locale.GetText ("Value is not a System.Char"));
100 public override bool Equals (object o)
105 return ((char) o) == m_value;
109 public int CompareTo (char value)
111 if (m_value == value)
120 public bool Equals (char value)
122 return m_value == value;
126 public override int GetHashCode ()
131 public static double GetNumericValue (char c)
133 if (c > (char)0x3289) {
134 if (c >= (char)0xFF10 && c <= (char)0xFF19)
135 return (c - 0xFF10); // Numbers 0-9
137 // Default not set data
142 return numeric_data_values [numeric_data [c]];
148 public static double GetNumericValue (string str, int index)
151 throw new ArgumentNullException ("str");
153 if (index < 0 || index >= str.Length)
154 throw new ArgumentOutOfRangeException (Locale.GetText (
155 "The value of index is less than zero, or greater than or equal to the length of str."));
157 return GetNumericValue (str[index]);
160 public static UnicodeCategory GetUnicodeCategory (char c)
163 return (UnicodeCategory)(category_data [c]);
167 public static UnicodeCategory GetUnicodeCategory (string str, int index)
170 throw new ArgumentNullException ("str");
172 if (index < 0 || index >= str.Length)
173 throw new ArgumentOutOfRangeException (Locale.GetText (
174 "The value of index is less than zero, or greater than or equal to the length of str."));
176 return GetUnicodeCategory (str[index]);
179 public static bool IsControl (char c)
182 return (category_data [c] == (byte)UnicodeCategory.Control);
186 public static bool IsControl (string str, int index)
189 throw new ArgumentNullException ("str");
191 if (index < 0 || index >= str.Length)
192 throw new ArgumentOutOfRangeException (Locale.GetText (
193 "The value of index is less than zero, or greater than or equal to the length of str."));
195 return IsControl (str[index]);
198 public static bool IsDigit (char c)
201 return (category_data [c] == (byte)UnicodeCategory.DecimalDigitNumber);
205 public static bool IsDigit (string str, int index)
208 throw new ArgumentNullException ("str");
210 if (index < 0 || index >= str.Length)
211 throw new ArgumentOutOfRangeException (Locale.GetText (
212 "The value of index is less than zero, or greater than or equal to the length of str."));
214 return IsDigit (str[index]);
218 public static bool IsHighSurrogate (char c)
220 return c >= '\uD800' && c <= '\uDBFF';
223 public static bool IsHighSurrogate (string s, int index)
226 throw new ArgumentNullException ("s");
228 if (index < 0 || index >= s.Length)
229 throw new ArgumentOutOfRangeException ("index");
231 return IsHighSurrogate (s [index]);
235 public static bool IsLetter (char c)
238 UnicodeCategory Category = (UnicodeCategory)category_data [c];
240 case UnicodeCategory.UppercaseLetter:
241 case UnicodeCategory.LowercaseLetter:
242 case UnicodeCategory.TitlecaseLetter:
243 case UnicodeCategory.ModifierLetter:
244 case UnicodeCategory.OtherLetter:
252 public static bool IsLetter (string str, int index)
255 throw new ArgumentNullException ("str");
257 if (index < 0 || index >= str.Length)
258 throw new ArgumentOutOfRangeException (Locale.GetText (
259 "The value of index is less than zero, or greater than or equal to the length of str."));
261 return IsLetter (str[index]);
264 public static bool IsLetterOrDigit (char c)
267 UnicodeCategory Category = (UnicodeCategory)category_data [c];
269 case UnicodeCategory.DecimalDigitNumber:
270 case UnicodeCategory.UppercaseLetter:
271 case UnicodeCategory.LowercaseLetter:
272 case UnicodeCategory.TitlecaseLetter:
273 case UnicodeCategory.ModifierLetter:
274 case UnicodeCategory.OtherLetter:
282 public static bool IsLetterOrDigit (string str, int index)
285 throw new ArgumentNullException ("str");
287 if (index < 0 || index >= str.Length)
288 throw new ArgumentOutOfRangeException (Locale.GetText (
289 "The value of index is less than zero, or greater than or equal to the length of str."));
291 return IsLetterOrDigit (str[index]);
294 public static bool IsLower (char c)
297 return (category_data [c] == (byte)UnicodeCategory.LowercaseLetter);
301 public static bool IsLower (string str, int index)
304 throw new ArgumentNullException ("str");
306 if (index < 0 || index >= str.Length)
307 throw new ArgumentOutOfRangeException (Locale.GetText (
308 "The value of index is less than zero, or greater than or equal to the length of str."));
310 return IsLower (str[index]);
314 public static bool IsLowSurrogate (char c)
316 return c >= '\uDC00' && c <= '\uDFFF';
319 public static bool IsLowSurrogate (string s, int index)
322 throw new ArgumentNullException ("s");
324 if (index < 0 || index >= s.Length)
325 throw new ArgumentOutOfRangeException ("index");
327 return IsLowSurrogate (s [index]);
331 public static bool IsNumber (char c)
334 UnicodeCategory Category = (UnicodeCategory)category_data [c];
336 case UnicodeCategory.DecimalDigitNumber:
337 case UnicodeCategory.LetterNumber:
338 case UnicodeCategory.OtherNumber:
346 public static bool IsNumber (string str, int index)
349 throw new ArgumentNullException ("str");
351 if (index < 0 || index >= str.Length)
352 throw new ArgumentOutOfRangeException (Locale.GetText (
353 "The value of index is less than zero, or greater than or equal to the length of str."));
355 return IsNumber (str[index]);
358 public static bool IsPunctuation (char c)
361 UnicodeCategory Category = (UnicodeCategory)category_data [c];
363 case UnicodeCategory.ConnectorPunctuation:
364 case UnicodeCategory.DashPunctuation:
365 case UnicodeCategory.OpenPunctuation:
366 case UnicodeCategory.ClosePunctuation:
367 case UnicodeCategory.InitialQuotePunctuation:
368 case UnicodeCategory.FinalQuotePunctuation:
369 case UnicodeCategory.OtherPunctuation:
377 public static bool IsPunctuation (string str, int index)
380 throw new ArgumentNullException ("str");
382 if (index < 0 || index >= str.Length)
383 throw new ArgumentOutOfRangeException (Locale.GetText (
384 "The value of index is less than zero, or greater than or equal to the length of str."));
386 return IsPunctuation (str[index]);
389 public static bool IsSeparator (char c)
392 UnicodeCategory Category = (UnicodeCategory)category_data [c];
394 case UnicodeCategory.SpaceSeparator:
395 case UnicodeCategory.LineSeparator:
396 case UnicodeCategory.ParagraphSeparator:
404 public static bool IsSeparator (string str, int index)
407 throw new ArgumentNullException ("str");
409 if (index < 0 || index >= str.Length)
410 throw new ArgumentOutOfRangeException (Locale.GetText (
411 "The value of index is less than zero, or greater than or equal to the length of str."));
413 return IsSeparator (str[index]);
416 public static bool IsSurrogate (char c)
419 return (category_data [c] == (byte)UnicodeCategory.Surrogate);
423 public static bool IsSurrogate (string str, int index)
426 throw new ArgumentNullException ("str");
428 if (index < 0 || index >= str.Length)
429 throw new ArgumentOutOfRangeException (Locale.GetText (
430 "The value of index is less than zero, or greater than or equal to the length of str."));
432 return IsSurrogate (str[index]);
435 public static bool IsSymbol (char c)
438 UnicodeCategory Category = (UnicodeCategory)category_data [c];
440 case UnicodeCategory.MathSymbol:
441 case UnicodeCategory.CurrencySymbol:
442 case UnicodeCategory.ModifierSymbol:
443 case UnicodeCategory.OtherSymbol:
451 public static bool IsSymbol (string str, int index)
454 throw new ArgumentNullException ("str");
456 if (index < 0 || index >= str.Length)
457 throw new ArgumentOutOfRangeException (Locale.GetText (
458 "The value of index is less than zero, or greater than or equal to the length of str."));
460 return IsSymbol (str[index]);
463 public static bool IsUpper (char c)
466 return (category_data [c] == (byte)UnicodeCategory.UppercaseLetter);
470 public static bool IsUpper (string str, int index)
473 throw new ArgumentNullException ("str");
475 if (index < 0 || index >= str.Length)
476 throw new ArgumentOutOfRangeException (Locale.GetText (
477 "The value of index is less than zero, or greater than or equal to the length of str."));
479 return IsUpper (str[index]);
482 public static bool IsWhiteSpace (char c)
485 if (category_data [c] == (byte)UnicodeCategory.SpaceSeparator)
494 case (char)0x85: // NEL
495 case (char)0x2028: // Line Separator
496 case (char)0x2029: // Paragraph Separator
498 case (char)0x205F: // Medium Mathematical Space
507 public static bool IsWhiteSpace (string str, int index)
510 throw new ArgumentNullException ("str");
512 if (index < 0 || index >= str.Length)
513 throw new ArgumentOutOfRangeException (Locale.GetText (
514 "The value of index is less than zero, or greater than or equal to the length of str."));
516 return IsWhiteSpace (str[index]);
519 public static char Parse (string str)
522 throw new ArgumentNullException ("str");
525 throw new FormatException ("string contains more than one character.");
530 public static char ToLower (char c)
532 return ToLower (c, CultureInfo.CurrentCulture);
536 public static char ToLowerInvariant (char c)
538 internal static char ToLowerInvariant (char c)
542 if (c <= ((char)0x24cf))
543 return (char) to_lower_data_low [c];
544 if (c >= ((char)0xff21))
545 return (char) to_lower_data_high[c - 0xff21];
550 public static char ToLower (char c, CultureInfo culture)
553 throw new ArgumentNullException ("culture");
554 if (culture.LCID == 0x007F) // Invariant
555 return ToLowerInvariant (c);
557 return culture.TextInfo.ToLower (c);
560 public static char ToUpper (char c)
562 return ToUpper (c, CultureInfo.CurrentCulture);
566 public static char ToUpperInvariant (char c)
568 internal static char ToUpperInvariant (char c)
572 if (c <= ((char)0x24e9))
573 return (char) to_upper_data_low [c];
574 if (c >= ((char)0xff21))
575 return (char) to_upper_data_high [c - 0xff21];
580 public static char ToUpper (char c, CultureInfo culture)
583 throw new ArgumentNullException ("culture");
584 if (culture.LCID == 0x007F) // Invariant
585 return ToUpperInvariant (c);
587 return culture.TextInfo.ToUpper (c);
590 public override string ToString ()
592 // LAMESPEC: ECMA draft lists this as returning ToString (null),
593 // However it doesn't list another ToString() method.
594 return new String (m_value, 1);
597 public static string ToString(char c)
599 return new String (c, 1);
602 public string ToString (IFormatProvider fp)
604 // LAMESPEC: ECMA draft doesn't say Char implements IFormattable
605 return new String (m_value, 1);
608 // =========== IConvertible Methods =========== //
610 public TypeCode GetTypeCode ()
612 return TypeCode.Char;
615 object IConvertible.ToType (Type conversionType, IFormatProvider provider)
617 return System.Convert.ToType(m_value, conversionType, provider);
620 bool IConvertible.ToBoolean (IFormatProvider provider)
622 throw new InvalidCastException();
625 byte IConvertible.ToByte (IFormatProvider provider)
627 return System.Convert.ToByte(m_value);
630 char IConvertible.ToChar (IFormatProvider provider)
635 DateTime IConvertible.ToDateTime (IFormatProvider provider)
637 throw new InvalidCastException();
640 decimal IConvertible.ToDecimal (IFormatProvider provider)
642 throw new InvalidCastException();
645 double IConvertible.ToDouble (IFormatProvider provider)
647 throw new InvalidCastException();
650 short IConvertible.ToInt16 (IFormatProvider provider)
652 return System.Convert.ToInt16(m_value);
655 int IConvertible.ToInt32 (IFormatProvider provider)
657 return System.Convert.ToInt32(m_value);
660 long IConvertible.ToInt64 (IFormatProvider provider)
662 return System.Convert.ToInt64(m_value);
665 sbyte IConvertible.ToSByte (IFormatProvider provider)
667 return System.Convert.ToSByte(m_value);
670 float IConvertible.ToSingle (IFormatProvider provider)
672 throw new InvalidCastException();
675 ushort IConvertible.ToUInt16 (IFormatProvider provider)
677 return System.Convert.ToUInt16(m_value);
680 uint IConvertible.ToUInt32 (IFormatProvider provider)
682 return System.Convert.ToUInt32(m_value);
685 ulong IConvertible.ToUInt64 (IFormatProvider provider)
687 return System.Convert.ToUInt64(m_value);