CharInputStream.avt

Переключить прокрутку окна
Загрузить этот исходный код

/*
    Реализация среды исполнения языка программирования
    Объектно-ориентированный продвинутый векторный транслятор

    Copyright © 2021, 2024 Малик Разработчик

    Это свободная программа: вы можете перераспространять ее и/или изменять
    ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
    в каком она была опубликована Фондом свободного программного обеспечения;
    либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.

    Эта программа распространяется в надежде, что она будет полезной,
    но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
    или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
    общественной лицензии GNU.

    Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
    вместе с этой программой. Если это не так, см.
    <https://www.gnu.org/licenses/>.
*/

package avt.io;

import avt.io.charset.*;
import avt.io.extension.*;

public final class CharInputStream(Object, Closeable, CharReader, Extendable)
{
    public static CharInputStream create(ByteReader reader, String charsetName) throws UnsupportedCharsetNameException {
        CharDecoder decoder = Charset.get(charsetName).newDecoder();
        return new CharInputStream(reader, decoder);
    }

    private CharDecoder fldDecoder;
    private final ByteReader fldReader;
    private final CharInputStreamMarkExtension fldMarkExtension;
    private final CharInputStreamStreamedExtension fldStreamedExtension;

    public (ByteReader reader): this(reader, Charset.getDefault().newDecoder()) {  }

    public (ByteReader reader, CharDecoder decoder) {
        LimitedSizeExtension ext1 = null;
        MarkExtension ext0 = null;
        if(reader != null)
        {
            ext0 = (MarkExtension) reader.getExtension(MarkExtension.class);
            ext1 = (LimitedSizeExtension) reader.getExtension(LimitedSizeExtension.class);
        }
        fldDecoder = decoder != null ? decoder : Charset.getDefault().newDecoder();
        fldReader = reader;
        fldMarkExtension = ext0 == null ? null : new CharInputStreamMarkExtension(ext0);
        fldStreamedExtension = new CharInputStreamStreamedExtension(ext1);
    }

    public void close() throws IOException { fldReader.close(); }

    public int read() throws IOException {
        CharactersBuffer stream = readChars(1);
        return stream.length < 1 ? -1 : stream[0];
    }

    public int read(char[] dst, int offset, int length) throws IOException {
        if(dst == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "dst" }));
        }
        Array.checkBounds(dst, offset, length);
        if(length <= 0) return 0;
        CharactersBuffer stream = readChars(length);
        int result = Int.min(stream.length, length);
        if(result <= 0) return -1;
        stream.getChars(0, result, dst, offset);
        return result;
    }

    public long skip(long charsQuantity) throws IOException {
        if(charsQuantity <= 0L) return 0L;
        long result = 0L;
        for(char[] buffer = new char[224]; charsQuantity > 0L; )
        {
            long skipped = (long) read(buffer, 0, (int) Long.min(charsQuantity, 224L));
            if(skipped < 0L) break;
            charsQuantity -= skipped;
            result += skipped;
        }
        return result;
    }

    public Extension[] getExtensions() {
        Extension ext1 = fldMarkExtension;
        Extension ext0 = fldStreamedExtension;
        return ext1 == null ? new Extension[] { ext0 } : new Extension[] { ext0, ext1 };
    }

    public Extension getExtension(Class type) {
        Extension ext = fldStreamedExtension;
        if(type == null || type.isAssignableFrom(ext.getClass())) return ext;
        return (ext = fldMarkExtension) != null && (type == null || type.isAssignableFrom(ext.getClass())) ? ext : null;
    }

    public ByteReader reader { read = fldReader }

    public CharDecoder decoder { read = fldDecoder, write = setDecoder }

    private void setDecoder(CharDecoder newDecoder) { fldDecoder = newDecoder != null ? newDecoder : Charset.getDefault().newDecoder(); }

    private CharactersBuffer readChars(int length) throws CharacterDecodingException, IOException {
        ByteReader src = fldReader;
        CharDecoder decoder = fldDecoder;
        CharInputStreamStreamedExtension ext = fldStreamedExtension;
        CharactersBuffer dst = ext.fldCharactersBuffer;
        dst.discard(ext.fldCharactersReaded);
        ext.fldCharactersReaded = Int.MAX_VALUE;
        for(int readed = -1; readed != (readed = dst.length) && readed < length; )
        {
            int remained = length - readed;
            decoder.decodeToWriter(dst, src, remained >= Int.MAX_VALUE - 6 ? Int.MAX_VALUE : remained + 6);
        }
        ext.fldCharactersReaded = length;
        return dst;
    }
}

class CharInputStreamMarkExtension(Object, Extension, MarkExtension)
{
    private final MarkExtension fldMarkExtension;

    (MarkExtension ext) { fldMarkExtension = ext; }

    public void reset() throws IOException { fldMarkExtension.reset(); }

    public void mark(int transferLimit) { fldMarkExtension.mark(transferLimit); }
}

class CharInputStreamStreamedExtension(Object, Extension, StreamedExtension)
{
    int fldCharactersReaded;
    final CharactersBuffer fldCharactersBuffer;
    private final LimitedSizeExtension fldLimitedSizeExtension;

    (LimitedSizeExtension ext) {
        fldCharactersBuffer = new CharactersBuffer();
        fldLimitedSizeExtension = ext;
    }

    public boolean ready() throws IOException {
        LimitedSizeExtension ext;
        return fldCharactersBuffer.length > fldCharactersReaded || (ext = fldLimitedSizeExtension) != null && ext.available() > 0L;
    }
}