Made reading read-only ByteBuffers work.
authorWouter van Oortmerssen <wvo@google.com>
Wed, 3 Sep 2014 01:35:20 +0000 (18:35 -0700)
committerWouter van Oortmerssen <wvo@google.com>
Wed, 3 Sep 2014 18:03:02 +0000 (11:03 -0700)
Also added new constructor that allows ByteBuffer reuse.

Change-Id: I9c20ea96c67533066461f4e23b0d03b9b47cd068
Tested: on OS X.

java/flatbuffers/FlatBufferBuilder.java
java/flatbuffers/Table.java
tests/JavaTest.java

index a5ec1fb..50adeb5 100755 (executable)
@@ -30,7 +30,7 @@ public class FlatBufferBuilder {
     int space;           // Remaining space in the ByteBuffer.
     static final Charset utf8charset = Charset.forName("UTF-8");
     int minalign = 1;    // Minimum alignment encountered so far.
-    int[] vtable;        // The vtable for the current table, null otherwise.
+    int[] vtable = null; // The vtable for the current table, null otherwise.
     int object_start;    // Starting offset of the current struct/table.
     int[] vtables = new int[16];  // List of offsets of all vtables.
     int num_vtables = 0;          // Number of entries in `vtables` in use.
@@ -47,6 +47,14 @@ public class FlatBufferBuilder {
         bb = newByteBuffer(new byte[initial_size]);
     }
 
+    // Alternative constructor allowing reuse of ByteBuffers
+    public FlatBufferBuilder(ByteBuffer existing_bb) {
+        bb = existing_bb;
+        bb.clear();
+        bb.order(ByteOrder.LITTLE_ENDIAN);
+        space = bb.capacity();
+    }
+
     ByteBuffer newByteBuffer(byte[] buf) {
         ByteBuffer newbb = ByteBuffer.wrap(buf);
         newbb.order(ByteOrder.LITTLE_ENDIAN);
index bfab3e0..f25188a 100755 (executable)
@@ -42,7 +42,17 @@ public class Table {
   // Create a java String from UTF-8 data stored inside the flatbuffer.
   protected String __string(int offset) {
     offset += bb.getInt(offset);
-    return new String(bb.array(), offset + SIZEOF_INT, bb.getInt(offset), Charset.forName("UTF-8"));
+    if (bb.hasArray()) {
+      return new String(bb.array(), offset + SIZEOF_INT, bb.getInt(offset), Charset.forName("UTF-8"));
+    } else {
+      // We can't access .array(), since the ByteBuffer is read-only.
+      // We're forced to make an extra copy:
+      bb.position(offset + SIZEOF_INT);
+      byte[] copy = new byte[bb.getInt(offset)];
+      bb.get(copy);
+      bb.position(0);
+      return new String(copy, 0, copy.length, Charset.forName("UTF-8"));
+    }
   }
 
   // Get the length of a vector whose offset is stored at "offset" in this object.
index 902362f..76f89f5 100755 (executable)
@@ -103,9 +103,12 @@ class JavaTest {
         }
 
         // Test it:
-
         TestBuffer(fbb.dataBuffer(), fbb.dataStart());
 
+        // Make sure it also works with read only ByteBuffers. This is slower, since
+        // creating strings incurs an additional copy (see Table.__string).
+        TestBuffer(fbb.dataBuffer().asReadOnlyBuffer(), fbb.dataStart());
+
         System.out.println("FlatBuffers test: completed successfully");
     }