]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.databoard/src/org/simantics/databoard/util/binary/BinaryMemory.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / util / binary / BinaryMemory.java
diff --git a/bundles/org.simantics.databoard/src/org/simantics/databoard/util/binary/BinaryMemory.java b/bundles/org.simantics.databoard/src/org/simantics/databoard/util/binary/BinaryMemory.java
new file mode 100644 (file)
index 0000000..087a6a9
--- /dev/null
@@ -0,0 +1,573 @@
+/*******************************************************************************\r
+ * Copyright (c) 2010, 2016 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.databoard.util.binary;
+
+import java.io.DataInputStream;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.nio.ByteBuffer;\r
+
+/**
+ * Rancom access memory blob
+ *
+ * @author Toni Kalajainen <toni.kalajainen@vtt.fi>
+ */
+public class BinaryMemory implements RandomAccessBinary {
+
+       ByteBuffer buf;
+       long pointer;
+       /** the number of bytes added spare to the buffer when it is incremented */
+       int increment;
+       
+       /**
+        * New memory blob
+        */
+       public BinaryMemory() {
+               buf = ByteBuffer.allocate(16);
+               increment = 16;
+       }
+\r
+       /**\r
+        * New memory blob\r
+        */\r
+       public BinaryMemory(byte[] data) {\r
+               this.buf = ByteBuffer.wrap(data);\r
+       }\r
+       \r
+       /**\r
+        * New memory blob\r
+        */\r
+       public BinaryMemory(byte[] data, int offset, int length) {\r
+               this.buf = ByteBuffer.wrap(data, offset, length);\r
+       }\r
+       
+       /**
+        * New memory blob
+        */
+       public BinaryMemory(int initialSize) {
+               buf = ByteBuffer.allocate(initialSize);
+               increment = Math.max(16, initialSize);
+       }
+       
+       /**
+        * New memory blob
+        */
+       public BinaryMemory(int initialSize, int increment) {
+               buf = ByteBuffer.allocate(initialSize);
+               this.increment = increment;
+       }
+       
+       /**
+        * Assume an existing byte buffer
+        * 
+        * @param buf buffer
+        */
+       public BinaryMemory(ByteBuffer buf) {
+               this.buf = buf;
+       }
+       
+       /**
+        * Get the backend byte buffer. The result may change if BinaryMemory is 
+        * written.
+        * 
+        * @return byte buffer
+        */
+       public ByteBuffer toByteBuffer() {
+               return buf;
+       }
+       
+       @Override
+       public void close() throws IOException {
+       }
+\r
+       @Override\r
+       public boolean isOpen() {\r
+               return true;\r
+       }\r
+       
+       @Override
+       public void flush() throws IOException {
+       }\r
+       \r
+       @Override\r
+       public void reset() throws IOException {\r
+       }
+
+       @Override
+       public byte readByte() {
+               assertHasReadableBytes(1);              
+               buf.position( (int) pointer );
+               byte result = buf.get();
+               pointer += 1;
+               return result;
+       }\r
+       \r
+       int _read() {\r
+               if (pointer >= buf.limit()) return -1;\r
+               buf.position( (int) pointer );\r
+               byte result = buf.get();\r
+               pointer += 1;\r
+               return result & 0xff;\r
+       }       \r
+       \r
+    public final String readLine() throws IOException {\r
+       StringBuffer input = new StringBuffer();\r
+       int c = -1;\r
+       boolean eol = false;\r
+\r
+       while (!eol) {\r
+           switch (c = _read()) {\r
+           case -1:\r
+           case '\n':\r
+               eol = true;\r
+               break;\r
+           case '\r':\r
+               eol = true;\r
+               long cur = position();\r
+               if ((_read()) != '\n') {\r
+                   position(cur);\r
+               }\r
+               break;\r
+           default:\r
+               input.append((char)c);\r
+               break;\r
+           }\r
+       }\r
+\r
+       if ((c == -1) && (input.length() == 0)) {\r
+           return null;\r
+       }\r
+       return input.toString();\r
+    }  \r
+    \r
+    public final String readUTF() throws IOException {\r
+       return DataInputStream.readUTF(this);\r
+    }     \r
+       \r
+       @Override\r
+       public int readUnsignedByte() throws IOException {\r
+               return readByte() & 0x000000ff;\r
+       }               
+\r
+       @Override\r
+       public boolean readBoolean() throws IOException {\r
+               assertHasReadableBytes(1);              \r
+               buf.position( (int) pointer );\r
+               byte result = buf.get();\r
+               pointer += 1;\r
+               return result!=0;\r
+       }\r
+       
+       @Override
+       public void readFully(byte[] dst, int offset, int length) {
+               assertHasReadableBytes(length);
+               buf.position( (int) pointer );
+               buf.get(dst, offset, length);
+               pointer += length;
+       }
+
+       @Override
+       public void readFully(byte[] dst) {
+               assertHasReadableBytes(dst.length);             
+               buf.position( (int) pointer );
+               buf.get(dst);
+               pointer += dst.length;
+       }
+
+       @Override
+       public void readFully(ByteBuffer buf) {         
+               int bytes = buf.remaining();
+               assertHasReadableBytes( bytes );
+               buf.position( (int) pointer );
+               if (buf.hasArray()) {
+                       this.buf.get(buf.array(), buf.arrayOffset() + buf.position(), bytes);
+                       buf.position(buf.capacity());
+               } else {
+                       buf.put(buf);
+               }
+               pointer += bytes;
+       }
+
+       @Override
+       public void readFully(ByteBuffer buf, int length) {
+               assertHasReadableBytes(length);
+               buf.position( (int) pointer );
+               if (buf.hasArray()) {
+                       this.buf.get(buf.array(), buf.arrayOffset() + buf.position(), length);
+                       buf.position(buf.position() + length);
+               } else {
+//                     int len = Math.min( Math.min( buf.remaining(), this.buf.remaining() ), length);
+                       int len = length;
+                       int origLimit = this.buf.limit();
+                       try {
+                               this.buf.limit(this.buf.position()+len);
+                               buf.put(this.buf);
+                       } finally {
+                               this.buf.limit(origLimit);
+                       }
+               }
+               pointer += length;
+       }
+
+       @Override
+       public double readDouble() {
+               assertHasReadableBytes(8);
+               buf.position( (int) pointer );
+               double value = buf.getDouble();
+               pointer += 8;
+               return value;
+       }
+
+       @Override
+       public float readFloat() {
+               assertHasReadableBytes(4);
+               buf.position( (int) pointer );
+               float result = buf.getFloat();
+               pointer += 4;
+               return result;
+       }
+
+       @Override
+       public int readInt() {
+               assertHasReadableBytes(4);
+               buf.position( (int) pointer );
+               int value = buf.getInt();
+               pointer += 4;
+               return value;
+       }
+
+       @Override
+       public long readLong() {
+               assertHasReadableBytes(8);
+               buf.position( (int) pointer );
+               long value = buf.getLong();
+               pointer += 8;
+               return value;
+       }
+
+       @Override
+       public short readShort() {
+               assertHasReadableBytes(2);
+               buf.position( (int) pointer );
+               short result = buf.getShort();
+               pointer += 2;
+               return result;
+       }\r
+       \r
+       @Override\r
+       public char readChar() {\r
+               assertHasReadableBytes(2);\r
+               buf.position( (int) pointer );\r
+               char result = buf.getChar();\r
+               pointer += 2;\r
+               return result;\r
+       }       \r
+       \r
+       @Override\r
+       public int readUnsignedShort() {\r
+               assertHasReadableBytes(2);\r
+               buf.position( (int) pointer );\r
+               int result = buf.getShort() & 0xffff;\r
+               pointer += 2;\r
+               return result;\r
+       }       
+
+       @Override
+       public long length() {
+               return buf.limit();
+       }
+       
+       @Override
+       public long position() {
+               return pointer;
+       }
+       
+       @Override
+       public void position(long newPosition) throws IOException {
+               this.pointer = newPosition;
+       }
+       
+       @Override
+       public void write(int b) throws IOException {
+               assertHasWritableBytes(1);
+               buf.position( (int) pointer );
+               buf.put((byte) b);
+               pointer += 1;
+       }\r
+       \r
+       @Override\r
+       public void writeByte(int b) throws IOException {\r
+               assertHasWritableBytes(1);\r
+               buf.position( (int) pointer );\r
+               buf.put((byte) b);\r
+               pointer += 1;\r
+       }       \r
+       \r
+       @Override\r
+       public void writeBoolean(boolean v) throws IOException {\r
+               assertHasWritableBytes(1);\r
+               buf.position( (int) pointer );\r
+               buf.put( (byte) (v ? 1 : 0) );\r
+               pointer += 1;\r
+       }
+
+       @Override
+       public void writeFully(ByteBuffer src) throws IOException {
+               long bytes = src.remaining();
+               assertHasWritableBytes( bytes );
+               buf.position( (int) pointer );
+               buf.put(src);
+               pointer += bytes;
+       }
+
+       @Override
+       public void writeFully(ByteBuffer src, int length) throws IOException {
+               assertHasWritableBytes(length);
+               buf.position( (int) pointer );
+               if (src.hasArray()) {
+                       byte[] array = src.array();
+                       buf.put(array, src.arrayOffset() + src.position(), length);
+               } else {
+                       for (int i=0; i<length; i++)
+                               buf.put(src.get());
+               }
+               pointer += length;
+       }
+
+       
+       public void put(InputStream is) throws IOException {
+               long oldLen = length();
+               while (is.available()>0) {
+                       int n = is.available();
+                       assertHasWritableBytes(n);
+                       byte buf[] = this.buf.array();
+                       n = is.read(buf, (int) pointer, n);                     
+                       pointer += n;
+               }
+               long newLen = length();
+               if (newLen>oldLen & pointer<newLen) setLength(pointer);
+       }
+
+       @Override
+       public void write(byte[] src, int offset, int length) throws IOException {
+               assertHasWritableBytes(length);
+               buf.position( (int) pointer );
+               buf.put(src, offset, length);
+               pointer += length;
+       }
+
+       @Override
+       public void write(byte[] src) throws IOException {
+               assertHasWritableBytes(src.length);
+               buf.position( (int) pointer );
+               buf.put(src);
+               pointer += src.length;
+       }
+
+       @Override
+       public void writeDouble(double value) throws IOException {
+               assertHasWritableBytes(8);
+               buf.position( (int) pointer );
+               buf.putDouble(value);
+               pointer += 8;
+       }
+
+       @Override
+       public void writeFloat(float value) throws IOException {
+               assertHasWritableBytes(4);
+               buf.position( (int) pointer );
+               buf.putFloat(value);
+               pointer += 4;
+       }
+
+       @Override
+       public void writeInt(int value) throws IOException {
+               assertHasWritableBytes(4);
+               buf.position( (int) pointer );
+               buf.putInt(value);
+               pointer += 4;
+       }
+
+       @Override
+       public void writeLong(long value) throws IOException {
+               assertHasWritableBytes(8);
+               buf.position( (int) pointer );
+               buf.putLong(value);
+               pointer += 8;
+       }
+
+       @Override
+       public void writeShort(int value) throws IOException {
+               assertHasWritableBytes(2);
+               buf.position( (int) pointer );
+               buf.putShort( (short) value);
+               pointer += 2;
+       }\r
+       \r
+       @Override\r
+       public void writeChar(int value) throws IOException {\r
+               assertHasWritableBytes(2);\r
+               buf.position( (int) pointer );\r
+               buf.putShort( (short) value);\r
+               pointer += 2;\r
+       }       \r
+       \r
+       @Override\r
+       public void writeBytes(String s) throws IOException {\r
+               int len = s.length();\r
+               assertHasWritableBytes(len);\r
+               buf.position( (int) pointer );\r
+               for (int i = 0 ; i < len ; i++) {\r
+                   buf.put((byte)s.charAt(i));\r
+               }\r
+               pointer += len;\r
+       }       \r
+       \r
+       @Override\r
+       public void writeChars(String s) throws IOException {\r
+        int len = s.length();\r
+               assertHasWritableBytes(len*2);\r
+        for (int i = 0 ; i < len ; i++) {\r
+            int v = s.charAt(i);\r
+            buf.put( (byte) ((v >>> 8) & 0xFF) ); \r
+            buf.put( (byte) ((v >>> 0) & 0xFF) ); \r
+        }\r
+               pointer += len*2;\r
+       }\r
+       \r
+       @Override\r
+       public void writeUTF(String s) throws IOException {\r
+               int len = UTF8.getModifiedUTF8EncodingByteLength(s);\r
+               writeShort(len);\r
+               UTF8.writeModifiedUTF(this, s);\r
+       }       
+
+       void assertHasReadableBytes(long count) {
+               if (pointer + count > buf.limit())
+                       throw new IndexOutOfBoundsException();
+       }
+       
+       void assertHasWritableBytes(long count) 
+       throws IOException {
+               if (pointer + count > buf.limit()) 
+                       setLength(pointer+count);
+       }
+
+
+       @Override
+       public void insertBytes(long bytes, ByteSide side) throws IOException {
+               if (pointer<0) throw new IndexOutOfBoundsException();
+               // 1. Increase length
+               long oldLength = length();
+               long newLength = Math.max(oldLength + bytes, pointer + bytes);
+               // No need to allocate
+               if (newLength<buf.capacity()) {
+                       // Update limit
+                       buf.limit((int)newLength);
+                       
+                       // No need to move bytes
+                       if (pointer>oldLength) return;
+                               
+                       // Move bytes
+                       if (buf.hasArray()) {
+                               System.arraycopy(buf.array(), (int) pointer, buf.array(), (int) (pointer+bytes), (int) (oldLength - pointer));
+                       } 
+                       else 
+                       {
+                               byte[] b = new byte[(int) (oldLength - pointer)];
+                               buf.position((int)pointer);
+                               buf.get(b);
+                               buf.position( (int) (pointer + bytes) );
+                               buf.put(b);
+                       }
+               } else
+               // Need to reallocate
+               {
+                       long inc = Math.max(increment, newLength / 4);          
+                       ByteBuffer oldBuf = buf;
+                       ByteBuffer newBuf = ByteBuffer.allocate((int) (newLength + inc));
+                       newBuf.limit((int)newLength);
+                       
+                       newBuf.position(0);
+                       oldBuf.position(0);
+
+                       // Copy left side
+                       oldBuf.get(newBuf.array(), 0, (int)pointer);
+                       
+                       // Copy right side
+                       if (pointer<oldLength) 
+                       oldBuf.get(newBuf.array(), (int)(pointer+bytes), (int)(oldLength-pointer));
+                       
+                       buf = newBuf;
+               }
+               
+       }
+       
+       @Override
+       public void removeBytes(long bytes, ByteSide side) throws IOException {
+               long oldLength = length();
+               long newLength = oldLength - bytes;
+               if (pointer<0 || pointer>=length()) throw new IndexOutOfBoundsException();
+               
+               // move some bytes
+               if (buf.hasArray()) {
+                       System.arraycopy(buf.array(), (int)(pointer+bytes), buf.array(), (int) pointer, (int) (newLength-pointer) ); 
+               } else {
+                       byte[] b = new byte[(int) (oldLength-pointer)];
+                       buf.position((int) (pointer+bytes));
+                       buf.get(b);
+                       buf.position((int) (pointer));
+                       buf.put(b);
+               }
+               
+               buf.limit( (int) newLength );
+       }
+
+       @Override
+       public void setLength(long newLength) throws IOException {
+               int oldLength = (int) length();
+               if (oldLength==newLength) return;
+               if (newLength<=oldLength) {
+                       buf.limit((int)newLength);
+               } else
+               if (newLength<=buf.capacity()) {
+                       buf.limit((int)newLength);
+               } else {
+                       ByteBuffer oldBuf = buf;
+                       long inc = Math.max(increment, newLength / 4);
+                       ByteBuffer newBuf = ByteBuffer.allocate((int) (newLength + inc));
+                       oldBuf.position(0);
+                       oldBuf.get(newBuf.array(), 0, oldLength);
+                       newBuf.limit((int)newLength);
+                       buf = newBuf;
+               }               
+       }
+
+       @Override
+       public long skipBytes(long bytes) throws IOException {
+               pointer += bytes;\r
+               return bytes;
+       }
+\r
+       @Override\r
+       public int skipBytes(int bytes) throws IOException {\r
+               pointer += bytes;\r
+               return bytes;\r
+       }\r
+       
+       @Override
+       public String toString() {
+               return "Mem("+length()+")";
+       }
+       
+}
+