Пример #1
0
        /// <summary>
        /// Check if a position in a code point buffer is a grapheme cluster boundary
        /// </summary>
        /// <param name="codePoints">The code points</param>
        /// <param name="position">The position to check</param>
        /// <returns></returns>
        public static bool IsBoundary(Slice <int> codePoints, int position)
        {
            if (codePoints.Length == 0)
            {
                return(false);
            }

            // Get the grapheme cluster class of the character on each side
            var a = position <= 0 ? GraphemeClusterClass.SOT : UnicodeClasses.GraphemeClusterClass(codePoints[position - 1]);
            var b = position < codePoints.Length ? UnicodeClasses.GraphemeClusterClass(codePoints[position]) : GraphemeClusterClass.EOT;

            // Rule 11 - Special handling for ZWJ in extended pictograph
            if (a == GraphemeClusterClass.ZWJ)
            {
                var i = position - 2;
                while (i >= 0 && UnicodeClasses.GraphemeClusterClass(codePoints[i]) == GraphemeClusterClass.Extend)
                {
                    i--;
                }

                if (i >= 0 && UnicodeClasses.GraphemeClusterClass(codePoints[i]) == GraphemeClusterClass.ExtPict)
                {
                    a = GraphemeClusterClass.ExtPictZwg;
                }
            }

            // Special handling for regional indicator
            // Rule 12 and 13
            if (a == GraphemeClusterClass.Regional_Indicator)
            {
                // Count how many
                int count = 0;
                for (int i = position - 1; i > 0; i--)
                {
                    if (UnicodeClasses.GraphemeClusterClass(codePoints[i - 1]) != GraphemeClusterClass.Regional_Indicator)
                    {
                        break;
                    }
                    count++;
                }

                // If odd, switch from RI to Any
                if ((count % 2) != 0)
                {
                    a = GraphemeClusterClass.Any;
                }
            }


            return(pairTable[(int)b][(int)a] != 0);
        }