java: Enhance TMemoryInputTransport to allow operation on specific range of a buffer rather than the whole thing. This will allow us to avoid making array copies in some instances.

git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@930574 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/java/src/org/apache/thrift/TDeserializer.java b/lib/java/src/org/apache/thrift/TDeserializer.java
index 0797e7a..3c43a45 100644
--- a/lib/java/src/org/apache/thrift/TDeserializer.java
+++ b/lib/java/src/org/apache/thrift/TDeserializer.java
@@ -52,7 +52,7 @@
    * @param protocolFactory Factory to create a protocol
    */
   public TDeserializer(TProtocolFactory protocolFactory) {
-    trans_ = new TMemoryInputTransport(null);
+    trans_ = new TMemoryInputTransport();
     protocol_ = protocolFactory.getProtocol(trans_);
   }
 
diff --git a/lib/java/src/org/apache/thrift/transport/TFramedTransport.java b/lib/java/src/org/apache/thrift/transport/TFramedTransport.java
index 74e2c97..1387ac1 100644
--- a/lib/java/src/org/apache/thrift/transport/TFramedTransport.java
+++ b/lib/java/src/org/apache/thrift/transport/TFramedTransport.java
@@ -85,18 +85,22 @@
     return readBuffer_.read(buf, off, len);
   }
 
+  @Override
   public byte[] getBuffer() {
     return readBuffer_.getBuffer();
   }
 
+  @Override
   public int getBufferPosition() {
     return readBuffer_.getBufferPosition();
   }
 
+  @Override
   public int getBytesRemainingInBuffer() {
     return readBuffer_.getBytesRemainingInBuffer();
   }
 
+  @Override
   public void consumeBuffer(int len) {
     readBuffer_.consumeBuffer(len);
   }
diff --git a/lib/java/src/org/apache/thrift/transport/TMemoryInputTransport.java b/lib/java/src/org/apache/thrift/transport/TMemoryInputTransport.java
index 845c835..0a0998d 100644
--- a/lib/java/src/org/apache/thrift/transport/TMemoryInputTransport.java
+++ b/lib/java/src/org/apache/thrift/transport/TMemoryInputTransport.java
@@ -1,17 +1,30 @@
 package org.apache.thrift.transport;
 
-public class TMemoryInputTransport extends TTransport {
+public final class TMemoryInputTransport extends TTransport {
 
   private byte[] buf_;
   private int pos_;
+  private int endPos_;
+
+  public TMemoryInputTransport() {
+  }
 
   public TMemoryInputTransport(byte[] buf) {
     reset(buf);
   }
 
+  public TMemoryInputTransport(byte[] buf, int offset, int length) {
+    reset(buf, offset, length);
+  }
+
   public void reset(byte[] buf) {
+    reset(buf, 0, buf.length);
+  }
+
+  public void reset(byte[] buf, int offset, int length) {
     buf_ = buf;
-    pos_ = 0;
+    pos_ = offset;
+    endPos_ = offset + length;
   }
 
   @Override
@@ -51,7 +64,7 @@
   }
 
   public int getBytesRemainingInBuffer() {
-    return buf_.length - pos_;
+    return endPos_ - pos_;
   }
 
   public void consumeBuffer(int len) {
diff --git a/lib/java/test/org/apache/thrift/transport/TestTMemoryInputTransport.java b/lib/java/test/org/apache/thrift/transport/TestTMemoryInputTransport.java
index 2cfbac6..0b1702e 100644
--- a/lib/java/test/org/apache/thrift/transport/TestTMemoryInputTransport.java
+++ b/lib/java/test/org/apache/thrift/transport/TestTMemoryInputTransport.java
@@ -42,4 +42,26 @@
     assertEquals(new_buf, trans.getBuffer());
     assertEquals(3, trans.getBytesRemainingInBuffer());
   }
+
+  public void testWithOffsetAndLength() throws Exception {
+    byte[] input_buf = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+    TMemoryInputTransport trans = new TMemoryInputTransport(input_buf, 1, 3);
+    assertEquals(1, trans.getBufferPosition());
+    assertEquals(3, trans.getBytesRemainingInBuffer());
+    byte[] readBuffer = new byte[3];
+    trans.readAll(readBuffer, 0, 3);
+    assertTrue(Arrays.equals(new byte[]{2, 3, 4}, readBuffer));
+
+    try {
+      assertEquals(0, trans.readAll(readBuffer, 0, 3));
+      fail("should have thrown an exception");
+    } catch (Exception e) {
+      // yay
+    }
+
+    trans.reset(input_buf, 3, 4);
+    readBuffer = new byte[4];
+    trans.readAll(readBuffer, 0, 4);
+    assertTrue(Arrays.equals(new byte[]{4, 5, 6, 7}, readBuffer));
+  }
 }