[Java] Grow ArrayReadWriteBuf enough to match requested capacity. (#5921)
authorgreenrobot Team <13865709+greenrobot-team@users.noreply.github.com>
Fri, 5 Jun 2020 02:48:25 +0000 (04:48 +0200)
committerGitHub <noreply@github.com>
Fri, 5 Jun 2020 02:48:25 +0000 (19:48 -0700)
* [Java] Grow ArrayReadWriteBuf enough to match requested capacity.

Also handle requested capacity overflowing.

* [Java] Improve readability of ArrayReadWriteBuf.requestCapacity()

* [Java] prepare testBuilderGrowth() to fail again once FlexBuffersBuilder uses ByteBufferReadWriteBuf internally, add TestFail() as a better alternative to a plain "assert false"

* [Java] Revert some test changes and extract a small string that was used more than once; one could say three times, however, it might be worthy of a discussion if the third occasion also falls into this category, as it is an independent use case and thus would work in the same way even if the value changed.

Co-authored-by: Markus <markus@greenrobot>
java/com/google/flatbuffers/ArrayReadWriteBuf.java
tests/JavaTest.java

index 38412e5..b7573d6 100644 (file)
@@ -234,12 +234,18 @@ public class ArrayReadWriteBuf implements ReadWriteBuf {
 
   @Override
   public boolean requestCapacity(int capacity) {
-    if (buffer.length > capacity) {
+    if (capacity < 0) {
+      throw new IllegalArgumentException("Capacity may not be negative (likely a previous int overflow)");
+    }
+    if (buffer.length >= capacity) {
       return true;
     }
     // implemented in the same growing fashion as ArrayList
     int oldCapacity = buffer.length;
     int newCapacity = oldCapacity + (oldCapacity >> 1);
+    if (newCapacity < capacity) {  // Note: this also catches newCapacity int overflow
+      newCapacity = capacity;
+    }
     buffer = Arrays.copyOf(buffer, newCapacity);
     return true;
   }
index a0dead9..39c7733 100644 (file)
@@ -1022,13 +1022,14 @@ class JavaTest {
 
     public static void testBuilderGrowth() {
         FlexBuffersBuilder builder = new FlexBuffersBuilder();
-        builder.putString("This is a small string");
+        String someString = "This is a small string";
+        builder.putString(someString);
         ByteBuffer b = builder.finish();
-        TestEq("This is a small string", FlexBuffers.getRoot(b).asString());
+        TestEq(someString, FlexBuffers.getRoot(b).asString());
 
         FlexBuffersBuilder failBuilder = new FlexBuffersBuilder(ByteBuffer.allocate(1));
         try {
-            failBuilder.putString("This is a small string");
+            failBuilder.putString(someString);
             // This should never be reached, it should throw an exception
             // since ByteBuffers do not grow
             assert(false);
@@ -1224,4 +1225,5 @@ class JavaTest {
             System.exit(1);
         }
     }
+
 }