Exemplo n.º 1
0
        public bool MoveNext()
        {
            // get the first char if we're at the beginning of the string
            if (!_curClass.HasValue)
            {
                _curClass = PeekCharClass() == LineBreakClass.Space ? LineBreakClass.WordJoiner : MapFirst(ReadCharClass());
            }

            while (_pos < _text.Length)
            {
                _lastPos = _pos;
                var lastClass = _nextClass;
                _nextClass = ReadCharClass();

                // explicit newline
                if (_curClass.HasValue && (_curClass == LineBreakClass.MandatoryBreak || _curClass == LineBreakClass.CarriageReturn && _nextClass != LineBreakClass.LineFeed))
                {
                    _curClass = MapFirst(MapClass(_nextClass.Value));
                    Current   = new LineBreak(FindPriorNonWhitespace(_lastPos), _lastPos, true);
                    return(true);
                }

                // handle classes not handled by the pair table
                LineBreakClass?cur = null;
                switch (_nextClass.Value)
                {
                case LineBreakClass.Space:
                    cur = _curClass;
                    break;

                case LineBreakClass.MandatoryBreak:
                case LineBreakClass.LineFeed:
                case LineBreakClass.NextLine:
                    cur = LineBreakClass.MandatoryBreak;
                    break;

                case LineBreakClass.CarriageReturn:
                    cur = LineBreakClass.CarriageReturn;
                    break;

                case LineBreakClass.ContingentBreak:
                    cur = LineBreakClass.BreakAfter;
                    break;
                }

                if (cur != null)
                {
                    _curClass = cur;

                    if (_nextClass.Value == LineBreakClass.MandatoryBreak)
                    {
                        _lastPos = _pos;
                        Current  = new LineBreak(FindPriorNonWhitespace(_lastPos), _lastPos, true);
                        return(true);
                    }

                    continue;
                }

                // if not handled already, use the pair table
                var shouldBreak = false;
                switch (BreakPairTable.Map(_curClass.Value, _nextClass.Value))
                {
                case PairBreakType.DI:     // Direct break
                    shouldBreak = true;
                    _lastPos    = _pos;
                    break;

                case PairBreakType.IN:     // possible indirect break
                    shouldBreak = lastClass.HasValue && lastClass.Value == LineBreakClass.Space;
                    break;

                case PairBreakType.CI:
                    shouldBreak = lastClass.HasValue && lastClass.Value == LineBreakClass.Space;
                    if (!shouldBreak)
                    {
                        continue;
                    }
                    break;

                case PairBreakType.CP:     // prohibited for combining marks
                    if (!lastClass.HasValue || lastClass.Value != LineBreakClass.Space)
                    {
                        continue;
                    }
                    break;
                }

                _curClass = _nextClass;

                if (shouldBreak)
                {
                    Current = new LineBreak(FindPriorNonWhitespace(_lastPos), _lastPos);
                    return(true);
                }
            }

            if (_pos >= _text.Length)
            {
                if (_lastPos < _text.Length)
                {
                    _lastPos = _text.Length;
                    var  cls      = Codepoint.ReadAt(_text, _text.Length - 1, out _).LineBreakClass;
                    bool required = cls == LineBreakClass.MandatoryBreak || cls == LineBreakClass.LineFeed || cls == LineBreakClass.CarriageReturn;
                    Current = new LineBreak(FindPriorNonWhitespace(_text.Length), _text.Length, required);
                    return(true);
                }
            }

            return(false);
        }
Exemplo n.º 2
0
        public bool MoveNext()
        {
            // Get the first char if we're at the beginning of the string.
            if (_first)
            {
                var firstClass = NextCharClass();
                _first        = false;
                _currentClass = MapFirst(firstClass);
                _nextClass    = firstClass;
                _lb8a         = firstClass == LineBreakClass.ZWJ;
                _lb30a        = 0;
            }

            while (_position < _text.Length)
            {
                _lastPosition = _position;
                var lastClass = _nextClass;
                _nextClass = NextCharClass();

                // Explicit newline
                switch (_currentClass)
                {
                case LineBreakClass.MandatoryBreak:
                case LineBreakClass.CarriageReturn when _nextClass != LineBreakClass.LineFeed:
                {
                    _currentClass = MapFirst(_nextClass);
                    Current       = new LineBreak(FindPriorNonWhitespace(_lastPosition), _lastPosition, true);
                    return(true);
                }
                }

                var shouldBreak = GetSimpleBreak() ?? GetPairTableBreak(lastClass);

                // Rule LB8a
                _lb8a = _nextClass == LineBreakClass.ZWJ;

                if (shouldBreak)
                {
                    Current = new LineBreak(FindPriorNonWhitespace(_lastPosition), _lastPosition);
                    return(true);
                }
            }

            if (_position >= _text.Length)
            {
                if (_lastPosition < _text.Length)
                {
                    _lastPosition = _text.Length;

                    var required = false;

                    switch (_currentClass)
                    {
                    case LineBreakClass.MandatoryBreak:
                    case LineBreakClass.CarriageReturn when _nextClass != LineBreakClass.LineFeed:
                        required = true;
                        break;
                    }

                    Current = new LineBreak(FindPriorNonWhitespace(_lastPosition), _lastPosition, required);
                    return(true);
                }
            }

            Current = default;

            return(false);
        }