]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.graph/src/org/simantics/graph/representation/ByteFileReader.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.graph / src / org / simantics / graph / representation / ByteFileReader.java
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
new file mode 100644 (file)
index 0000000..d4fb31f
--- /dev/null
@@ -0,0 +1,261 @@
+package org.simantics.graph.representation;\r
+\r
+import java.io.Closeable;\r
+import java.io.EOFException;\r
+import java.io.File;\r
+import java.io.FileInputStream;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.nio.ByteBuffer;\r
+import java.nio.channels.ReadableByteChannel;\r
+\r
+/**\r
+ * Must be closed after using by invoking {@link #close()}.\r
+ */\r
+public class ByteFileReader implements Closeable {\r
+\r
+       final char[] chars = new char[3*128];\r
+\r
+       final private File file;\r
+       \r
+       /**\r
+        * May be <code>null</code>. If specified, it will be closed in\r
+        * {@link #close()}.\r
+        */\r
+       private InputStream stream;\r
+\r
+       /**\r
+        * A readable channel must always be specified since it is used for all\r
+        * reading. Channel is never closed by this class.\r
+        */\r
+       private ReadableByteChannel channel;\r
+       \r
+       final private ByteBuffer byteBuffer;\r
+       \r
+       final protected byte[] bytes;\r
+       private int size;\r
+\r
+       protected int byteIndex = 0;\r
+\r
+       final protected ReadableByteChannel getChannel() {\r
+               return channel;\r
+       }\r
+       \r
+       final protected ByteBuffer getByteBuffer() {\r
+               return byteBuffer;\r
+       }\r
+\r
+       final protected byte[] getBytes() {\r
+               return bytes;\r
+\r
+       }\r
+       final protected String utf(byte[] bytes, int index, int target) {\r
+               int i = 0;\r
+               while(index < target) {\r
+                       int c = bytes[index++]&0xff;\r
+                       if(c <= 0x7F) {\r
+                               chars[i++] = (char)(c&0x7F);\r
+                       } else if (c > 0x07FF) {\r
+                               int c2 = bytes[index++]&0xff;\r
+                               int c3 = bytes[index++]&0xff;\r
+                               chars[i++] = (char)(((c&0xf)<<12) + ((c2&0x3f)<<6) + (c3&0x3f)); \r
+                       } else {\r
+                               int c2 = bytes[index++]&0xff;\r
+                               chars[i++] = (char)(((c&0x1f)<<6) + (c2&0x3f)); \r
+                       }\r
+                       \r
+               }\r
+               return new String(chars, 0, i);\r
+       }\r
+\r
+       final protected byte[] safeBytes(int amount) throws IOException {\r
+\r
+               byte[] result = new byte[amount];\r
+               \r
+               int has = size-byteIndex;\r
+               if(amount >= has) {\r
+                       ReadableByteChannel c = channel;\r
+               ByteBuffer bb = byteBuffer;\r
+                       System.arraycopy(bytes, byteIndex, result, 0, has);\r
+                       ByteBuffer bb2 = ByteBuffer.wrap(result);\r
+                       bb2.position(has);\r
+                       // For some peculiar reason this seems to avoid OOM with large blocks as compared to c.read(bb2\r
+                       while(has < amount) {\r
+                               int todo = Math.min(amount-has, 65536);\r
+                               bb2.limit(has+todo);\r
+                               int got = c.read(bb2);\r
+                               if(got == -1) throw new IOException("Unexpected end-of-file");\r
+                               has += got; \r
+                       }\r
+                       size = c.read(bb);\r
+                       bb.position(0);\r
+                       byteIndex = 0;\r
+               } else {\r
+                       System.arraycopy(bytes, byteIndex, result, 0, amount);\r
+                       byteIndex += amount;\r
+               }\r
+\r
+               return result;\r
+               \r
+       }\r
+\r
+       final protected int getByte() throws IOException {\r
+           int has = size-byteIndex;\r
+           int result;\r
+        if(has == 0) {\r
+            ReadableByteChannel c = channel;\r
+            ByteBuffer bb = byteBuffer;            \r
+            size = c.read(bb);\r
+            if(size == -1) {\r
+                               throw new EOFException("Unexpected end-of-file");\r
+            }\r
+            bb.position(0);\r
+            byteIndex = 0;\r
+            if(size == 0)\r
+                return -1;\r
+        }\r
+        result = bytes[byteIndex];\r
+        if(result < 0)\r
+            result += 256;\r
+        ++byteIndex;        \r
+        return result;\r
+       }\r
+\r
+       public int getDynamicUInt32() throws IOException {\r
+               int length = getByte()&0xff; \r
+               if(length >= 0x80) {\r
+                       if(length >= 0xc0) {\r
+                               if(length >= 0xe0) {\r
+                                       if(length >= 0xf0) {\r
+                                               length &= 0x0f;\r
+                                               length += ((getByte()&0xff)<<3);\r
+                                               length += ((getByte()&0xff)<<11);\r
+                                               length += ((getByte()&0xff)<<19);\r
+                                               length += 0x10204080;\r
+                                       }\r
+                                       else {\r
+                                               length &= 0x1f;\r
+                                               length += ((getByte()&0xff)<<4);\r
+                                               length += ((getByte()&0xff)<<12);\r
+                                               length += ((getByte()&0xff)<<20);\r
+                                               length += 0x204080;\r
+                                       }\r
+                               }\r
+                               else {\r
+                                       length &= 0x3f;\r
+                                       length += ((getByte()&0xff)<<5);\r
+                                       length += ((getByte()&0xff)<<13);\r
+                                       length += 0x4080;\r
+                               }\r
+                       }\r
+                       else {\r
+                               length &= 0x7f;\r
+                               length += ((getByte()&0xff)<<6);\r
+                               length += 0x80;\r
+                       }\r
+               }\r
+               return length;\r
+       }\r
+\r
+       final protected int safeInt() throws IOException {\r
+\r
+               if(byteIndex >= (size-5)) {\r
+                       int result = 0;\r
+                       ReadableByteChannel c = channel;\r
+               ByteBuffer bb = byteBuffer;\r
+                       if(byteIndex == size) {\r
+                               size = c.read(bb);\r
+                               if(size == -1) throw new EOFException("Unexpected end-of-file");\r
+                               bb.position(0);\r
+                               byteIndex = 0;\r
+                       }\r
+                       result |= ((int)(bytes[byteIndex++]&0xff)<<24);\r
+                       if(byteIndex == size) {\r
+                               size = c.read(bb);\r
+                               if(size == -1) throw new EOFException("Unexpected end-of-file");\r
+                               bb.position(0);\r
+                               byteIndex = 0;\r
+                       }\r
+                       result |= ((int)(bytes[byteIndex++]&0xff)<<16);\r
+                       if(byteIndex == size) {\r
+                               size = c.read(bb);\r
+                               if(size == -1) throw new EOFException("Unexpected end-of-file");\r
+                               bb.position(0);\r
+                               byteIndex = 0;\r
+                       }\r
+                       result |= ((int)(bytes[byteIndex++]&0xff)<<8);\r
+                       if(byteIndex == size) {\r
+                               size = c.read(bb);\r
+                               if(size == -1) throw new EOFException("Unexpected end-of-file");\r
+                               bb.position(0);\r
+                               byteIndex = 0;\r
+                       }\r
+                       result |= ((int)(bytes[byteIndex++]&0xff)<<0);\r
+                       if(byteIndex == size) {\r
+                               size = c.read(bb);\r
+                               bb.position(0);\r
+                               byteIndex = 0;\r
+                       }\r
+                       return result;\r
+               } else {\r
+                       return ((bytes[byteIndex++]&0xff)<<24) | ((bytes[byteIndex++]&0xff)<<16) | ((bytes[byteIndex++]&0xff)<<8) | ((bytes[byteIndex++]&0xff));\r
+               }\r
+               \r
+       }\r
+       \r
+       final protected int getSize() {\r
+               return size;\r
+       }\r
+\r
+       public ByteFileReader(File file, int size) throws IOException {\r
+           \r
+        bytes = new byte[size];\r
+        byteBuffer = ByteBuffer.wrap(bytes);\r
+\r
+        this.file = file;\r
+        \r
+        FileInputStream fis = new FileInputStream(file); \r
+        stream = fis; \r
+        channel = fis.getChannel();\r
+        this.size = channel.read(byteBuffer);\r
+        byteBuffer.position(0);\r
+           \r
+       }\r
+\r
+       public ByteFileReader(FileInputStream stream, int size) throws IOException {\r
+               this(stream, stream.getChannel(), size);\r
+       }\r
+    \r
+       public ByteFileReader(InputStream stream, ReadableByteChannel channel, int size) throws IOException {\r
+           \r
+               bytes = new byte[size];\r
+               byteBuffer = ByteBuffer.wrap(bytes);\r
+\r
+               this.file = null;\r
+               this.stream = stream;\r
+               this.channel = channel;\r
+               this.size = channel.read(byteBuffer);\r
+               byteBuffer.position(0);\r
+               \r
+       }\r
+\r
+       public void close() throws IOException {\r
+               if (stream != null) {\r
+                       stream.close();\r
+                       stream = null;\r
+               }\r
+       }\r
+       \r
+       public void reset() throws IOException {\r
+           \r
+           if(file == null) throw new IllegalStateException("No file - cannot reset");\r
+        \r
+        FileInputStream fis = new FileInputStream(file); \r
+        stream = fis; \r
+        channel = fis.getChannel();\r
+        this.size = channel.read(byteBuffer);\r
+        byteBuffer.position(0);\r
+        \r
+       }\r
+\r
+}\r