HighlightReader.java

/*
 * Copyright © 2014-2025 The CTAN Team and individual authors
 *
 * This file is distributed under the 3-clause BSD license.
 * See file LICENSE for details.
 */

package org.ctan.markup.markdown.syntax;

import java.io.IOException;
import java.io.PushbackReader;
import java.io.Reader;

/**
 * This class establishes a reader which treats ``` as EOF.
 *
 * @author <a href="mailto:gene@ctan.org">Gerd Neugebauer</a>
 */
public class HighlightReader extends PushbackReader {

    /**
     * This is the constructor for <code>HighlightReader</code>.
     *
     * @param reader the reader
     */
    public HighlightReader(Reader reader) {

        super(reader, 64);
    }

    /**
     * {@inheritDoc}
     *
     * @see java.io.PushbackReader#close()
     */
    @Override
    public void close() throws IOException {

        // noop
    }

    /**
     * This method checks that the lookahead of several characters are identical
     * to the expected character. Then these are digested. Otherwise the
     * characters are pushed back into the input.
     *
     * @param s the expected characters
     *
     * @return {@code true} iff <i>n</i> characters have been found
     *
     * @throws IOException in case of an I/O error
     */
    public boolean expect(int... s) throws IOException {

        var i = 0;

        for (int c : s) {
            var cc = read();
            if (c != cc) {
                unread(cc);
                while (i-- > 0) {
                    unread(s[i]);
                }
                return false;
            }
            i++;
        }

        return true;
    }

    /**
     * {@inheritDoc}
     *
     * @see java.io.Reader#read()
     */
    @Override
    public int read() throws IOException {

        var c = super.read();
        if (c != '`') {
            return c;
        }
        c = super.read();
        if (c != '`') {
            unread(c);
            return '`';
        }
        c = super.read();
        if (c != '`') {
            unread(c);
            unread('`');
            return '`';
        }

        return -1;
    }

    /**
     * {@inheritDoc}
     *
     * @see java.io.Reader#read(char[], int, int)
     */
    @Override
    public int read(char[] cbuf, int off, int len) throws IOException {

        throw new UnsupportedOperationException();
    }

    /**
     * {@inheritDoc}
     *
     * @see java.io.PushbackReader#unread(int)
     */
    @Override
    public void unread(int c) throws IOException {

        if (c >= 0) {
            super.unread(c);
        }
    }

}