/// <summary>
        /// Advances the enumerator to the next element of the collection.
        /// </summary>
        /// <returns>
        /// <see langword="true"/> if the enumerator was successfully advanced to the next element;
        /// <see langword="false"/> if the enumerator has passed the end of the collection.
        /// </returns>
        public bool MoveNext()
        {
            // Get the first char if we're at the beginning of the string.
            if (this.first)
            {
                LineBreakClass firstClass = this.NextCharClass();
                this.first        = false;
                this.currentClass = this.MapFirst(firstClass);
                this.nextClass    = firstClass;
                this.lb8a         = firstClass == LineBreakClass.ZWJ;
                this.lb30a        = 0;
            }

            while (this.position < this.pointsLength)
            {
                this.lastPosition = this.position;
                LineBreakClass lastClass = this.nextClass;
                this.nextClass = this.NextCharClass();

                // Explicit newline
                switch (this.currentClass)
                {
                case LineBreakClass.BK:
                case LineBreakClass.CR when this.nextClass != LineBreakClass.LF:
                    this.currentClass = this.MapFirst(this.nextClass);
                    this.Current      = new LineBreak(this.FindPriorNonWhitespace(this.lastPosition), this.lastPosition, true);
                    return(true);
                }

                bool?shouldBreak = this.GetSimpleBreak() ?? (bool?)this.GetPairTableBreak(lastClass);

                // Rule LB8a
                this.lb8a = this.nextClass == LineBreakClass.ZWJ;

                if (shouldBreak.Value)
                {
                    this.Current = new LineBreak(this.FindPriorNonWhitespace(this.lastPosition), this.lastPosition, false);
                    return(true);
                }
            }

            if (this.position >= this.pointsLength && this.lastPosition < this.pointsLength)
            {
                this.lastPosition = this.pointsLength;
                bool required = false;
                switch (this.currentClass)
                {
                case LineBreakClass.BK:
                case LineBreakClass.CR when this.nextClass != LineBreakClass.LF:
                    required = true;
                    break;
                }

                this.Current = new LineBreak(this.FindPriorNonWhitespace(this.pointsLength), this.lastPosition, required);
                return(true);
            }

            this.Current = default;
            return(false);
        }
예제 #2
0
        /// <summary>
        /// Returns the line break from the current code points if one is found.
        /// </summary>
        /// <param name="lineBreak">
        /// When this method returns, contains the value associate with the break;
        /// otherwise, the default value.
        /// This parameter is passed uninitialized.</param>
        /// <returns>The <see cref="bool"/>.</returns>
        public bool TryGetNextBreak(out LineBreak lineBreak)
        {
            // get the first char if we're at the beginning of the string
            if (this.first)
            {
                this.first = false;
                LineBreakClass firstClass = this.NextCharClass();
                this.currentClass = this.MapFirst(firstClass);
                this.nextClass    = firstClass;
                this.lb8a         = firstClass == LineBreakClass.ZWJ;
                this.lb30a        = 0;
            }

            while (this.position < this.codePoints.Length)
            {
                this.lastPosition = this.position;
                LineBreakClass lastClass = this.nextClass;
                this.nextClass = this.NextCharClass();

                // explicit newline
                if ((this.currentClass == LineBreakClass.BK) || ((this.currentClass == LineBreakClass.CR) && (this.nextClass != LineBreakClass.LF)))
                {
                    this.currentClass = this.MapFirst(this.MapClass(this.nextClass));
                    lineBreak         = new LineBreak(this.FindPriorNonWhitespace(this.lastPosition), this.lastPosition, true);
                    return(true);
                }

                bool?shouldBreak = this.GetSimpleBreak();

                if (!shouldBreak.HasValue)
                {
                    shouldBreak = this.GetPairTableBreak(lastClass);
                }

                // Rule LB8a
                this.lb8a = this.nextClass == LineBreakClass.ZWJ;

                if (shouldBreak.Value)
                {
                    lineBreak = new LineBreak(this.FindPriorNonWhitespace(this.lastPosition), this.lastPosition, false);
                    return(true);
                }
            }

            if (this.lastPosition < this.codePoints.Length)
            {
                this.lastPosition = this.codePoints.Length;
                bool required = (this.currentClass == LineBreakClass.BK) || ((this.currentClass == LineBreakClass.CR) && (this.nextClass != LineBreakClass.LF));
                lineBreak = new LineBreak(this.FindPriorNonWhitespace(this.codePoints.Length), this.lastPosition, required);
                return(true);
            }
            else
            {
                lineBreak = default;
                return(false);
            }
        }