The Labs \ Source Viewer \ SSCLI \ System \ Char

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. /*============================================================
  16. **
  17. ** Class:  Char
  18. **
  19. **
  20. ** Purpose: This is the value class representing a Unicode character
  21. ** Char methods until we create this functionality.
  22. **
  23. **
  24. ===========================================================*/
  25. namespace System
  26. {
  27.    
  28.     using System;
  29.     using System.Globalization;
  30.     using System.Runtime.InteropServices;
  31.     using System.Runtime.CompilerServices;
  32.    
  33.     [System.Runtime.InteropServices.ComVisible(true)]
  34.     [Serializable(), System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
  35.     public struct Char : IComparable, IConvertible, IComparable<char>, IEquatable<char>
  36.     {
  37.         //
  38.         // Member Variables
  39.         //
  40.         internal char m_value;
  41.        
  42.         //
  43.         // Public Constants
  44.         //
  45.         // The maximum character value.
  46.         public const char MaxValue = (char)65535;
  47.         // The minimum character value.
  48.         public const char MinValue = (char)0;
  49.        
  50.         // Unicode category values from Unicode U+0000 ~ U+00FF. Store them in byte[] array to save space.
  51.         private static readonly byte[] categoryForLatin1 = {(byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control,
  52.         (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control,
  53.         (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control,
  54.         (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.SpaceSeparator, (byte)UnicodeCategory.OtherPunctuation, (byte)UnicodeCategory.OtherPunctuation, (byte)UnicodeCategory.OtherPunctuation, (byte)UnicodeCategory.CurrencySymbol, (byte)UnicodeCategory.OtherPunctuation, (byte)UnicodeCategory.OtherPunctuation, (byte)UnicodeCategory.OtherPunctuation,
  55.         (byte)UnicodeCategory.OpenPunctuation, (byte)UnicodeCategory.ClosePunctuation, (byte)UnicodeCategory.OtherPunctuation, (byte)UnicodeCategory.MathSymbol, (byte)UnicodeCategory.OtherPunctuation, (byte)UnicodeCategory.DashPunctuation, (byte)UnicodeCategory.OtherPunctuation, (byte)UnicodeCategory.OtherPunctuation, (byte)UnicodeCategory.DecimalDigitNumber, (byte)UnicodeCategory.DecimalDigitNumber,
  56.         (byte)UnicodeCategory.DecimalDigitNumber, (byte)UnicodeCategory.DecimalDigitNumber, (byte)UnicodeCategory.DecimalDigitNumber, (byte)UnicodeCategory.DecimalDigitNumber, (byte)UnicodeCategory.DecimalDigitNumber, (byte)UnicodeCategory.DecimalDigitNumber, (byte)UnicodeCategory.DecimalDigitNumber, (byte)UnicodeCategory.DecimalDigitNumber, (byte)UnicodeCategory.OtherPunctuation, (byte)UnicodeCategory.OtherPunctuation,
  57.         (byte)UnicodeCategory.MathSymbol, (byte)UnicodeCategory.MathSymbol, (byte)UnicodeCategory.MathSymbol, (byte)UnicodeCategory.OtherPunctuation, (byte)UnicodeCategory.OtherPunctuation, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter,
  58.         (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter,
  59.         (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter,
  60.         (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.OpenPunctuation, (byte)UnicodeCategory.OtherPunctuation, (byte)UnicodeCategory.ClosePunctuation, (byte)UnicodeCategory.ModifierSymbol, (byte)UnicodeCategory.ConnectorPunctuation, (byte)UnicodeCategory.ModifierSymbol, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter,
  61.         (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter,
  62.         (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter,
  63.         (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.OpenPunctuation, (byte)UnicodeCategory.MathSymbol, (byte)UnicodeCategory.ClosePunctuation, (byte)UnicodeCategory.MathSymbol, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control,
  64.         (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control,
  65.         (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control,
  66.         (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control,
  67.         (byte)UnicodeCategory.SpaceSeparator, (byte)UnicodeCategory.OtherPunctuation, (byte)UnicodeCategory.CurrencySymbol, (byte)UnicodeCategory.CurrencySymbol, (byte)UnicodeCategory.CurrencySymbol, (byte)UnicodeCategory.CurrencySymbol, (byte)UnicodeCategory.OtherSymbol, (byte)UnicodeCategory.OtherSymbol, (byte)UnicodeCategory.ModifierSymbol, (byte)UnicodeCategory.OtherSymbol,
  68.         (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.InitialQuotePunctuation, (byte)UnicodeCategory.MathSymbol, (byte)UnicodeCategory.DashPunctuation, (byte)UnicodeCategory.OtherSymbol, (byte)UnicodeCategory.ModifierSymbol, (byte)UnicodeCategory.OtherSymbol, (byte)UnicodeCategory.MathSymbol, (byte)UnicodeCategory.OtherNumber, (byte)UnicodeCategory.OtherNumber,
  69.         (byte)UnicodeCategory.ModifierSymbol, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.OtherSymbol, (byte)UnicodeCategory.OtherPunctuation, (byte)UnicodeCategory.ModifierSymbol, (byte)UnicodeCategory.OtherNumber, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.FinalQuotePunctuation, (byte)UnicodeCategory.OtherNumber, (byte)UnicodeCategory.OtherNumber,
  70.         (byte)UnicodeCategory.OtherNumber, (byte)UnicodeCategory.OtherPunctuation, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter,
  71.         (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter,
  72.         (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.MathSymbol, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter,
  73.         (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter,
  74.         (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter,
  75.         (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.MathSymbol, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter,
  76.             // 0000 - 0007
  77.             // 0008 - 000F
  78.             // 0010 - 0017
  79.             // 0018 - 001F
  80.             // 0020 - 0027
  81.             // 0028 - 002F
  82.             // 0030 - 0037
  83.             // 0038 - 003F
  84.             // 0040 - 0047
  85.             // 0048 - 004F
  86.             // 0050 - 0057
  87.             // 0058 - 005F
  88.             // 0060 - 0067
  89.             // 0068 - 006F
  90.             // 0070 - 0077
  91.             // 0078 - 007F
  92.             // 0080 - 0087
  93.             // 0088 - 008F
  94.             // 0090 - 0097
  95.             // 0098 - 009F
  96.             // 00A0 - 00A7
  97.             // 00A8 - 00AF
  98.             // 00B0 - 00B7
  99.             // 00B8 - 00BF
  100.             // 00C0 - 00C7
  101.             // 00C8 - 00CF
  102.             // 00D0 - 00D7
  103.             // 00D8 - 00DF
  104.             // 00E0 - 00E7
  105.             // 00E8 - 00EF
  106.             // 00F0 - 00F7
  107.             // 00F8 - 00FF
  108.         (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter};
  109.        
  110.         // Return true for all characters below or equal U+00ff, which is ASCII + Latin-1 Supplement.
  111.         private static bool IsLatin1(char ch)
  112.         {
  113.             return (ch <= 'ÿ');
  114.         }
  115.        
  116.         // Return true for all characters below or equal U+007f, which is ASCII.
  117.         private static bool IsAscii(char ch)
  118.         {
  119.             return (ch <= '\u127');
  120.         }
  121.        
  122.         // Return the Unicode category for Unicode character <= 0x00ff.
  123.         private static UnicodeCategory GetLatin1UnicodeCategory(char ch)
  124.         {
  125.             BCLDebug.Assert(IsLatin1(ch), "Char.GetLatin1UnicodeCategory(): ch should be <= 007f");
  126.             return (UnicodeCategory)(categoryForLatin1[(int)ch]);
  127.         }
  128.        
  129.         //
  130.         // Private Constants
  131.         //
  132.        
  133.         //
  134.         // Overriden Instance Methods
  135.         //
  136.        
  137.         // Calculate a hashcode for a 2 byte Unicode character.
  138.         public override int GetHashCode()
  139.         {
  140.             return (int)m_value | ((int)m_value << 16);
  141.         }
  142.        
  143.         // Used for comparing two boxed Char objects.
  144.         //
  145.         public override bool Equals(object obj)
  146.         {
  147.             if (!(obj is char)) {
  148.                 return false;
  149.             }
  150.             return (m_value == ((char)obj).m_value);
  151.         }
  152.        
  153.         public bool Equals(char obj)
  154.         {
  155.             return m_value == obj;
  156.         }
  157.        
  158.         // Compares this object to another object, returning an integer that
  159.         // indicates the relationship.
  160.         // Returns a value less than zero if this object
  161.         // null is considered to be less than any instance.
  162.         // If object is not of type Char, this method throws an ArgumentException.
  163.         //
  164.         public int CompareTo(object value)
  165.         {
  166.             if (value == null) {
  167.                 return 1;
  168.             }
  169.             if (!(value is char)) {
  170.                 throw new ArgumentException(Environment.GetResourceString("Arg_MustBeChar"));
  171.             }
  172.            
  173.             return (m_value - ((char)value).m_value);
  174.         }
  175.        
  176.        
  177.         public int CompareTo(char value)
  178.         {
  179.             return (m_value - value);
  180.         }
  181.        
  182.         // Overrides System.Object.ToString.
  183.         public override string ToString()
  184.         {
  185.             return Char.ToString(m_value);
  186.         }
  187.        
  188.         public string ToString(IFormatProvider provider)
  189.         {
  190.             return Char.ToString(m_value);
  191.         }
  192.        
  193.         //
  194.         // Formatting Methods
  195.         //
  196.        
  197. /*===================================ToString===================================
  198.       **This static methods takes a character and returns the String representation of it.
  199.       ==============================================================================*/       
  200.         // Provides a string representation of a character.
  201.         public static string ToString(char c)
  202.         {
  203.             return new string(c, 1);
  204.         }
  205.        
  206.         public static char Parse(string s)
  207.         {
  208.             if (s == null) {
  209.                 throw new ArgumentNullException("s");
  210.             }
  211.            
  212.             if (s.Length != 1) {
  213.                 throw new FormatException(Environment.GetResourceString("Format_NeedSingleChar"));
  214.             }
  215.             return s[0];
  216.         }
  217.        
  218.         public static bool TryParse(string s, out char result)
  219.         {
  220.             result = '\0';
  221.             if (s == null) {
  222.                 return false;
  223.             }
  224.             if (s.Length != 1) {
  225.                 return false;
  226.             }
  227.             result = s[0];
  228.             return true;
  229.         }
  230.        
  231.         //
  232.         // Static Methods
  233.         //
  234. /*=================================ISDIGIT======================================
  235.       **A wrapper for Char.  Returns a boolean indicating whether    **
  236.       **character c is considered to be a digit.                                    **
  237.       ==============================================================================*/       
  238.         // Determines whether a character is a digit.
  239.         public static bool IsDigit(char c)
  240.         {
  241.             if (IsLatin1(c)) {
  242.                 return (c >= '0' && c <= '9');
  243.             }
  244.             return (CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.DecimalDigitNumber);
  245.         }
  246.        
  247.        
  248. /*=================================CheckLetter=====================================
  249.       ** Check if the specified UnicodeCategory belongs to the letter categories.
  250.       ==============================================================================*/       
  251.         static internal bool CheckLetter(UnicodeCategory uc)
  252.         {
  253.             switch (uc) {
  254.                 case (UnicodeCategory.UppercaseLetter):
  255.                 case (UnicodeCategory.LowercaseLetter):
  256.                 case (UnicodeCategory.TitlecaseLetter):
  257.                 case (UnicodeCategory.ModifierLetter):
  258.                 case (UnicodeCategory.OtherLetter):
  259.                     return (true);
  260.             }
  261.             return (false);
  262.         }
  263.        
  264. /*=================================ISLETTER=====================================
  265.       **A wrapper for Char.  Returns a boolean indicating whether    **
  266.       **character c is considered to be a letter.                                  **
  267.       ==============================================================================*/       
  268.         // Determines whether a character is a letter.
  269.         public static bool IsLetter(char c)
  270.         {
  271.             if (IsLatin1(c)) {
  272.                 if (IsAscii(c)) {
  273.                     c |= (char)32;
  274.                     return ((c >= 'a' && c <= 'z'));
  275.                 }
  276.                 return (CheckLetter(GetLatin1UnicodeCategory(c)));
  277.             }
  278.             return (CheckLetter(CharUnicodeInfo.GetUnicodeCategory(c)));
  279.         }
  280.        
  281.         private static bool IsWhiteSpaceLatin1(char c)
  282.         {
  283.            
  284.             // There are characters which belong to UnicodeCategory.Control but are considered as white spaces.
  285.             // We use code point comparisons for these characters here as a temporary fix.
  286.            
  287.             // U+0009 = <control> HORIZONTAL TAB
  288.             // U+000a = <control> LINE FEED
  289.             // U+000b = <control> VERTICAL TAB
  290.             // U+000c = <contorl> FORM FEED
  291.             // U+000d = <control> CARRIAGE RETURN
  292.             // U+0085 = <control> NEXT LINE
  293.             // U+00a0 = NO-BREAK SPACE
  294.             if ((c == ' ') || (c >= '\t' && c <= '\r') || c == ' ' || c == '\u133') {
  295.                 return (true);
  296.             }
  297.             return (false);
  298.         }
  299.        
  300. /*===============================ISWHITESPACE===================================
  301.     **A wrapper for Char.  Returns a boolean indicating whether    **
  302.     **character c is considered to be a whitespace character.                    **
  303.     ==============================================================================*/       
  304.         // Determines whether a character is whitespace.
  305.         public static bool IsWhiteSpace(char c)
  306.         {
  307.            
  308.             if (IsLatin1(c)) {
  309.                 return (IsWhiteSpaceLatin1(c));
  310.             }
  311.             return CharUnicodeInfo.IsWhiteSpace(c);
  312.         }
  313.        
  314.        
  315. /*===================================IsUpper====================================
  316.         **Arguments: c -- the characater to be checked.
  317.         **Returns:  True if c is an uppercase character.
  318.         ==============================================================================*/       
  319.         // Determines whether a character is upper-case.
  320.         public static bool IsUpper(char c)
  321.         {
  322.             if (IsLatin1(c)) {
  323.                 if (IsAscii(c)) {
  324.                     return (c >= 'A' && c <= 'Z');
  325.                 }
  326.                 return (GetLatin1UnicodeCategory(c) == UnicodeCategory.UppercaseLetter);
  327.             }
  328.             return (CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.UppercaseLetter);
  329.         }
  330.        
  331. /*===================================IsLower====================================
  332.         **Arguments: c -- the characater to be checked.
  333.         **Returns:  True if c is an lowercase character.
  334.         ==============================================================================*/       
  335.         // Determines whether a character is lower-case.
  336.         public static bool IsLower(char c)
  337.         {
  338.             if (IsLatin1(c)) {
  339.                 if (IsAscii(c)) {
  340.                     return (c >= 'a' && c <= 'z');
  341.                 }
  342.                 return (GetLatin1UnicodeCategory(c) == UnicodeCategory.LowercaseLetter);
  343.             }
  344.             return (CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.LowercaseLetter);
  345.         }
  346.        
  347.         static internal bool CheckPunctuation(UnicodeCategory uc)
  348.         {
  349.             switch (uc) {
  350.                 case UnicodeCategory.ConnectorPunctuation:
  351.                 case UnicodeCategory.DashPunctuation:
  352.                 case UnicodeCategory.OpenPunctuation:
  353.                 case UnicodeCategory.ClosePunctuation:
  354.                 case UnicodeCategory.InitialQuotePunctuation:
  355.                 case UnicodeCategory.FinalQuotePunctuation:
  356.                 case UnicodeCategory.OtherPunctuation:
  357.                     return (true);
  358.             }
  359.             return (false);
  360.         }
  361.        
  362.        
  363. /*================================IsPunctuation=================================
  364.         **Arguments: c -- the characater to be checked.
  365.         **Returns:  True if c is an punctuation mark
  366.         ==============================================================================*/       
  367.         // Determines whether a character is a punctuation mark.
  368.         public static bool IsPunctuation(char c)
  369.         {
  370.             if (IsLatin1(c)) {
  371.                 return (CheckPunctuation(GetLatin1UnicodeCategory(c)));
  372.             }
  373.             return (CheckPunctuation(CharUnicodeInfo.GetUnicodeCategory(c)));
  374.         }
  375.        
  376. /*=================================CheckLetterOrDigit=====================================
  377.       ** Check if the specified UnicodeCategory belongs to the letter or digit categories.
  378.       ==============================================================================*/       
  379.         static internal bool CheckLetterOrDigit(UnicodeCategory uc)
  380.         {
  381.             switch (uc) {
  382.                 case UnicodeCategory.UppercaseLetter:
  383.                 case UnicodeCategory.LowercaseLetter:
  384.                 case UnicodeCategory.TitlecaseLetter:
  385.                 case UnicodeCategory.ModifierLetter:
  386.                 case UnicodeCategory.OtherLetter:
  387.                 case UnicodeCategory.DecimalDigitNumber:
  388.                     return (true);
  389.             }
  390.             return (false);
  391.         }
  392.        
  393.         // Determines whether a character is a letter or a digit.
  394.         public static bool IsLetterOrDigit(char c)
  395.         {
  396.             if (IsLatin1(c)) {
  397.                 return (CheckLetterOrDigit(GetLatin1UnicodeCategory(c)));
  398.             }
  399.             return (CheckLetterOrDigit(CharUnicodeInfo.GetUnicodeCategory(c)));
  400.         }
  401.        
  402. /*===================================ToUpper====================================
  403.       **
  404.       ==============================================================================*/       
  405.         // Converts a character to upper-case for the specified culture.
  406.         // <;<;Not fully implemented>;>;
  407.         public static char ToUpper(char c, CultureInfo culture)
  408.         {
  409.             if (culture == null)
  410.                 throw new ArgumentNullException("culture");
  411.             return culture.TextInfo.ToUpper(c);
  412.         }
  413.        
  414. /*=================================TOUPPER======================================
  415.       **A wrapper for Char.toUpperCase.  Converts character c to its **
  416.       **uppercase equivalent.  If c is already an uppercase character or is not an  **
  417.       **alphabetic, nothing happens.                                                **
  418.       ==============================================================================*/       
  419.         // Converts a character to upper-case for the default culture.
  420.         //
  421.         public static char ToUpper(char c)
  422.         {
  423.             return ToUpper(c, CultureInfo.CurrentCulture);
  424.         }
  425.        
  426.         // Converts a character to upper-case for invariant culture.
  427.         public static char ToUpperInvariant(char c)
  428.         {
  429.             return ToUpper(c, CultureInfo.InvariantCulture);
  430.         }
  431.        
  432. /*===================================ToLower====================================
  433.       **
  434.       ==============================================================================*/       
  435.         // Converts a character to lower-case for the specified culture.
  436.         // <;<;Not fully implemented>;>;
  437.         public static char ToLower(char c, CultureInfo culture)
  438.         {
  439.             if (culture == null)
  440.                 throw new ArgumentNullException("culture");
  441.             return culture.TextInfo.ToLower(c);
  442.         }
  443.        
  444. /*=================================TOLOWER======================================
  445.       **A wrapper for Char.toLowerCase.  Converts character c to its **
  446.       **lowercase equivalent.  If c is already a lowercase character or is not an  **
  447.       **alphabetic, nothing happens.                                                **
  448.       ==============================================================================*/       
  449.         // Converts a character to lower-case for the default culture.
  450.         public static char ToLower(char c)
  451.         {
  452.             return ToLower(c, CultureInfo.CurrentCulture);
  453.         }
  454.        
  455.         // Converts a character to lower-case for invariant culture.
  456.         public static char ToLowerInvariant(char c)
  457.         {
  458.             return ToLower(c, CultureInfo.InvariantCulture);
  459.         }
  460.        
  461.         //
  462.         // IValue implementation
  463.         //
  464.         public TypeCode GetTypeCode()
  465.         {
  466.             return TypeCode.Char;
  467.         }
  468.        
  469.        
  470.         /// <internalonly/>
  471.         bool IConvertible.ToBoolean(IFormatProvider provider)
  472.         {
  473.             throw new InvalidCastException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("InvalidCast_FromTo"), "Char", "Boolean"));
  474.         }
  475.        
  476.         /// <internalonly/>
  477.         char IConvertible.ToChar(IFormatProvider provider)
  478.         {
  479.             return m_value;
  480.         }
  481.        
  482.         /// <internalonly/>
  483.         sbyte IConvertible.ToSByte(IFormatProvider provider)
  484.         {
  485.             return Convert.ToSByte(m_value);
  486.         }
  487.        
  488.         /// <internalonly/>
  489.         byte IConvertible.ToByte(IFormatProvider provider)
  490.         {
  491.             return Convert.ToByte(m_value);
  492.         }
  493.        
  494.         /// <internalonly/>
  495.         short IConvertible.ToInt16(IFormatProvider provider)
  496.         {
  497.             return Convert.ToInt16(m_value);
  498.         }
  499.        
  500.         /// <internalonly/>
  501.         ushort IConvertible.ToUInt16(IFormatProvider provider)
  502.         {
  503.             return Convert.ToUInt16(m_value);
  504.         }
  505.        
  506.         /// <internalonly/>
  507.         int IConvertible.ToInt32(IFormatProvider provider)
  508.         {
  509.             return Convert.ToInt32(m_value);
  510.         }
  511.        
  512.         /// <internalonly/>
  513.         uint IConvertible.ToUInt32(IFormatProvider provider)
  514.         {
  515.             return Convert.ToUInt32(m_value);
  516.         }
  517.        
  518.         /// <internalonly/>
  519.         long IConvertible.ToInt64(IFormatProvider provider)
  520.         {
  521.             return Convert.ToInt64(m_value);
  522.         }
  523.        
  524.         /// <internalonly/>
  525.         ulong IConvertible.ToUInt64(IFormatProvider provider)
  526.         {
  527.             return Convert.ToUInt64(m_value);
  528.         }
  529.        
  530.         /// <internalonly/>
  531.         float IConvertible.ToSingle(IFormatProvider provider)
  532.         {
  533.             throw new InvalidCastException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("InvalidCast_FromTo"), "Char", "Single"));
  534.         }
  535.        
  536.         /// <internalonly/>
  537.         double IConvertible.ToDouble(IFormatProvider provider)
  538.         {
  539.             throw new InvalidCastException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("InvalidCast_FromTo"), "Char", "Double"));
  540.         }
  541.        
  542.         /// <internalonly/>
  543.         decimal IConvertible.ToDecimal(IFormatProvider provider)
  544.         {
  545.             throw new InvalidCastException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("InvalidCast_FromTo"), "Char", "Decimal"));
  546.         }
  547.        
  548.         /// <internalonly/>
  549.         DateTime IConvertible.ToDateTime(IFormatProvider provider)
  550.         {
  551.             throw new InvalidCastException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("InvalidCast_FromTo"), "Char", "DateTime"));
  552.         }
  553.        
  554.         /// <internalonly/>
  555.         object IConvertible.ToType(Type type, IFormatProvider provider)
  556.         {
  557.             return Convert.DefaultToType((IConvertible)this, type, provider);
  558.         }
  559.        
  560.         public static bool IsControl(char c)
  561.         {
  562.             if (IsLatin1(c)) {
  563.                 return (GetLatin1UnicodeCategory(c) == UnicodeCategory.Control);
  564.             }
  565.             return (CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.Control);
  566.         }
  567.        
  568.         public static bool IsControl(string s, int index)
  569.         {
  570.             if (s == null)
  571.                 throw new ArgumentNullException("s");
  572.             if (((uint)index) >= ((uint)s.Length)) {
  573.                 throw new ArgumentOutOfRangeException("index");
  574.             }
  575.             char c = s[index];
  576.             if (IsLatin1(c)) {
  577.                 return (GetLatin1UnicodeCategory(c) == UnicodeCategory.Control);
  578.             }
  579.             return (CharUnicodeInfo.GetUnicodeCategory(s, index) == UnicodeCategory.Control);
  580.         }
  581.        
  582.        
  583.         public static bool IsDigit(string s, int index)
  584.         {
  585.             if (s == null)
  586.                 throw new ArgumentNullException("s");
  587.             if (((uint)index) >= ((uint)s.Length)) {
  588.                 throw new ArgumentOutOfRangeException("index");
  589.             }
  590.             char c = s[index];
  591.             if (IsLatin1(c)) {
  592.                 return (c >= '0' && c <= '9');
  593.             }
  594.             return (CharUnicodeInfo.GetUnicodeCategory(s, index) == UnicodeCategory.DecimalDigitNumber);
  595.         }
  596.        
  597.         public static bool IsLetter(string s, int index)
  598.         {
  599.             if (s == null)
  600.                 throw new ArgumentNullException("s");
  601.             if (((uint)index) >= ((uint)s.Length)) {
  602.                 throw new ArgumentOutOfRangeException("index");
  603.             }
  604.             char c = s[index];
  605.             if (IsLatin1(c)) {
  606.                 if (IsAscii(c)) {
  607.                     c |= (char)32;
  608.                     return ((c >= 'a' && c <= 'z'));
  609.                 }
  610.                 return (CheckLetter(GetLatin1UnicodeCategory(c)));
  611.             }
  612.             return (CheckLetter(CharUnicodeInfo.GetUnicodeCategory(s, index)));
  613.         }
  614.        
  615.         public static bool IsLetterOrDigit(string s, int index)
  616.         {
  617.             if (s == null)
  618.                 throw new ArgumentNullException("s");
  619.             if (((uint)index) >= ((uint)s.Length)) {
  620.                 throw new ArgumentOutOfRangeException("index");
  621.             }
  622.             char c = s[index];
  623.             if (IsLatin1(c)) {
  624.                 return CheckLetterOrDigit(GetLatin1UnicodeCategory(c));
  625.             }
  626.             return CheckLetterOrDigit(CharUnicodeInfo.GetUnicodeCategory(s, index));
  627.         }
  628.        
  629.         public static bool IsLower(string s, int index)
  630.         {
  631.             if (s == null)
  632.                 throw new ArgumentNullException("s");
  633.             if (((uint)index) >= ((uint)s.Length)) {
  634.                 throw new ArgumentOutOfRangeException("index");
  635.             }
  636.             char c = s[index];
  637.             if (IsLatin1(c)) {
  638.                 if (IsAscii(c)) {
  639.                     return (c >= 'a' && c <= 'z');
  640.                 }
  641.                 return (GetLatin1UnicodeCategory(c) == UnicodeCategory.LowercaseLetter);
  642.             }
  643.            
  644.             return (CharUnicodeInfo.GetUnicodeCategory(s, index) == UnicodeCategory.LowercaseLetter);
  645.         }
  646.        
  647. /*=================================CheckNumber=====================================
  648.         ** Check if the specified UnicodeCategory belongs to the number categories.
  649.         ==============================================================================*/       
  650.        
  651.         static internal bool CheckNumber(UnicodeCategory uc)
  652.         {
  653.             switch (uc) {
  654.                 case (UnicodeCategory.DecimalDigitNumber):
  655.                 case (UnicodeCategory.LetterNumber):
  656.                 case (UnicodeCategory.OtherNumber):
  657.                     return (true);
  658.             }
  659.             return (false);
  660.         }
  661.        
  662.         public static bool IsNumber(char c)
  663.         {
  664.             if (IsLatin1(c)) {
  665.                 if (IsAscii(c)) {
  666.                     return (c >= '0' && c <= '9');
  667.                 }
  668.                 return (CheckNumber(GetLatin1UnicodeCategory(c)));
  669.             }
  670.             return (CheckNumber(CharUnicodeInfo.GetUnicodeCategory(c)));
  671.         }
  672.        
  673.         public static bool IsNumber(string s, int index)
  674.         {
  675.             if (s == null)
  676.                 throw new ArgumentNullException("s");
  677.             if (((uint)index) >= ((uint)s.Length)) {
  678.                 throw new ArgumentOutOfRangeException("index");
  679.             }
  680.             char c = s[index];
  681.             if (IsLatin1(c)) {
  682.                 if (IsAscii(c)) {
  683.                     return (c >= '0' && c <= '9');
  684.                 }
  685.                 return (CheckNumber(GetLatin1UnicodeCategory(c)));
  686.             }
  687.             return (CheckNumber(CharUnicodeInfo.GetUnicodeCategory(s, index)));
  688.         }
  689.        
  690.         ////////////////////////////////////////////////////////////////////////
  691.         //
  692.         // IsPunctuation
  693.         //
  694.         // Determines if the given character is a punctuation character.
  695.         //
  696.         ////////////////////////////////////////////////////////////////////////
  697.        
  698.         public static bool IsPunctuation(string s, int index)
  699.         {
  700.             if (s == null)
  701.                 throw new ArgumentNullException("s");
  702.             if (((uint)index) >= ((uint)s.Length)) {
  703.                 throw new ArgumentOutOfRangeException("index");
  704.             }
  705.             char c = s[index];
  706.             if (IsLatin1(c)) {
  707.                 return (CheckPunctuation(GetLatin1UnicodeCategory(c)));
  708.             }
  709.             return (CheckPunctuation(CharUnicodeInfo.GetUnicodeCategory(s, index)));
  710.         }
  711.        
  712.        
  713. /*================================= CheckSeparator ============================
  714.         ** Check if the specified UnicodeCategory belongs to the seprator categories.
  715.         ==============================================================================*/       
  716.        
  717.         static internal bool CheckSeparator(UnicodeCategory uc)
  718.         {
  719.             switch (uc) {
  720.                 case UnicodeCategory.SpaceSeparator:
  721.                 case UnicodeCategory.LineSeparator:
  722.                 case UnicodeCategory.ParagraphSeparator:
  723.                     return (true);
  724.             }
  725.             return (false);
  726.         }
  727.        
  728.         private static bool IsSeparatorLatin1(char c)
  729.         {
  730.             // U+00a0 = NO-BREAK SPACE
  731.             // There is no LineSeparator or ParagraphSeparator in Latin 1 range.
  732.             return (c == ' ' || c == ' ');
  733.         }
  734.        
  735.         public static bool IsSeparator(char c)
  736.         {
  737.             if (IsLatin1(c)) {
  738.                 return (IsSeparatorLatin1(c));
  739.             }
  740.             return (CheckSeparator(CharUnicodeInfo.GetUnicodeCategory(c)));
  741.         }
  742.        
  743.         public static bool IsSeparator(string s, int index)
  744.         {
  745.             if (s == null)
  746.                 throw new ArgumentNullException("s");
  747.             if (((uint)index) >= ((uint)s.Length)) {
  748.                 throw new ArgumentOutOfRangeException("index");
  749.             }
  750.             char c = s[index];
  751.             if (IsLatin1(c)) {
  752.                 return (IsSeparatorLatin1(c));
  753.             }
  754.             return (CheckSeparator(CharUnicodeInfo.GetUnicodeCategory(s, index)));
  755.         }
  756.        
  757.         public static bool IsSurrogate(char c)
  758.         {
  759.             return (c >= HIGH_SURROGATE_START && c <= LOW_SURROGATE_END);
  760.         }
  761.        
  762.         public static bool IsSurrogate(string s, int index)
  763.         {
  764.             if (s == null) {
  765.                 throw new ArgumentNullException("s");
  766.             }
  767.             if (((uint)index) >= ((uint)s.Length)) {
  768.                 throw new ArgumentOutOfRangeException("index");
  769.             }
  770.             return (IsSurrogate(s[index]));
  771.         }
  772.        
  773. /*================================= CheckSymbol ============================
  774.         ** Check if the specified UnicodeCategory belongs to the symbol categories.
  775.         ==============================================================================*/       
  776.        
  777.         static internal bool CheckSymbol(UnicodeCategory uc)
  778.         {
  779.             switch (uc) {
  780.                 case (UnicodeCategory.MathSymbol):
  781.                 case (UnicodeCategory.CurrencySymbol):
  782.                 case (UnicodeCategory.ModifierSymbol):
  783.                 case (UnicodeCategory.OtherSymbol):
  784.                     return (true);
  785.             }
  786.             return (false);
  787.         }
  788.        
  789.         public static bool IsSymbol(char c)
  790.         {
  791.             if (IsLatin1(c)) {
  792.                 return (CheckSymbol(GetLatin1UnicodeCategory(c)));
  793.             }
  794.             return (CheckSymbol(CharUnicodeInfo.GetUnicodeCategory(c)));
  795.         }
  796.        
  797.         public static bool IsSymbol(string s, int index)
  798.         {
  799.             if (s == null)
  800.                 throw new ArgumentNullException("s");
  801.             if (((uint)index) >= ((uint)s.Length)) {
  802.                 throw new ArgumentOutOfRangeException("index");
  803.             }
  804.             if (IsLatin1(s[index])) {
  805.                 return (CheckSymbol(GetLatin1UnicodeCategory(s[index])));
  806.             }
  807.             return (CheckSymbol(CharUnicodeInfo.GetUnicodeCategory(s, index)));
  808.         }
  809.        
  810.        
  811.         public static bool IsUpper(string s, int index)
  812.         {
  813.             if (s == null)
  814.                 throw new ArgumentNullException("s");
  815.             if (((uint)index) >= ((uint)s.Length)) {
  816.                 throw new ArgumentOutOfRangeException("index");
  817.             }
  818.             char c = s[index];
  819.             if (IsLatin1(c)) {
  820.                 if (IsAscii(c)) {
  821.                     return (c >= 'A' && c <= 'Z');
  822.                 }
  823.                 return (GetLatin1UnicodeCategory(c) == UnicodeCategory.UppercaseLetter);
  824.             }
  825.            
  826.             return (CharUnicodeInfo.GetUnicodeCategory(s, index) == UnicodeCategory.UppercaseLetter);
  827.         }
  828.        
  829.         public static bool IsWhiteSpace(string s, int index)
  830.         {
  831.             if (s == null)
  832.                 throw new ArgumentNullException("s");
  833.             if (((uint)index) >= ((uint)s.Length)) {
  834.                 throw new ArgumentOutOfRangeException("index");
  835.             }
  836.            
  837.             if (IsLatin1(s[index])) {
  838.                 return IsWhiteSpaceLatin1(s[index]);
  839.             }
  840.            
  841.             return CharUnicodeInfo.IsWhiteSpace(s, index);
  842.         }
  843.        
  844.         public static UnicodeCategory GetUnicodeCategory(char c)
  845.         {
  846.             if (IsLatin1(c)) {
  847.                 return (GetLatin1UnicodeCategory(c));
  848.             }
  849.             return CharUnicodeInfo.InternalGetUnicodeCategory(c);
  850.         }
  851.        
  852.         public static UnicodeCategory GetUnicodeCategory(string s, int index)
  853.         {
  854.             if (s == null)
  855.                 throw new ArgumentNullException("s");
  856.             if (((uint)index) >= ((uint)s.Length)) {
  857.                 throw new ArgumentOutOfRangeException("index");
  858.             }
  859.             if (IsLatin1(s[index])) {
  860.                 return (GetLatin1UnicodeCategory(s[index]));
  861.             }
  862.             return CharUnicodeInfo.InternalGetUnicodeCategory(s, index);
  863.         }
  864.        
  865.         public static double GetNumericValue(char c)
  866.         {
  867.             return CharUnicodeInfo.GetNumericValue(c);
  868.         }
  869.        
  870.         public static double GetNumericValue(string s, int index)
  871.         {
  872.             if (s == null)
  873.                 throw new ArgumentNullException("s");
  874.             if (((uint)index) >= ((uint)s.Length)) {
  875.                 throw new ArgumentOutOfRangeException("index");
  876.             }
  877.             return CharUnicodeInfo.GetNumericValue(s, index);
  878.         }
  879.        
  880.        
  881. /*================================= IsHighSurrogate ============================
  882.         ** Check if a char is a high surrogate.
  883.         ==============================================================================*/       
  884.         public static bool IsHighSurrogate(char c)
  885.         {
  886.             return ((c >= CharUnicodeInfo.HIGH_SURROGATE_START) && (c <= CharUnicodeInfo.HIGH_SURROGATE_END));
  887.         }
  888.        
  889.         public static bool IsHighSurrogate(string s, int index)
  890.         {
  891.             if (s == null) {
  892.                 throw new ArgumentNullException("s");
  893.             }
  894.             if (index < 0 || index >= s.Length) {
  895.                 throw new ArgumentOutOfRangeException("index");
  896.             }
  897.             return (IsHighSurrogate(s[index]));
  898.         }
  899.        
  900. /*================================= IsLowSurrogate ============================
  901.         ** Check if a char is a low surrogate.
  902.         ==============================================================================*/       
  903.         public static bool IsLowSurrogate(char c)
  904.         {
  905.             return ((c >= CharUnicodeInfo.LOW_SURROGATE_START) && (c <= CharUnicodeInfo.LOW_SURROGATE_END));
  906.         }
  907.        
  908.         public static bool IsLowSurrogate(string s, int index)
  909.         {
  910.             if (s == null) {
  911.                 throw new ArgumentNullException("s");
  912.             }
  913.             if (index < 0 || index >= s.Length) {
  914.                 throw new ArgumentOutOfRangeException("index");
  915.             }
  916.             return (IsLowSurrogate(s[index]));
  917.         }
  918.        
  919. /*================================= IsSurrogatePair ============================
  920.         ** Check if the string specified by the index starts with a surrogate pair.
  921.         ==============================================================================*/       
  922.         public static bool IsSurrogatePair(string s, int index)
  923.         {
  924.             if (s == null) {
  925.                 throw new ArgumentNullException("s");
  926.             }
  927.             if (index < 0 || index >= s.Length) {
  928.                 throw new ArgumentOutOfRangeException("index");
  929.             }
  930.             if (index + 1 < s.Length) {
  931.                 return (IsSurrogatePair(s[index], s[index + 1]));
  932.             }
  933.             return (false);
  934.         }
  935.        
  936.         public static bool IsSurrogatePair(char highSurrogate, char lowSurrogate)
  937.         {
  938.             return ((highSurrogate >= CharUnicodeInfo.HIGH_SURROGATE_START && highSurrogate <= CharUnicodeInfo.HIGH_SURROGATE_END) && (lowSurrogate >= CharUnicodeInfo.LOW_SURROGATE_START && lowSurrogate <= CharUnicodeInfo.LOW_SURROGATE_END));
  939.         }
  940.        
  941.         internal const int UNICODE_PLANE00_END = 65535;
  942.         // The starting codepoint for Unicode plane 1. Plane 1 contains 0x010000 ~ 0x01ffff.
  943.         internal const int UNICODE_PLANE01_START = 65536;
  944.         // The end codepoint for Unicode plane 16. This is the maximum code point value allowed for Unicode.
  945.         // Plane 16 contains 0x100000 ~ 0x10ffff.
  946.         internal const int UNICODE_PLANE16_END = 1114111;
  947.        
  948.         internal const int HIGH_SURROGATE_START = 55296;
  949.         internal const int LOW_SURROGATE_END = 57343;
  950.        
  951.        
  952.        
  953. /*================================= ConvertFromUtf32 ============================
  954.         ** Convert an UTF32 value into a surrogate pair.
  955.         ==============================================================================*/       
  956.        
  957.         public static string ConvertFromUtf32(int utf32)
  958.         {
  959.             // For UTF32 values from U+00D800 ~ U+00DFFF, we should throw. They
  960.             // are considered as irregular code unit sequence, but they are not illegal.
  961.             if ((utf32 < 0 || utf32 > UNICODE_PLANE16_END) || (utf32 >= HIGH_SURROGATE_START && utf32 <= LOW_SURROGATE_END)) {
  962.                 throw new ArgumentOutOfRangeException("utf32", Environment.GetResourceString("ArgumentOutOfRange_InvalidUTF32"));
  963.             }
  964.            
  965.             if (utf32 < UNICODE_PLANE01_START) {
  966.                 // This is a BMP character.
  967.                 return (Char.ToString((char)utf32));
  968.             }
  969.             // This is a sumplementary character. Convert it to a surrogate pair in UTF-16.
  970.             utf32 -= UNICODE_PLANE01_START;
  971.             char[] surrogate = new char[2];
  972.             surrogate[0] = (char)((utf32 / 1024) + (int)CharUnicodeInfo.HIGH_SURROGATE_START);
  973.             surrogate[1] = (char)((utf32 % 1024) + (int)CharUnicodeInfo.LOW_SURROGATE_START);
  974.             return (new string(surrogate));
  975.         }
  976.        
  977.        
  978. /*=============================ConvertToUtf32===================================
  979.         ** Convert a surrogate pair to UTF32 value                                   
  980.         ==============================================================================*/       
  981.        
  982.         public static int ConvertToUtf32(char highSurrogate, char lowSurrogate)
  983.         {
  984.             if (!IsHighSurrogate(highSurrogate)) {
  985.                 throw new ArgumentOutOfRangeException("highSurrogate", Environment.GetResourceString("ArgumentOutOfRange_InvalidHighSurrogate"));
  986.             }
  987.             if (!IsLowSurrogate(lowSurrogate)) {
  988.                 throw new ArgumentOutOfRangeException("lowSurrogate", Environment.GetResourceString("ArgumentOutOfRange_InvalidLowSurrogate"));
  989.             }
  990.             return (((highSurrogate - CharUnicodeInfo.HIGH_SURROGATE_START) * 1024) + (lowSurrogate - CharUnicodeInfo.LOW_SURROGATE_START) + UNICODE_PLANE01_START);
  991.         }
  992.        
  993. /*=============================ConvertToUtf32===================================
  994.         ** Convert a character or a surrogate pair starting at index of the specified string
  995.         ** to UTF32 value.
  996.         ** The char pointed by index should be a surrogate pair or a BMP character.
  997.         ** This method throws if a high-surrogate is not followed by a low surrogate.
  998.         ** This method throws if a low surrogate is seen without preceding a high-surrogate.
  999.         ==============================================================================*/       
  1000.        
  1001.         public static int ConvertToUtf32(string s, int index)
  1002.         {
  1003.             if (s == null) {
  1004.                 throw new ArgumentNullException("s");
  1005.             }
  1006.            
  1007.             if (index < 0 || index >= s.Length) {
  1008.                 throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
  1009.             }
  1010.             // Check if the character at index is a high surrogate.
  1011.             int temp1 = (int)s[index] - CharUnicodeInfo.HIGH_SURROGATE_START;
  1012.             if (temp1 >= 0 && temp1 <= 2047) {
  1013.                 // Found a surrogate char.
  1014.                 if (temp1 <= 1023) {
  1015.                     // Found a high surrogate.
  1016.                     if (index < s.Length - 1) {
  1017.                         int temp2 = (int)s[index + 1] - CharUnicodeInfo.LOW_SURROGATE_START;
  1018.                         if (temp2 >= 0 && temp2 <= 1023) {
  1019.                             // Found a low surrogate.
  1020.                             return ((temp1 * 1024) + temp2 + UNICODE_PLANE01_START);
  1021.                         }
  1022.                         else {
  1023.                             throw new ArgumentException(Environment.GetResourceString("Argument_InvalidHighSurrogate", index), "s");
  1024.                         }
  1025.                     }
  1026.                     else {
  1027.                         // Found a high surrogate at the end of the string.
  1028.                         throw new ArgumentException(Environment.GetResourceString("Argument_InvalidHighSurrogate", index), "s");
  1029.                     }
  1030.                 }
  1031.                 else {
  1032.                     // Find a low surrogate at the character pointed by index.
  1033.                     throw new ArgumentException(Environment.GetResourceString("Argument_InvalidLowSurrogate", index), "s");
  1034.                 }
  1035.             }
  1036.             // Not a high-surrogate or low-surrogate. Genereate the UTF32 value for the BMP characters.
  1037.             return ((int)s[index]);
  1038.         }
  1039.     }
  1040. }

Developer Fusion