class StrictLineBreakIterator extends BreakIterator {

    private final List<Integer> breaks = new ArrayList<>();
    private char peekChar = CharacterIterator.DONE;
    private CharacterIterator charIt;
    private int breakOffset = -1;

    public StrictLineBreakIterator() {
        charIt = new StringCharacterIterator("");
    }

    @Override
    public int first() {
        breaks.clear();
        breakOffset = -1;
        charIt.first();
        return 0;
    }

    @Override
    public int last() {
        int c;
        do {
            c = current();
        } while (next() != BreakIterator.DONE);
        return c;
    }

    @Override
    public int next(int n) {
        if (n < 0) {
            throw new IllegalArgumentException("n cannot be negative");
        }

        int noff = current();
        for (int i = 0; i < n; ++i) {
            noff = next();
            if (noff == BreakIterator.DONE) {
                return noff;
            }
        }
        return noff;
    }

    @Override
    public int next() {<FILL_FUNCTION_BODY>}

    @Override
    public int previous() {
        if (breakOffset >= 0) {
            if (--breakOffset >= 0) {
                return breaks.get(breakOffset);
            }
            return 0;
        }
        return BreakIterator.DONE;
    }

    @Override
    public int following(int offset) {
        if (!breaks.isEmpty() && breaks.get(breaks.size() - 1) > offset) {
            int lo = 0;
            int hi = breaks.size() - 1;
            int mid;
            while (lo <= hi) {
                mid = lo + (hi - lo) / 2;
                int boff = breaks.get(mid);
                if (offset < boff) {
                    if (mid < 1 || offset >= breaks.get(mid - 1)) {
                        return boff;
                    } else {
                        hi = mid - 1;
                    }
                } else {
                    lo = mid + 1;
                }
            }
            // This should not be reached.
            return BreakIterator.DONE;
        }

        int noff;
        do {
            noff = next();
            if (noff > offset) {
                return noff;
            }
        } while (noff != BreakIterator.DONE);
        return noff;
    }

    @Override
    public int current() {
        if (breakOffset < 0) {
            return 0;
        }
        return breakOffset < breaks.size() ? breaks.get(breakOffset) :
            charIt.current();
    }

    @Override
    public CharacterIterator getText() {
        return (CharacterIterator) charIt.clone();
    }

    @Override
    public void setText(CharacterIterator newText) {
        if (newText == null) {
            throw new IllegalArgumentException("newText is null");
        }
        this.charIt = newText;
        this.breaks.clear();
        this.peekChar = newText.current();
        this.breakOffset = -1;
    }
}

        if (breakOffset + 1 < breaks.size()) {
            return breaks.get(++breakOffset);
        }

        char lastChar = CharacterIterator.DONE;
        int charOff;
        while (true) {
            char nextChar;
            if (peekChar != CharacterIterator.DONE) {
                nextChar = peekChar;
                peekChar = CharacterIterator.DONE;
            } else {
                nextChar = charIt.next();
            }

            switch (nextChar) {
                case CharacterIterator.DONE:
                    if (lastChar != CharacterIterator.DONE) {
                        charOff = charIt.getIndex();
                        breaks.add(charOff);
                        ++breakOffset;
                        return charOff;
                    } else {
                        return BreakIterator.DONE;
                    }
                case '\n':
                    // charOff is just past the LF
                    charOff = charIt.getIndex() + 1;
                    breaks.add(charOff);
                    ++breakOffset;
                    return charOff;
                case '\r':
                    charOff = charIt.getIndex() + 1;
                    peekChar = charIt.next();
                    switch (peekChar) {
                        case '\n':
                            peekChar = CharacterIterator.DONE;
                            // charOff is just past the LF
                            ++charOff;
                            breaks.add(charOff);
                            ++breakOffset;
                            return charOff;
                        case CharacterIterator.DONE:
                        default:
                            breaks.add(charOff);
                            ++breakOffset;
                            return charOff;
                    }
                default:
                    lastChar = nextChar;
                    break;
            }
        }
    
<methods>public java.lang.Object clone() ,public abstract int current() ,public abstract int first() ,public abstract int following(int) ,public static synchronized java.util.Locale[] getAvailableLocales() ,public static java.text.BreakIterator getCharacterInstance() ,public static java.text.BreakIterator getCharacterInstance(java.util.Locale) ,public static java.text.BreakIterator getLineInstance() ,public static java.text.BreakIterator getLineInstance(java.util.Locale) ,public static java.text.BreakIterator getSentenceInstance() ,public static java.text.BreakIterator getSentenceInstance(java.util.Locale) ,public abstract java.text.CharacterIterator getText() ,public static java.text.BreakIterator getWordInstance() ,public static java.text.BreakIterator getWordInstance(java.util.Locale) ,public boolean isBoundary(int) ,public abstract int last() ,public abstract int next() ,public abstract int next(int) ,public int preceding(int) ,public abstract int previous() ,public void setText(java.lang.String) ,public abstract void setText(java.text.CharacterIterator) <variables>private static final int CHARACTER_INDEX,public static final int DONE,private static final int LINE_INDEX,private static final int SENTENCE_INDEX,private static final int WORD_INDEX,private static final SoftReference<java.text.BreakIterator.BreakIteratorCache>[] iterCache