DataOutputStream.avt

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

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

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

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

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

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

package avt.io;

import avt.io.charset.*;

public final class DataOutputStream(Object, Closeable, ByteWriter, Extendable)
{
    public static DataOutputStream create(ByteWriter writer, String charsetName) throws UnsupportedCharsetNameException {
        Charset charset = Charset.get(charsetName);
        return new DataOutputStream(writer, charset);
    }

    private Charset fldCharset;
    private final ByteWriter fldWriter;
    private final BigEndianDataOutput fldBigEndianDataOutput;
    private final LittleEndianDataOutput fldLittleEndianDataOutput;

    public (ByteWriter writer): this(writer, Charset.getDefault()) {  }

    public (ByteWriter writer, Charset charset) {
        if(charset == null) charset = Charset.getDefault();
        byte[] data = new byte[0x40];
        fldCharset = charset;
        fldWriter = writer;
        fldBigEndianDataOutput = new BigEndianDataOutput(writer, data) { fldCharset = charset };
        fldLittleEndianDataOutput = new LittleEndianDataOutput(writer, data) { fldCharset = charset };
    }

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

    public void write(int byteData) throws IOException { fldWriter.write(byteData); }

    public void write(byte[] src) throws IOException { fldWriter.write(src); }

    public void write(byte[] src, int offset, int length) throws IOException { fldWriter.write(src, offset, length); }

    public void flush() throws IOException { fldWriter.flush(); }

    public Extension[] getExtensions() { return fldWriter.getExtensions(); }

    public Extension getExtension(Class type) { return fldWriter.getExtension(type); }

    public ByteWriter writer { read = fldWriter }

    public Charset charset { read = fldCharset, write = setCharset }

    public DataOutput bigEndianDataOutput { read = fldBigEndianDataOutput }

    public DataOutput littleEndianDataOutput { read = fldLittleEndianDataOutput }

    private void setCharset(Charset newCharset) {
        if(newCharset == null) newCharset = Charset.getDefault();
        fldCharset = fldLittleEndianDataOutput.fldCharset = fldBigEndianDataOutput.fldCharset = newCharset;
    }
}

class LittleEndianDataOutput(Object, DataOutput)
{
    protected final byte[] fldData;
    protected final ByteWriter fldWriter;
    Charset fldCharset;

    public (ByteWriter writer, byte[] data) {
        fldData = data;
        fldWriter = writer;
    }

    public void write(byte[] src) throws IOException { fldWriter.write(src, 0, src == null ? 0 : src.length); }

    public void write(byte[] src, int offset, int length) throws IOException { fldWriter.write(src, offset, length); }

    public void writeBoolean(boolean data) throws IOException { fldWriter.write(data ? 1 : 0); }

    public native void writeChar(char data) throws IOException;

    public void writeByte(int data) throws IOException { fldWriter.write(data); }

    public native void writeShort(int data) throws IOException;

    public native void writeInt(int data) throws IOException;

    public native void writeByte2(int2 data) throws IOException;

    public native void writeShort2(int2 data) throws IOException;

    public native void writeInt2(int2 data) throws IOException;

    public native void writeByte4(int4 data) throws IOException;

    public native void writeShort4(int4 data) throws IOException;

    public native void writeInt4(int4 data) throws IOException;

    public native void writeByte8(int8 data) throws IOException;

    public native void writeShort8(int8 data) throws IOException;

    public native void writeInt8(int8 data) throws IOException;

    public native void writeLong(long data) throws IOException;

    public native void writeLong2(long2 data) throws IOException;

    public native void writeLong4(long4 data) throws IOException;

    public native void writeLong8(long8 data) throws IOException;

    public native void writeFloat(float data) throws IOException;

    public native void writeFloat2(float2 data) throws IOException;

    public native void writeFloat4(float4 data) throws IOException;

    public native void writeFloat8(float8 data) throws IOException;

    public native void writeDouble(double data) throws IOException;

    public native void writeDouble2(double2 data) throws IOException;

    public native void writeDouble4(double4 data) throws IOException;

    public native void writeDouble8(double8 data) throws IOException;

    public native void writeReal(real data) throws IOException;

    public void writeUTF(String data) throws IOException {
        int stringLength;
        if(data == null || (stringLength = data.length) <= 0)
        {
            writeShort(0);
            return;
        }
        if(stringLength > 0x00010000) stringLength = 0x00010000;
        char[] stringData = new char[stringLength];
        data.getChars(0, stringLength, stringData, 0);
        int resultLength = 0;
        for(int index = stringLength; index-- > 0; )
        {
            int chr = stringData[index];
            if((resultLength += chr > 0x0000 && chr < 0x0080 ? 1 : chr < 0x0800 ? 2 : 3) > 0xffff)
            {
                throw new UTFDataFormatException(package.getResourceString("invalid-data-format.utf.too-long"));
            }
        }
        byte[] resultData = new byte[resultLength];
        for(int index = 0; index < stringLength; index++)
        {
            int chr = stringData[index];
            if(chr > 0x0000 && chr < 0x0080)
            {
                resultData[resultLength++] = (byte) chr;
                continue;
            }
            if(chr < 0x0800)
            {
                resultData[resultLength++] = (byte) (0xc0 | (chr >> 6) & 0x1f);
                resultData[resultLength++] = (byte) (0x80 | chr & 0x3f);
                continue;
            }
            resultData[resultLength++] = (byte) (0xe0 | (chr >> 12) & 0x0f);
            resultData[resultLength++] = (byte) (0x80 | (chr >> 6) & 0x3f);
            resultData[resultLength++] = (byte) (0x80 | chr & 0x3f);
        }
        writeShort(resultLength);
        write(resultData, 0, resultLength);
    }

    public void writeln(String data) throws IOException {
        Charset charset = fldCharset;
        ByteWriter writer = fldWriter;
        if(data != null) writer.write(data.toByteArray(charset));
        writer.write(Platform.instance.lineSeparator.toByteArray(charset));
    }

    public void write(String data) throws IOException {
        Charset charset = fldCharset;
        ByteWriter writer = fldWriter;
        if(data != null) writer.write(data.toByteArray(charset));
        writer.write("\u0020".toByteArray(charset));
    }

    protected void writeData(int length) throws IOException {
        fldWriter.write(fldData, 0, length);
    }
}

class BigEndianDataOutput(LittleEndianDataOutput)
{
    public (ByteWriter writer, byte[] data): super(writer, data) {  }

    protected native void writeData(int length) throws IOException;
}