package org.simantics.scl.runtime.io; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.charset.Charset; import gnu.trove.list.array.TByteArrayList; public class SclIO { private static final Charset UTF8 = Charset.forName("UTF-8"); public static byte readByte(InputStream in) throws IOException { int ch1 = in.read(); if(ch1 < 0) throw new EOFException(); return (byte)ch1; } public static boolean readBoolean(InputStream in) throws IOException { int ch1 = in.read(); if(ch1 < 0) throw new EOFException(); return ch1 != 0; } public static char readCharacter(InputStream in) throws IOException { int ch1 = in.read(); int ch2 = in.read(); if ((ch1 | ch2) < 0) throw new EOFException(); return (char)((ch1 << 8) + ch2); } public static short readShort(InputStream in) throws IOException { int ch1 = in.read(); int ch2 = in.read(); if ((ch1 | ch2) < 0) throw new EOFException(); return (short)((ch1 << 8) + ch2); } public static int readInteger(InputStream in) throws IOException { int ch1 = in.read(); int ch2 = in.read(); int ch3 = in.read(); int ch4 = in.read(); if ((ch1 | ch2 | ch3 | ch4) < 0) throw new EOFException(); return (ch1 << 24) + (ch2 << 16) + (ch3 << 8) + ch4; } public static long readLong(InputStream in) throws IOException { int ch1 = in.read(); int ch2 = in.read(); int ch3 = in.read(); int ch4 = in.read(); int ch5 = in.read(); int ch6 = in.read(); int ch7 = in.read(); int ch8 = in.read(); if ((ch1 | ch2 | ch3 | ch4 | ch5 | ch6 | ch7 | ch8) < 0) throw new EOFException(); return ((long)ch1 << 56) + ((long)ch2 << 48) + ((long)ch3 << 40) + ((long)ch4 << 32) + ((long)ch5 << 24) + (ch6 << 16) + (ch7 << 8) + ch8; } public static float readFloat(InputStream in) throws IOException { return Float.intBitsToFloat(readInteger(in)); } public static double readDouble(InputStream in) throws IOException { return Double.longBitsToDouble(readLong(in)); } public static int readLength(InputStream in) throws IOException { int length = in.read()&0xff; if(length >= 0x80) { if(length >= 0xc0) { if(length >= 0xe0) { if(length >= 0xf0) { length &= 0x0f; length += in.read()<<3; length += in.read()<<11; length += in.read()<<19; length += 0x10204080; } else { length &= 0x1f; length += in.read()<<4; length += in.read()<<12; length += in.read()<<20; length += 0x204080; } } else { length &= 0x3f; length += in.read()<<5; length += in.read()<<13; length += 0x4080; } } else { length &= 0x7f; length += in.read()<<6; length += 0x80; } } return length; } private static byte[] readFully(InputStream in, int length) throws IOException { byte[] result = new byte[length]; int cur = 0; while(cur < length) { int c = in.read(result, cur, length-cur); if(c <= 0) throw new EOFException(); cur += c; } return result; } public static byte[] readByteArray(InputStream in) throws IOException { int length = readLength(in); return readFully(in, length); } public static double[] readDoubleArray(InputStream in) throws IOException { int length = readLength(in); double[] result = new double[length]; for(int i=0;i>> 8)); out.write((int)(v)); } public static void writeShort(OutputStream out, short v) throws IOException { out.write((int)(v >>> 8)); out.write((int)(v)); } public static void writeInteger(OutputStream out, int v) throws IOException { out.write(v >>> 24); out.write(v >>> 16); out.write(v >>> 8); out.write(v); } public static void writeLong(OutputStream out, long v) throws IOException { out.write((int)(v >>> 56)); out.write((int)(v >>> 48)); out.write((int)(v >>> 40)); out.write((int)(v >>> 32)); out.write((int)(v >>> 24)); out.write((int)(v >>> 16)); out.write((int)(v >>> 8)); out.write((int)v); } public static void writeFloat(OutputStream out, float v) throws IOException { writeInteger(out, Float.floatToRawIntBits(v)); } public static void writeDouble(OutputStream out, double v) throws IOException { writeLong(out, Double.doubleToRawLongBits(v)); } public static void writeLength(OutputStream out, int length) throws IOException { if(length < 0x80) { out.write(length); } else { length -= 0x80; if(length < 0x4000) { out.write( ((length&0x3f) | 0x80) ); out.write( (length>>>6) ); } else { length -= 0x4000; if(length < 0x200000) { out.write( (length&0x1f) | 0xc0 ); out.write( length>>>5 ); out.write( length>>>13 ); } else { length -= 0x200000; if(length < 0x10000000) { out.write( (length&0x0f) | 0xe0 ); out.write( length>>>4 ); out.write( length>>>12 ); out.write( length>>>20 ); } else { length -= 0x10000000; out.write( ((length&0x07) | 0xf0) ); out.write( length>>>3 ); out.write( length>>>11 ); out.write( length>>>19 ); out.write( length>>>27 ); } } } } } public static void writeByteArray(OutputStream out, byte[] v) throws IOException { writeLength(out, v.length); out.write(v); } public static void writeDoubleArray(OutputStream out, double[] v) throws IOException { writeLength(out, v.length); for(double s : v) writeDouble(out, s); } public static void writeString(OutputStream out, String v) throws IOException { writeByteArray(out, v.getBytes(UTF8)); } public static int ioSizeString(String v) { return ioSizeLength(v.length()) + v.getBytes().length; } public static int ioSizeLength(int length) { if(length < 0x80) return 1; if(length < 0x4080) return 2; if(length < 0x204080) return 3; if(length < 0x10204080) return 4; return 5; } }