X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;ds=sidebyside;f=bundles%2Forg.simantics.graph%2Fsrc%2Forg%2Fsimantics%2Fgraph%2Frepresentation%2FByteFileReader.java;h=3a76a911a0d3c269c4c72cf5053b742aa8579432;hb=e235ff48dd50e787f5508a2280826372ef20a3d7;hp=d4fb31f24648e20a33997d7dbdc836ed4ba3ff19;hpb=969bd23cab98a79ca9101af33334000879fb60c5;p=simantics%2Fplatform.git
diff --git a/bundles/org.simantics.graph/src/org/simantics/graph/representation/ByteFileReader.java b/bundles/org.simantics.graph/src/org/simantics/graph/representation/ByteFileReader.java
index d4fb31f24..3a76a911a 100644
--- a/bundles/org.simantics.graph/src/org/simantics/graph/representation/ByteFileReader.java
+++ b/bundles/org.simantics.graph/src/org/simantics/graph/representation/ByteFileReader.java
@@ -1,261 +1,306 @@
-package org.simantics.graph.representation;
-
-import java.io.Closeable;
-import java.io.EOFException;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.ByteBuffer;
-import java.nio.channels.ReadableByteChannel;
-
-/**
- * Must be closed after using by invoking {@link #close()}.
- */
-public class ByteFileReader implements Closeable {
-
- final char[] chars = new char[3*128];
-
- final private File file;
-
- /**
- * May be null
. If specified, it will be closed in
- * {@link #close()}.
- */
- private InputStream stream;
-
- /**
- * A readable channel must always be specified since it is used for all
- * reading. Channel is never closed by this class.
- */
- private ReadableByteChannel channel;
-
- final private ByteBuffer byteBuffer;
-
- final protected byte[] bytes;
- private int size;
-
- protected int byteIndex = 0;
-
- final protected ReadableByteChannel getChannel() {
- return channel;
- }
-
- final protected ByteBuffer getByteBuffer() {
- return byteBuffer;
- }
-
- final protected byte[] getBytes() {
- return bytes;
-
- }
- final protected String utf(byte[] bytes, int index, int target) {
- int i = 0;
- while(index < target) {
- int c = bytes[index++]&0xff;
- if(c <= 0x7F) {
- chars[i++] = (char)(c&0x7F);
- } else if (c > 0x07FF) {
- int c2 = bytes[index++]&0xff;
- int c3 = bytes[index++]&0xff;
- chars[i++] = (char)(((c&0xf)<<12) + ((c2&0x3f)<<6) + (c3&0x3f));
- } else {
- int c2 = bytes[index++]&0xff;
- chars[i++] = (char)(((c&0x1f)<<6) + (c2&0x3f));
- }
-
- }
- return new String(chars, 0, i);
- }
-
- final protected byte[] safeBytes(int amount) throws IOException {
-
- byte[] result = new byte[amount];
-
- int has = size-byteIndex;
- if(amount >= has) {
- ReadableByteChannel c = channel;
- ByteBuffer bb = byteBuffer;
- System.arraycopy(bytes, byteIndex, result, 0, has);
- ByteBuffer bb2 = ByteBuffer.wrap(result);
- bb2.position(has);
- // For some peculiar reason this seems to avoid OOM with large blocks as compared to c.read(bb2
- while(has < amount) {
- int todo = Math.min(amount-has, 65536);
- bb2.limit(has+todo);
- int got = c.read(bb2);
- if(got == -1) throw new IOException("Unexpected end-of-file");
- has += got;
- }
- size = c.read(bb);
- bb.position(0);
- byteIndex = 0;
- } else {
- System.arraycopy(bytes, byteIndex, result, 0, amount);
- byteIndex += amount;
- }
-
- return result;
-
- }
-
- final protected int getByte() throws IOException {
- int has = size-byteIndex;
- int result;
- if(has == 0) {
- ReadableByteChannel c = channel;
- ByteBuffer bb = byteBuffer;
- size = c.read(bb);
- if(size == -1) {
- throw new EOFException("Unexpected end-of-file");
- }
- bb.position(0);
- byteIndex = 0;
- if(size == 0)
- return -1;
- }
- result = bytes[byteIndex];
- if(result < 0)
- result += 256;
- ++byteIndex;
- return result;
- }
-
- public int getDynamicUInt32() throws IOException {
- int length = getByte()&0xff;
- if(length >= 0x80) {
- if(length >= 0xc0) {
- if(length >= 0xe0) {
- if(length >= 0xf0) {
- length &= 0x0f;
- length += ((getByte()&0xff)<<3);
- length += ((getByte()&0xff)<<11);
- length += ((getByte()&0xff)<<19);
- length += 0x10204080;
- }
- else {
- length &= 0x1f;
- length += ((getByte()&0xff)<<4);
- length += ((getByte()&0xff)<<12);
- length += ((getByte()&0xff)<<20);
- length += 0x204080;
- }
- }
- else {
- length &= 0x3f;
- length += ((getByte()&0xff)<<5);
- length += ((getByte()&0xff)<<13);
- length += 0x4080;
- }
- }
- else {
- length &= 0x7f;
- length += ((getByte()&0xff)<<6);
- length += 0x80;
- }
- }
- return length;
- }
-
- final protected int safeInt() throws IOException {
-
- if(byteIndex >= (size-5)) {
- int result = 0;
- ReadableByteChannel c = channel;
- ByteBuffer bb = byteBuffer;
- if(byteIndex == size) {
- size = c.read(bb);
- if(size == -1) throw new EOFException("Unexpected end-of-file");
- bb.position(0);
- byteIndex = 0;
- }
- result |= ((int)(bytes[byteIndex++]&0xff)<<24);
- if(byteIndex == size) {
- size = c.read(bb);
- if(size == -1) throw new EOFException("Unexpected end-of-file");
- bb.position(0);
- byteIndex = 0;
- }
- result |= ((int)(bytes[byteIndex++]&0xff)<<16);
- if(byteIndex == size) {
- size = c.read(bb);
- if(size == -1) throw new EOFException("Unexpected end-of-file");
- bb.position(0);
- byteIndex = 0;
- }
- result |= ((int)(bytes[byteIndex++]&0xff)<<8);
- if(byteIndex == size) {
- size = c.read(bb);
- if(size == -1) throw new EOFException("Unexpected end-of-file");
- bb.position(0);
- byteIndex = 0;
- }
- result |= ((int)(bytes[byteIndex++]&0xff)<<0);
- if(byteIndex == size) {
- size = c.read(bb);
- bb.position(0);
- byteIndex = 0;
- }
- return result;
- } else {
- return ((bytes[byteIndex++]&0xff)<<24) | ((bytes[byteIndex++]&0xff)<<16) | ((bytes[byteIndex++]&0xff)<<8) | ((bytes[byteIndex++]&0xff));
- }
-
- }
-
- final protected int getSize() {
- return size;
- }
-
- public ByteFileReader(File file, int size) throws IOException {
-
- bytes = new byte[size];
- byteBuffer = ByteBuffer.wrap(bytes);
-
- this.file = file;
-
- FileInputStream fis = new FileInputStream(file);
- stream = fis;
- channel = fis.getChannel();
- this.size = channel.read(byteBuffer);
- byteBuffer.position(0);
-
- }
-
- public ByteFileReader(FileInputStream stream, int size) throws IOException {
- this(stream, stream.getChannel(), size);
- }
-
- public ByteFileReader(InputStream stream, ReadableByteChannel channel, int size) throws IOException {
-
- bytes = new byte[size];
- byteBuffer = ByteBuffer.wrap(bytes);
-
- this.file = null;
- this.stream = stream;
- this.channel = channel;
- this.size = channel.read(byteBuffer);
- byteBuffer.position(0);
-
- }
-
- public void close() throws IOException {
- if (stream != null) {
- stream.close();
- stream = null;
- }
- }
-
- public void reset() throws IOException {
-
- if(file == null) throw new IllegalStateException("No file - cannot reset");
-
- FileInputStream fis = new FileInputStream(file);
- stream = fis;
- channel = fis.getChannel();
- this.size = channel.read(byteBuffer);
- byteBuffer.position(0);
-
- }
-
-}
+package org.simantics.graph.representation;
+
+import java.io.Closeable;
+import java.io.EOFException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UTFDataFormatException;
+import java.nio.ByteBuffer;
+import java.nio.channels.ReadableByteChannel;
+
+/**
+ * Must be closed after using by invoking {@link #close()}.
+ */
+public class ByteFileReader implements Closeable {
+
+ final char[] chars = new char[3*128];
+
+ final private File file;
+
+ /**
+ * May be null
. If specified, it will be closed in
+ * {@link #close()}.
+ */
+ private InputStream stream;
+
+ /**
+ * A readable channel must always be specified since it is used for all
+ * reading. Channel is never closed by this class.
+ */
+ private ReadableByteChannel channel;
+
+ final private ByteBuffer byteBuffer;
+
+ final protected byte[] bytes;
+ private int size;
+
+ protected int byteIndex = 0;
+
+ final protected ReadableByteChannel getChannel() {
+ return channel;
+ }
+
+ final protected ByteBuffer getByteBuffer() {
+ return byteBuffer;
+ }
+
+ final protected byte[] getBytes() {
+ return bytes;
+
+ }
+
+ final protected String utf(byte[] bytearr, int index, int target) throws UTFDataFormatException {
+ // Copied from DataInputStream
+ int utflen = target - index;
+ char[] chararr = utflen > chars.length ? new char[utflen] : chars;
+
+ int c, char2, char3;
+ int count = index;
+ int chararr_count=0;
+
+ while (count < target) {
+ c = (int) bytearr[count] & 0xff;
+ if (c > 127) break;
+ count++;
+ chararr[chararr_count++]=(char)c;
+ }
+
+ while (count < target) {
+ c = (int) bytearr[count] & 0xff;
+ switch (c >> 4) {
+ case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
+ /* 0xxxxxxx*/
+ count++;
+ chararr[chararr_count++]=(char)c;
+ break;
+ case 12: case 13:
+ /* 110x xxxx 10xx xxxx*/
+ count += 2;
+ if (count > target)
+ throw new UTFDataFormatException(
+ "malformed input: partial character at end (" + (count-index) + " > " + utflen + ")");
+ char2 = (int) bytearr[count-1];
+ if ((char2 & 0xC0) != 0x80)
+ throw new UTFDataFormatException(
+ "malformed input around byte " + count);
+ chararr[chararr_count++]=(char)(((c & 0x1F) << 6) |
+ (char2 & 0x3F));
+ break;
+ case 14:
+ /* 1110 xxxx 10xx xxxx 10xx xxxx */
+ count += 3;
+ if (count > target)
+ throw new UTFDataFormatException(
+ "malformed input: partial character at end (" + (count-index) + " > " + utflen + ")");
+ char2 = (int) bytearr[count-2];
+ char3 = (int) bytearr[count-1];
+ if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
+ throw new UTFDataFormatException(
+ "malformed input around byte " + (count-1));
+ chararr[chararr_count++]=(char)(((c & 0x0F) << 12) |
+ ((char2 & 0x3F) << 6) |
+ ((char3 & 0x3F) << 0));
+ break;
+ default:
+ /* 10xx xxxx, 1111 xxxx */
+ throw new UTFDataFormatException(
+ "malformed input around byte " + count);
+ }
+ }
+ // The number of chars produced may be less than utflen
+ return new String(chararr, 0, chararr_count);
+ }
+
+ final protected byte[] safeBytes(int amount) throws IOException {
+ byte[] result = new byte[amount];
+ int has = size-byteIndex;
+ if(amount >= has) {
+ ReadableByteChannel c = channel;
+ ByteBuffer bb = byteBuffer;
+ System.arraycopy(bytes, byteIndex, result, 0, has);
+ ByteBuffer bb2 = ByteBuffer.wrap(result);
+ bb2.position(has);
+ // For some peculiar reason this seems to avoid OOM with large blocks as compared to c.read(bb2
+ while(has < amount) {
+ int todo = Math.min(amount-has, 65536);
+ bb2.limit(has+todo);
+ int got = c.read(bb2);
+ if(got == -1) throw new IOException("Unexpected end-of-file");
+ has += got;
+ // For some unknown reason this is needed!
+ // Spec indicates that read would increment position but it does not.
+ bb2.position(has);
+ }
+ size = c.read(bb);
+ bb.position(0);
+ byteIndex = 0;
+ } else {
+ System.arraycopy(bytes, byteIndex, result, 0, amount);
+ byteIndex += amount;
+ }
+
+ return result;
+
+ }
+
+ final protected int getByte() throws IOException {
+ int has = size-byteIndex;
+ int result;
+ if(has == 0) {
+ ReadableByteChannel c = channel;
+ ByteBuffer bb = byteBuffer;
+ size = c.read(bb);
+ if(size == -1) {
+ throw new EOFException("Unexpected end-of-file");
+ }
+ bb.position(0);
+ byteIndex = 0;
+ if(size == 0)
+ return -1;
+ }
+ result = bytes[byteIndex++] & 0xff;
+ return result;
+ }
+
+ public int getDynamicUInt32() throws IOException {
+ int length = getByte();
+ if(length >= 0x80) {
+ if(length >= 0xc0) {
+ if(length >= 0xe0) {
+ if(length >= 0xf0) {
+ length &= 0x0f;
+ length += (getByte()<<3);
+ length += (getByte()<<11);
+ length += (getByte()<<19);
+ length += 0x10204080;
+ }
+ else {
+ length &= 0x1f;
+ length += (getByte()<<4);
+ length += (getByte()<<12);
+ length += (getByte()<<20);
+ length += 0x204080;
+ }
+ }
+ else {
+ length &= 0x3f;
+ length += (getByte()<<5);
+ length += (getByte()<<13);
+ length += 0x4080;
+ }
+ }
+ else {
+ length &= 0x7f;
+ length += (getByte()<<6);
+ length += 0x80;
+ }
+ }
+ return length;
+ }
+
+ final protected int safeInt() throws IOException {
+
+ byte[] bytes = this.bytes;
+
+ if(byteIndex >= (size-5)) {
+ int result = 0;
+ ReadableByteChannel c = channel;
+ ByteBuffer bb = byteBuffer;
+ if(byteIndex == size) {
+ size = c.read(bb);
+ if(size == -1) throw new EOFException("Unexpected end-of-file");
+ bb.position(0);
+ byteIndex = 0;
+ }
+ result |= ((int)(bytes[byteIndex++]&0xff)<<24);
+ if(byteIndex == size) {
+ size = c.read(bb);
+ if(size == -1) throw new EOFException("Unexpected end-of-file");
+ bb.position(0);
+ byteIndex = 0;
+ }
+ result |= ((int)(bytes[byteIndex++]&0xff)<<16);
+ if(byteIndex == size) {
+ size = c.read(bb);
+ if(size == -1) throw new EOFException("Unexpected end-of-file");
+ bb.position(0);
+ byteIndex = 0;
+ }
+ result |= ((int)(bytes[byteIndex++]&0xff)<<8);
+ if(byteIndex == size) {
+ size = c.read(bb);
+ if(size == -1) throw new EOFException("Unexpected end-of-file");
+ bb.position(0);
+ byteIndex = 0;
+ }
+ result |= ((int)(bytes[byteIndex++]&0xff));
+ if(byteIndex == size) {
+ size = c.read(bb);
+ bb.position(0);
+ byteIndex = 0;
+ }
+ return result;
+ } else {
+ return ((bytes[byteIndex++]&0xff)<<24) | ((bytes[byteIndex++]&0xff)<<16) | ((bytes[byteIndex++]&0xff)<<8) | ((bytes[byteIndex++]&0xff));
+ }
+
+ }
+
+ final protected int getSize() {
+ return size;
+ }
+
+ public ByteFileReader(File file, int size) throws IOException {
+
+ bytes = new byte[size];
+ byteBuffer = ByteBuffer.wrap(bytes);
+
+ this.file = file;
+
+ FileInputStream fis = new FileInputStream(file);
+ stream = fis;
+ channel = fis.getChannel();
+ this.size = channel.read(byteBuffer);
+ byteBuffer.position(0);
+
+ }
+
+ public ByteFileReader(FileInputStream stream, int size) throws IOException {
+ this(stream, stream.getChannel(), size);
+ }
+
+ public ByteFileReader(InputStream stream, ReadableByteChannel channel, int size) throws IOException {
+
+ bytes = new byte[size];
+ byteBuffer = ByteBuffer.wrap(bytes);
+
+ this.file = null;
+ this.stream = stream;
+ this.channel = channel;
+ this.size = channel.read(byteBuffer);
+ byteBuffer.position(0);
+
+ }
+
+ public void close() throws IOException {
+ if (stream != null) {
+ stream.close();
+ stream = null;
+ }
+ }
+
+ public void reset() throws IOException {
+
+ if(file == null) throw new IllegalStateException("No file - cannot reset");
+
+ FileInputStream fis = new FileInputStream(file);
+ stream = fis;
+ channel = fis.getChannel();
+ this.size = channel.read(byteBuffer);
+ byteBuffer.position(0);
+
+ }
+
+}