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); }
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); }