Java wrapper: allow using partial byte arrays (#999)

diff --git a/java/org/brotli/wrapper/dec/Decoder.java b/java/org/brotli/wrapper/dec/Decoder.java
index de69d3a..a2228d1 100644
--- a/java/org/brotli/wrapper/dec/Decoder.java
+++ b/java/org/brotli/wrapper/dec/Decoder.java
@@ -138,16 +138,14 @@
     source.close();
   }
 
-  /**
-   * Decodes the given data buffer.
-   */
-  public static byte[] decompress(byte[] data) throws IOException {
-    DecoderJNI.Wrapper decoder = new DecoderJNI.Wrapper(data.length);
+  /** Decodes the given data buffer starting at offset till length. */
+  public static byte[] decompress(byte[] data, int offset, int length) throws IOException {
+    DecoderJNI.Wrapper decoder = new DecoderJNI.Wrapper(length);
     ArrayList<byte[]> output = new ArrayList<byte[]>();
     int totalOutputSize = 0;
     try {
-      decoder.getInputBuffer().put(data);
-      decoder.push(data.length);
+      decoder.getInputBuffer().put(data, offset, length);
+      decoder.push(length);
       while (decoder.getStatus() != DecoderJNI.Status.DONE) {
         switch (decoder.getStatus()) {
           case OK:
@@ -182,11 +180,16 @@
       return output.get(0);
     }
     byte[] result = new byte[totalOutputSize];
-    int offset = 0;
+    int resultOffset = 0;
     for (byte[] chunk : output) {
-      System.arraycopy(chunk, 0, result, offset, chunk.length);
-      offset += chunk.length;
+      System.arraycopy(chunk, 0, result, resultOffset, chunk.length);
+      resultOffset += chunk.length;
     }
     return result;
   }
+
+  /** Decodes the given data buffer. */
+  public static byte[] decompress(byte[] data) throws IOException {
+    return decompress(data, 0, data.length);
+  }
 }
diff --git a/java/org/brotli/wrapper/enc/Encoder.java b/java/org/brotli/wrapper/enc/Encoder.java
index 88af481..696bd57 100644
--- a/java/org/brotli/wrapper/enc/Encoder.java
+++ b/java/org/brotli/wrapper/enc/Encoder.java
@@ -6,13 +6,13 @@
 
 package org.brotli.wrapper.enc;
 
-import org.brotli.enc.PreparedDictionary;
 import java.io.IOException;
 import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.channels.WritableByteChannel;
 import java.util.ArrayList;
 import java.util.List;
+import org.brotli.enc.PreparedDictionary;
 
 /**
  * Base class for OutputStream / Channel implementations.
@@ -209,22 +209,21 @@
     }
   }
 
-  /**
-   * Encodes the given data buffer.
-   */
-  public static byte[] compress(byte[] data, Parameters params) throws IOException {
-    if (data.length == 0) {
+  /** Encodes the given data buffer. */
+  public static byte[] compress(byte[] data, int offset, int length, Parameters params)
+      throws IOException {
+    if (length == 0) {
       byte[] empty = new byte[1];
       empty[0] = 6;
       return empty;
     }
     /* data.length > 0 */
     EncoderJNI.Wrapper encoder =
-        new EncoderJNI.Wrapper(data.length, params.quality, params.lgwin, params.mode);
+        new EncoderJNI.Wrapper(length, params.quality, params.lgwin, params.mode);
     ArrayList<byte[]> output = new ArrayList<byte[]>();
     int totalOutputSize = 0;
     try {
-      encoder.getInputBuffer().put(data);
+      encoder.getInputBuffer().put(data, offset, length);
       encoder.push(EncoderJNI.Operation.FINISH, data.length);
       while (true) {
         if (!encoder.isSuccess()) {
@@ -248,18 +247,27 @@
       return output.get(0);
     }
     byte[] result = new byte[totalOutputSize];
-    int offset = 0;
+    int resultOffset = 0;
     for (byte[] chunk : output) {
-      System.arraycopy(chunk, 0, result, offset, chunk.length);
-      offset += chunk.length;
+      System.arraycopy(chunk, 0, result, resultOffset, chunk.length);
+      resultOffset += chunk.length;
     }
     return result;
   }
 
+  /** Encodes the given data buffer. */
+  public static byte[] compress(byte[] data, Parameters params) throws IOException {
+    return compress(data, 0, data.length, params);
+  }
+
   public static byte[] compress(byte[] data) throws IOException {
     return compress(data, new Parameters());
   }
 
+  public static byte[] compress(byte[] data, int offset, int length) throws IOException {
+    return compress(data, offset, length, new Parameters());
+  }
+
   /**
    * Prepares raw or serialized dictionary for being used by encoder.
    *