1f7c6911047d63bc76292f55ce538da32818dd931Jesse Wilson/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one or more 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contributor license agreements. See the NOTICE file distributed with 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this work for additional information regarding copyright ownership. 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (the "License"); you may not use this file except in compliance with 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the License. You may obtain a copy of the License at 8f7c6911047d63bc76292f55ce538da32818dd931Jesse Wilson * 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 10f7c6911047d63bc76292f55ce538da32818dd931Jesse Wilson * 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.util.zip; 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 20f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstromimport dalvik.system.CloseGuard; 21c941a854631c4bf2369adc84887bb6dd386a1bccElliott Hughesimport java.io.FileDescriptor; 222d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughesimport java.util.Arrays; 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 252d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * This class decompresses data that was compressed using the <i>DEFLATE</i> 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * algorithm (see <a href="http://www.gzip.org/algorithm.txt">specification</a>). 2757995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson * 282d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * <p>It is usually more convenient to use {@link InflaterInputStream}. 292d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * 302d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * <p>To decompress an in-memory {@code byte[]} to another in-memory {@code byte[]} manually: 312d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * <pre> 322d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * byte[] compressedBytes = ... 332d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * int decompressedByteCount = ... // From your format's metadata. 342d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * Inflater inflater = new Inflater(); 352d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * inflater.setInput(compressedBytes, 0, compressedBytes.length); 362d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * byte[] decompressedBytes = new byte[decompressedByteCount]; 372d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * if (inflater.inflate(decompressedBytes) != decompressedByteCount) { 382d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * throw new AssertionError(); 392d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * } 402d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * inflater.end(); 412d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * </pre> 422d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * <p>In situations where you don't have all the input in one array (or have so much 432d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * input that you want to feed it to the inflater in chunks), it's possible to call 442d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * {@link #setInput} repeatedly, but you're much better off using {@link InflaterInputStream} 452d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * to handle all this for you. 462d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * 472d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * <p>If you don't know how big the decompressed data will be, you can call {@link #inflate} 482d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * repeatedly on a temporary buffer, copying the bytes to a {@link java.io.ByteArrayOutputStream}, 492d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * but this is probably another sign you'd be better off using {@link InflaterInputStream}. 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class Inflater { 52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 532d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes private int inLength; 54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 552d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes private int inRead; // Set by inflateImpl. 562d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes private boolean finished; // Set by inflateImpl. 572d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes private boolean needsDictionary; // Set by inflateImpl. 58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 5957995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson private long streamHandle = -1; 6057995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson 6112f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom private final CloseGuard guard = CloseGuard.get(); 62f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom 6357995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson /** 6457995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson * This constructor creates an inflater that expects a header from the input 652d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * stream. Use {@link #Inflater(boolean)} if the input comes without a ZLIB 6657995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson * header. 6757995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson */ 6857995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson public Inflater() { 6957995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson this(false); 7057995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson } 7157995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson 7257995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson /** 7357995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson * This constructor allows to create an inflater that expects no header from 7457995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson * the input stream. 7557995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson * 7657995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson * @param noHeader 7757995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson * {@code true} indicates that no ZLIB header comes with the 7857995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson * input. 7957995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson */ 8057995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson public Inflater(boolean noHeader) { 8157995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson streamHandle = createStream(noHeader); 8212f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom guard.open("end"); 8357995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson } 8457995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson 8557995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson private native long createStream(boolean noHeader1); 8657995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 882d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * Releases resources associated with this {@code Inflater}. Any unused 892d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * input or output is discarded. This method should be called explicitly in 902d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * order to free native resources as soon as possible. After {@code end()} is 912d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * called, other methods will typically throw {@code IllegalStateException}. 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public synchronized void end() { 94f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom guard.close(); 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (streamHandle != -1) { 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project endImpl(streamHandle); 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project inRead = 0; 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project inLength = 0; 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project streamHandle = -1; 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1032d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes private native void endImpl(long handle); 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 105e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom @Override protected void finalize() { 106e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom try { 10712f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom if (guard != null) { 10812f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom guard.warnIfOpen(); 10912f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom } 110e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom end(); 111e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } finally { 112e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom try { 113e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom super.finalize(); 114e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } catch (Throwable t) { 115e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom throw new AssertionError(t); 116e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } 117e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Indicates if the {@code Inflater} has inflated the entire deflated 1222d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * stream. If deflated bytes remain and {@link #needsInput} returns {@code 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * true} this method will return {@code false}. This method should be 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * called after all deflated input is supplied to the {@code Inflater}. 12557995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson * 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return {@code true} if all input has been inflated, {@code false} 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * otherwise. 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public synchronized boolean finished() { 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return finished; 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1342d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * Returns the {@link Adler32} checksum of the bytes inflated so far, or the 1352d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * checksum of the preset dictionary if {@link #needsDictionary} returns true. 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public synchronized int getAdler() { 138aee3e4d2e0a2830fc2ef8e96a13796d012becab2Elliott Hughes checkOpen(); 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return getAdlerImpl(streamHandle); 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1422d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes private native int getAdlerImpl(long handle); 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 14557995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson * Returns the total number of bytes read by the {@code Inflater}. This 1462d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * method is the same as {@link #getTotalIn} except that it returns a 14757995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson * {@code long} value instead of an integer. 14857995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson */ 14957995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson public synchronized long getBytesRead() { 150aee3e4d2e0a2830fc2ef8e96a13796d012becab2Elliott Hughes checkOpen(); 15157995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson return getTotalInImpl(streamHandle); 15257995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson } 15357995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson 15457995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson /** 1552d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * Returns a the total number of bytes written by this {@code Inflater}. This 1562d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * method is the same as {@code getTotalOut} except it returns a 15757995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson * {@code long} value instead of an integer. 15857995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson */ 15957995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson public synchronized long getBytesWritten() { 160aee3e4d2e0a2830fc2ef8e96a13796d012becab2Elliott Hughes checkOpen(); 16157995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson return getTotalOutImpl(streamHandle); 16257995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson } 16357995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson 16457995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson /** 1652d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * Returns the number of bytes of current input remaining to be read by this 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * inflater. 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public synchronized int getRemaining() { 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return inLength - inRead; 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1732d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * Returns the total number of bytes of input read by this {@code Inflater}. This 1742d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * method is limited to 32 bits; use {@link #getBytesRead} instead. 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public synchronized int getTotalIn() { 177aee3e4d2e0a2830fc2ef8e96a13796d012becab2Elliott Hughes checkOpen(); 1782d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes return (int) Math.min(getTotalInImpl(streamHandle), (long) Integer.MAX_VALUE); 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1812d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes private native long getTotalInImpl(long handle); 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1842d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * Returns the total number of bytes written to the output buffer by this {@code 1852d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * Inflater}. The method is limited to 32 bits; use {@link #getBytesWritten} instead. 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public synchronized int getTotalOut() { 188aee3e4d2e0a2830fc2ef8e96a13796d012becab2Elliott Hughes checkOpen(); 1892d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes return (int) Math.min(getTotalOutImpl(streamHandle), (long) Integer.MAX_VALUE); 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1922d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes private native long getTotalOutImpl(long handle); 193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1952d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * Inflates bytes from the current input and stores them in {@code buf}. 19657995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson * 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param buf 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the buffer where decompressed data bytes are written. 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the number of bytes inflated. 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws DataFormatException 201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the underlying stream is corrupted or was not compressed 202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * using a {@code Deflater}. 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int inflate(byte[] buf) throws DataFormatException { 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return inflate(buf, 0, buf.length); 206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 2092d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * Inflates up to {@code byteCount} bytes from the current input and stores them in 2102d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * {@code buf} starting at {@code offset}. 21157995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson * 212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws DataFormatException 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the underlying stream is corrupted or was not compressed 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * using a {@code Deflater}. 215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the number of bytes inflated. 216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 2172d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes public synchronized int inflate(byte[] buf, int offset, int byteCount) throws DataFormatException { 2182d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes Arrays.checkOffsetAndCount(buf.length, offset, byteCount); 219f7c6911047d63bc76292f55ce538da32818dd931Jesse Wilson 220aee3e4d2e0a2830fc2ef8e96a13796d012becab2Elliott Hughes checkOpen(); 221f7c6911047d63bc76292f55ce538da32818dd931Jesse Wilson 222f7c6911047d63bc76292f55ce538da32818dd931Jesse Wilson if (needsInput()) { 223f7c6911047d63bc76292f55ce538da32818dd931Jesse Wilson return 0; 224f7c6911047d63bc76292f55ce538da32818dd931Jesse Wilson } 225f7c6911047d63bc76292f55ce538da32818dd931Jesse Wilson 226f7c6911047d63bc76292f55ce538da32818dd931Jesse Wilson boolean neededDict = needsDictionary; 227f7c6911047d63bc76292f55ce538da32818dd931Jesse Wilson needsDictionary = false; 2282d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes int result = inflateImpl(buf, offset, byteCount, streamHandle); 229f7c6911047d63bc76292f55ce538da32818dd931Jesse Wilson if (needsDictionary && neededDict) { 230b1433b3bd4dfc05426e5d9c3100b5fbaa198d8a0Elliott Hughes throw new DataFormatException("Needs dictionary"); 231f7c6911047d63bc76292f55ce538da32818dd931Jesse Wilson } 232f7c6911047d63bc76292f55ce538da32818dd931Jesse Wilson return result; 233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2352d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes private native int inflateImpl(byte[] buf, int offset, int byteCount, long handle); 236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 2382d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * Returns true if the input bytes were compressed with a preset 2392d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * dictionary. This method should be called if the first call to {@link #inflate} returns 0, 2402d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * to determine whether a dictionary is required. If so, {@link #setDictionary} 2412d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * should be called with the appropriate dictionary before calling {@code 2422d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * inflate} again. Use {@link #getAdler} to determine which dictionary is required. 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public synchronized boolean needsDictionary() { 245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return needsDictionary; 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 2492d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * Returns true if {@link #setInput} must be called before inflation can continue. 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public synchronized boolean needsInput() { 252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return inRead == inLength; 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 2562d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * Resets this {@code Inflater}. Should be called prior to inflating a new 257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * set of data. 258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public synchronized void reset() { 260aee3e4d2e0a2830fc2ef8e96a13796d012becab2Elliott Hughes checkOpen(); 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project finished = false; 262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project needsDictionary = false; 263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project inLength = inRead = 0; 264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project resetImpl(streamHandle); 265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2672d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes private native void resetImpl(long handle); 268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 2702d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * Sets the preset dictionary to be used for inflation to {@code dictionary}. 2712d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * See {@link #needsDictionary} for details. 272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 2732d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes public synchronized void setDictionary(byte[] dictionary) { 2742d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes setDictionary(dictionary, 0, dictionary.length); 275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 2782d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * Sets the preset dictionary to be used for inflation to a subsequence of {@code dictionary} 2792d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * starting at {@code offset} and continuing for {@code byteCount} bytes. See {@link 2802d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * #needsDictionary} for details. 281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 2822d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes public synchronized void setDictionary(byte[] dictionary, int offset, int byteCount) { 283aee3e4d2e0a2830fc2ef8e96a13796d012becab2Elliott Hughes checkOpen(); 2842d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes Arrays.checkOffsetAndCount(dictionary.length, offset, byteCount); 2852d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes setDictionaryImpl(dictionary, offset, byteCount, streamHandle); 286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2882d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes private native void setDictionaryImpl(byte[] dictionary, int offset, int byteCount, long handle); 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 2912d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * Sets the current input to to be decompressed. This method should only be 2922d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * called if {@link #needsInput} returns {@code true}. 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public synchronized void setInput(byte[] buf) { 295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project setInput(buf, 0, buf.length); 296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 2992d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * Sets the current input to to be decompressed. This method should only be 3002d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes * called if {@link #needsInput} returns {@code true}. 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 3022d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes public synchronized void setInput(byte[] buf, int offset, int byteCount) { 303aee3e4d2e0a2830fc2ef8e96a13796d012becab2Elliott Hughes checkOpen(); 3042d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes Arrays.checkOffsetAndCount(buf.length, offset, byteCount); 3052d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes inRead = 0; 3062d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes inLength = byteCount; 3072d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes setInputImpl(buf, offset, byteCount, streamHandle); 308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 3102d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes private native void setInputImpl(byte[] buf, int offset, int byteCount, long handle); 3112d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes 3122d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes synchronized int setFileInput(FileDescriptor fd, long offset, int byteCount) { 313aee3e4d2e0a2830fc2ef8e96a13796d012becab2Elliott Hughes checkOpen(); 314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project inRead = 0; 3152d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes inLength = setFileInputImpl(fd, offset, byteCount, streamHandle); 316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return inLength; 317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 3192d9c5fa8ce0182cd8c14736241b709fd50cab6f8Elliott Hughes private native int setFileInputImpl(FileDescriptor fd, long offset, int byteCount, long handle); 320aee3e4d2e0a2830fc2ef8e96a13796d012becab2Elliott Hughes 321aee3e4d2e0a2830fc2ef8e96a13796d012becab2Elliott Hughes private void checkOpen() { 322aee3e4d2e0a2830fc2ef8e96a13796d012becab2Elliott Hughes if (streamHandle == -1) { 323aee3e4d2e0a2830fc2ef8e96a13796d012becab2Elliott Hughes throw new IllegalStateException("attempt to use Inflater after calling end"); 324aee3e4d2e0a2830fc2ef8e96a13796d012becab2Elliott Hughes } 325aee3e4d2e0a2830fc2ef8e96a13796d012becab2Elliott Hughes } 326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 327