/*
Реализация среды исполнения языка программирования
Объектно-ориентированный продвинутый векторный транслятор
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;
}