1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package java.util.zip; 19 20 import dalvik.system.CloseGuard; 21 import java.util.Arrays; 22 import libcore.util.EmptyArray; 23 24 /** 25 * This class compresses data using the <i>DEFLATE</i> algorithm (see <a 26 * href="http://www.gzip.org/algorithm.txt">specification</a>). 27 * 28 * <p>It is usually more convenient to use {@link DeflaterOutputStream}. 29 * 30 * <p>To compress an in-memory {@code byte[]} to another in-memory {@code byte[]} manually: 31 * <pre> 32 * byte[] originalBytes = ... 33 * 34 * Deflater deflater = new Deflater(); 35 * deflater.setInput(originalBytes); 36 * deflater.finish(); 37 * 38 * ByteArrayOutputStream baos = new ByteArrayOutputStream(); 39 * byte[] buf = new byte[8192]; 40 * while (!deflater.finished()) { 41 * int byteCount = deflater.deflate(buf); 42 * baos.write(buf, 0, byteCount); 43 * } 44 * deflater.end(); 45 * 46 * byte[] compressedBytes = baos.toByteArray(); 47 * </pre> 48 * <p>In situations where you don't have all the input in one array (or have so much 49 * input that you want to feed it to the deflater in chunks), it's possible to call 50 * {@link #setInput setInput} repeatedly, but you're much better off using 51 * {@link DeflaterOutputStream} to handle all this for you. {@link DeflaterOutputStream} also helps 52 * minimize memory requirements — the sample code above is very expensive. 53 * 54 * <a name="compression_level"><h3>Compression levels</h3></a> 55 * <p>A compression level must be {@link #DEFAULT_COMPRESSION} to compromise between speed and 56 * compression (currently equivalent to level 6), or between 0 ({@link #NO_COMPRESSION}, where 57 * the input is simply copied) and 9 ({@link #BEST_COMPRESSION}). Level 1 ({@link #BEST_SPEED}) 58 * performs some compression, but with minimal speed overhead. 59 */ 60 public class Deflater { 61 62 /** 63 * This <a href="#compression_level">compression level</a> gives the best compression, 64 * but takes the most time. 65 */ 66 public static final int BEST_COMPRESSION = 9; 67 68 /** 69 * This <a href="#compression_level">compression level</a> gives minimal compression, 70 * but takes the least time (of any level that actually performs compression; 71 * see {@link #NO_COMPRESSION}). 72 */ 73 public static final int BEST_SPEED = 1; 74 75 /** 76 * This <a href="#compression_level">compression level</a> does no compression. 77 * It is even faster than {@link #BEST_SPEED}. 78 */ 79 public static final int NO_COMPRESSION = 0; 80 81 /** 82 * The default <a href="#compression_level">compression level</a>. 83 * This is a trade-off between speed and compression, currently equivalent to level 6. 84 */ 85 public static final int DEFAULT_COMPRESSION = -1; 86 87 /** 88 * The default compression strategy. 89 */ 90 public static final int DEFAULT_STRATEGY = 0; 91 92 /** 93 * The default compression method. 94 */ 95 public static final int DEFLATED = 8; 96 97 /** 98 * A compression strategy. 99 */ 100 public static final int FILTERED = 1; 101 102 /** 103 * A compression strategy. 104 */ 105 public static final int HUFFMAN_ONLY = 2; 106 107 /** 108 * Use buffering for best compression. 109 * 110 * @hide 111 * @since 1.7 112 */ 113 public static final int NO_FLUSH = 0; 114 115 /** 116 * Flush buffers so recipients can immediately decode the data sent thus 117 * far. This mode may degrade compression. 118 * 119 * @hide 120 * @since 1.7 121 */ 122 public static final int SYNC_FLUSH = 2; 123 124 /** 125 * Flush buffers so recipients can immediately decode the data sent thus 126 * far. The compression state is also reset to permit random access and 127 * recovery for clients who have discarded or damaged their own copy. This 128 * mode may degrade compression. 129 * 130 * @hide 131 * @since 1.7 132 */ 133 public static final int FULL_FLUSH = 3; 134 135 /** 136 * Flush buffers and mark the end of the data stream. 137 */ 138 private static final int FINISH = 4; 139 140 /** 141 * The ugly name flushParm is for RI compatibility, should code need to access this 142 * field via reflection if it's not able to use public API to choose what 143 * kind of flushing it gets. 144 */ 145 private int flushParm = NO_FLUSH; 146 147 private boolean finished; 148 149 private int compressLevel = DEFAULT_COMPRESSION; 150 151 private int strategy = DEFAULT_STRATEGY; 152 153 private long streamHandle = -1; 154 155 private byte[] inputBuffer; 156 157 private int inRead; 158 159 private int inLength; 160 161 private final CloseGuard guard = CloseGuard.get(); 162 163 /** 164 * Constructs a new {@code Deflater} instance using the 165 * default <a href="#compression_level">compression level</a>. 166 * The compression strategy can be specified with {@link #setStrategy}. A 167 * header is added to the output by default; use {@link 168 * #Deflater(int, boolean)} if you need to omit the header. 169 */ Deflater()170 public Deflater() { 171 this(DEFAULT_COMPRESSION, false); 172 } 173 174 /** 175 * Constructs a new {@code Deflater} instance with the 176 * given <a href="#compression_level">compression level</a>. 177 * The compression strategy can be specified with {@link #setStrategy}. 178 * A header is added to the output by default; use 179 * {@link #Deflater(int, boolean)} if you need to omit the header. 180 */ Deflater(int level)181 public Deflater(int level) { 182 this(level, false); 183 } 184 185 /** 186 * Constructs a new {@code Deflater} instance with the 187 * given <a href="#compression_level">compression level</a>. 188 * If {@code noHeader} is true, no ZLIB header is added to the 189 * output. In a zip file, every entry (compressed file) comes with such a 190 * header. The strategy can be specified using {@link #setStrategy}. 191 */ Deflater(int level, boolean noHeader)192 public Deflater(int level, boolean noHeader) { 193 if (level < DEFAULT_COMPRESSION || level > BEST_COMPRESSION) { 194 throw new IllegalArgumentException("Bad level: " + level); 195 } 196 compressLevel = level; 197 streamHandle = createStream(compressLevel, strategy, noHeader); 198 guard.open("end"); 199 } 200 201 /** 202 * Deflates the data (previously passed to {@link #setInput setInput}) into the 203 * supplied buffer. 204 * 205 * @return number of bytes of compressed data written to {@code buf}. 206 */ deflate(byte[] buf)207 public int deflate(byte[] buf) { 208 return deflate(buf, 0, buf.length); 209 } 210 211 /** 212 * Deflates data (previously passed to {@link #setInput setInput}) into a specific 213 * region within the supplied buffer. 214 * 215 * @return the number of bytes of compressed data written to {@code buf}. 216 */ deflate(byte[] buf, int offset, int byteCount)217 public synchronized int deflate(byte[] buf, int offset, int byteCount) { 218 return deflateImpl(buf, offset, byteCount, flushParm); 219 } 220 221 /** 222 * Deflates data (previously passed to {@link #setInput setInput}) into a specific 223 * region within the supplied buffer, optionally flushing the input buffer. 224 * 225 * @param flush one of {@link #NO_FLUSH}, {@link #SYNC_FLUSH} or {@link #FULL_FLUSH}. 226 * @return the number of compressed bytes written to {@code buf}. If this 227 * equals {@code byteCount}, the number of bytes of input to be flushed 228 * may have exceeded the output buffer's capacity. In this case, 229 * finishing a flush will require the output buffer to be drained 230 * and additional calls to {@link #deflate} to be made. 231 * @hide 232 * @since 1.7 233 */ deflate(byte[] buf, int offset, int byteCount, int flush)234 public synchronized int deflate(byte[] buf, int offset, int byteCount, int flush) { 235 if (flush != NO_FLUSH && flush != SYNC_FLUSH && flush != FULL_FLUSH) { 236 throw new IllegalArgumentException("Bad flush value: " + flush); 237 } 238 return deflateImpl(buf, offset, byteCount, flush); 239 } 240 deflateImpl(byte[] buf, int offset, int byteCount, int flush)241 private synchronized int deflateImpl(byte[] buf, int offset, int byteCount, int flush) { 242 checkOpen(); 243 Arrays.checkOffsetAndCount(buf.length, offset, byteCount); 244 if (inputBuffer == null) { 245 setInput(EmptyArray.BYTE); 246 } 247 return deflateImpl(buf, offset, byteCount, streamHandle, flush); 248 } 249 deflateImpl(byte[] buf, int offset, int byteCount, long handle, int flushParm)250 private native int deflateImpl(byte[] buf, int offset, int byteCount, long handle, int flushParm); 251 252 /** 253 * Frees all resources held onto by this deflating algorithm. Any unused 254 * input or output is discarded. This method should be called explicitly in 255 * order to free native resources as soon as possible. After {@code end()} is 256 * called, other methods will typically throw {@code IllegalStateException}. 257 */ end()258 public synchronized void end() { 259 guard.close(); 260 endImpl(); 261 } 262 endImpl()263 private void endImpl() { 264 if (streamHandle != -1) { 265 endImpl(streamHandle); 266 inputBuffer = null; 267 streamHandle = -1; 268 } 269 } 270 endImpl(long handle)271 private native void endImpl(long handle); 272 finalize()273 @Override protected void finalize() { 274 try { 275 if (guard != null) { 276 guard.warnIfOpen(); 277 } 278 synchronized (this) { 279 end(); // to allow overriding classes to clean up 280 endImpl(); // in case those classes don't call super.end() 281 } 282 } finally { 283 try { 284 super.finalize(); 285 } catch (Throwable t) { 286 throw new AssertionError(t); 287 } 288 } 289 } 290 291 /** 292 * Indicates to the {@code Deflater} that all uncompressed input has been provided 293 * to it. 294 * 295 * @see #finished 296 */ finish()297 public synchronized void finish() { 298 flushParm = FINISH; 299 } 300 301 /** 302 * Returns true if {@link #finish finish} has been called and all 303 * data provided by {@link #setInput setInput} has been 304 * successfully compressed and consumed by {@link #deflate deflate}. 305 */ finished()306 public synchronized boolean finished() { 307 return finished; 308 } 309 310 /** 311 * Returns the {@link Adler32} checksum of the uncompressed data read so far. 312 */ getAdler()313 public synchronized int getAdler() { 314 checkOpen(); 315 return getAdlerImpl(streamHandle); 316 } 317 getAdlerImpl(long handle)318 private native int getAdlerImpl(long handle); 319 320 /** 321 * Returns the total number of bytes of input read by this {@code Deflater}. This 322 * method is limited to 32 bits; use {@link #getBytesRead} instead. 323 */ getTotalIn()324 public synchronized int getTotalIn() { 325 checkOpen(); 326 return (int) getTotalInImpl(streamHandle); 327 } 328 getTotalInImpl(long handle)329 private native long getTotalInImpl(long handle); 330 331 /** 332 * Returns the total number of bytes written to the output buffer by this {@code 333 * Deflater}. The method is limited to 32 bits; use {@link #getBytesWritten} instead. 334 */ getTotalOut()335 public synchronized int getTotalOut() { 336 checkOpen(); 337 return (int) getTotalOutImpl(streamHandle); 338 } 339 getTotalOutImpl(long handle)340 private native long getTotalOutImpl(long handle); 341 342 /** 343 * Returns true if {@link #setInput setInput} must be called before deflation can continue. 344 * If all uncompressed data has been provided to the {@code Deflater}, 345 * {@link #finish} must be called to ensure the compressed data is output. 346 */ needsInput()347 public synchronized boolean needsInput() { 348 if (inputBuffer == null) { 349 return true; 350 } 351 return inRead == inLength; 352 } 353 354 /** 355 * Resets the {@code Deflater} to accept new input without affecting any 356 * previously made settings for the compression strategy or level. This 357 * operation <i>must</i> be called after {@link #finished} returns 358 * true if the {@code Deflater} is to be reused. 359 */ reset()360 public synchronized void reset() { 361 checkOpen(); 362 flushParm = NO_FLUSH; 363 finished = false; 364 resetImpl(streamHandle); 365 inputBuffer = null; 366 } 367 resetImpl(long handle)368 private native void resetImpl(long handle); 369 370 /** 371 * Sets the dictionary to be used for compression by this {@code Deflater}. 372 * This method can only be called if this {@code Deflater} supports the writing 373 * of ZLIB headers. This is the default, but can be overridden 374 * using {@link #Deflater(int, boolean)}. 375 */ setDictionary(byte[] dictionary)376 public void setDictionary(byte[] dictionary) { 377 setDictionary(dictionary, 0, dictionary.length); 378 } 379 380 /** 381 * Sets the dictionary to be used for compression by this {@code Deflater}. 382 * This method can only be called if this {@code Deflater} supports the writing 383 * of ZLIB headers. This is the default, but can be overridden 384 * using {@link #Deflater(int, boolean)}. 385 */ setDictionary(byte[] buf, int offset, int byteCount)386 public synchronized void setDictionary(byte[] buf, int offset, int byteCount) { 387 checkOpen(); 388 Arrays.checkOffsetAndCount(buf.length, offset, byteCount); 389 setDictionaryImpl(buf, offset, byteCount, streamHandle); 390 } 391 setDictionaryImpl(byte[] buf, int offset, int byteCount, long handle)392 private native void setDictionaryImpl(byte[] buf, int offset, int byteCount, long handle); 393 394 /** 395 * Sets the input buffer the {@code Deflater} will use to extract uncompressed bytes 396 * for later compression. 397 */ setInput(byte[] buf)398 public void setInput(byte[] buf) { 399 setInput(buf, 0, buf.length); 400 } 401 402 /** 403 * Sets the input buffer the {@code Deflater} will use to extract uncompressed bytes 404 * for later compression. 405 */ setInput(byte[] buf, int offset, int byteCount)406 public synchronized void setInput(byte[] buf, int offset, int byteCount) { 407 checkOpen(); 408 Arrays.checkOffsetAndCount(buf.length, offset, byteCount); 409 inLength = byteCount; 410 inRead = 0; 411 if (inputBuffer == null) { 412 setLevelsImpl(compressLevel, strategy, streamHandle); 413 } 414 inputBuffer = buf; 415 setInputImpl(buf, offset, byteCount, streamHandle); 416 } 417 setLevelsImpl(int level, int strategy, long handle)418 private native void setLevelsImpl(int level, int strategy, long handle); 419 setInputImpl(byte[] buf, int offset, int byteCount, long handle)420 private native void setInputImpl(byte[] buf, int offset, int byteCount, long handle); 421 422 /** 423 * Sets the given <a href="#compression_level">compression level</a> 424 * to be used when compressing data. This value must be set 425 * prior to calling {@link #setInput setInput}. 426 * @exception IllegalArgumentException 427 * If the compression level is invalid. 428 */ setLevel(int level)429 public synchronized void setLevel(int level) { 430 if (level < DEFAULT_COMPRESSION || level > BEST_COMPRESSION) { 431 throw new IllegalArgumentException("Bad level: " + level); 432 } 433 if (inputBuffer != null) { 434 throw new IllegalStateException("setLevel cannot be called after setInput"); 435 } 436 compressLevel = level; 437 } 438 439 /** 440 * Sets the compression strategy to be used. The strategy must be one of 441 * FILTERED, HUFFMAN_ONLY or DEFAULT_STRATEGY. This value must be set prior 442 * to calling {@link #setInput setInput}. 443 * 444 * @exception IllegalArgumentException 445 * If the strategy specified is not one of FILTERED, 446 * HUFFMAN_ONLY or DEFAULT_STRATEGY. 447 */ setStrategy(int strategy)448 public synchronized void setStrategy(int strategy) { 449 if (strategy < DEFAULT_STRATEGY || strategy > HUFFMAN_ONLY) { 450 throw new IllegalArgumentException("Bad strategy: " + strategy); 451 } 452 if (inputBuffer != null) { 453 throw new IllegalStateException("setStrategy cannot be called after setInput"); 454 } 455 this.strategy = strategy; 456 } 457 458 /** 459 * Returns the total number of bytes read by the {@code Deflater}. This 460 * method is the same as {@link #getTotalIn} except that it returns a 461 * {@code long} value instead of an integer. 462 */ getBytesRead()463 public synchronized long getBytesRead() { 464 checkOpen(); 465 return getTotalInImpl(streamHandle); 466 } 467 468 /** 469 * Returns a the total number of bytes written by this {@code Deflater}. This 470 * method is the same as {@code getTotalOut} except it returns a 471 * {@code long} value instead of an integer. 472 */ getBytesWritten()473 public synchronized long getBytesWritten() { 474 checkOpen(); 475 return getTotalOutImpl(streamHandle); 476 } 477 createStream(int level, int strategy1, boolean noHeader1)478 private native long createStream(int level, int strategy1, boolean noHeader1); 479 checkOpen()480 private void checkOpen() { 481 if (streamHandle == -1) { 482 throw new IllegalStateException("attempt to use Deflater after calling end"); 483 } 484 } 485 } 486