History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/util/zip/Deflater.java (1 of 18352 files). Show all

Unified · Split

java/pkg/java/util/zip/Deflater.java+550−0
@@ -0,0 +1,550 @@
1/*
2 * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package java.util.zip;
27
28/**
29 * This class provides support for general purpose compression using the
30 * popular ZLIB compression library. The ZLIB compression library was
31 * initially developed as part of the PNG graphics standard and is not
32 * protected by patents. It is fully described in the specifications at
33 * the <a href="package-summary.html#package_description">java.util.zip
34 * package description</a>.
35 *
36 * <p>The following code fragment demonstrates a trivial compression
37 * and decompression of a string using <tt>Deflater</tt> and
38 * <tt>Inflater</tt>.
39 *
40 * <blockquote><pre>
41 * try {
42 * // Encode a String into bytes
43 * String inputString = "blahblahblah";
44 * byte[] input = inputString.getBytes("UTF-8");
45 *
46 * // Compress the bytes
47 * byte[] output = new byte[100];
48 * Deflater compresser = new Deflater();
49 * compresser.setInput(input);
50 * compresser.finish();
51 * int compressedDataLength = compresser.deflate(output);
52 * compresser.end();
53 *
54 * // Decompress the bytes
55 * Inflater decompresser = new Inflater();
56 * decompresser.setInput(output, 0, compressedDataLength);
57 * byte[] result = new byte[100];
58 * int resultLength = decompresser.inflate(result);
59 * decompresser.end();
60 *
61 * // Decode the bytes into a String
62 * String outputString = new String(result, 0, resultLength, "UTF-8");
63 * } catch(java.io.UnsupportedEncodingException ex) {
64 * // handle
65 * } catch (java.util.zip.DataFormatException ex) {
66 * // handle
67 * }
68 * </pre></blockquote>
69 *
70 * @see Inflater
71 * @author David Connelly
72 */
73public
74class Deflater {
75
76 private final ZStreamRef zsRef;
77 private byte[] buf = new byte[0];
78 private int off, len;
79 private int level, strategy;
80 private boolean setParams;
81 private boolean finish, finished;
82
83 /**
84 * Compression method for the deflate algorithm (the only one currently
85 * supported).
86 */
87 public static final int DEFLATED = 8;
88
89 /**
90 * Compression level for no compression.
91 */
92 public static final int NO_COMPRESSION = 0;
93
94 /**
95 * Compression level for fastest compression.
96 */
97 public static final int BEST_SPEED = 1;
98
99 /**
100 * Compression level for best compression.
101 */
102 public static final int BEST_COMPRESSION = 9;
103
104 /**
105 * Default compression level.
106 */
107 public static final int DEFAULT_COMPRESSION = -1;
108
109 /**
110 * Compression strategy best used for data consisting mostly of small
111 * values with a somewhat random distribution. Forces more Huffman coding
112 * and less string matching.
113 */
114 public static final int FILTERED = 1;
115
116 /**
117 * Compression strategy for Huffman coding only.
118 */
119 public static final int HUFFMAN_ONLY = 2;
120
121 /**
122 * Default compression strategy.
123 */
124 public static final int DEFAULT_STRATEGY = 0;
125
126 /**
127 * Compression flush mode used to achieve best compression result.
128 *
129 * @see Deflater#deflate(byte[], int, int, int)
130 * @since 1.7
131 */
132 public static final int NO_FLUSH = 0;
133
134 /**
135 * Compression flush mode used to flush out all pending output; may
136 * degrade compression for some compression algorithms.
137 *
138 * @see Deflater#deflate(byte[], int, int, int)
139 * @since 1.7
140 */
141 public static final int SYNC_FLUSH = 2;
142
143 /**
144 * Compression flush mode used to flush out all pending output and
145 * reset the deflater. Using this mode too often can seriously degrade
146 * compression.
147 *
148 * @see Deflater#deflate(byte[], int, int, int)
149 * @since 1.7
150 */
151 public static final int FULL_FLUSH = 3;
152
153 static {
154 /* Zip library is loaded from System.initializeSystemClass */
155 initIDs();
156 }
157
158 /**
159 * Creates a new compressor using the specified compression level.
160 * If 'nowrap' is true then the ZLIB header and checksum fields will
161 * not be used in order to support the compression format used in
162 * both GZIP and PKZIP.
163 * @param level the compression level (0-9)
164 * @param nowrap if true then use GZIP compatible compression
165 */
166 public Deflater(int level, boolean nowrap) {
167 this.level = level;
168 this.strategy = DEFAULT_STRATEGY;
169 this.zsRef = new ZStreamRef(init(level, DEFAULT_STRATEGY, nowrap));
170 }
171
172 /**
173 * Creates a new compressor using the specified compression level.
174 * Compressed data will be generated in ZLIB format.
175 * @param level the compression level (0-9)
176 */
177 public Deflater(int level) {
178 this(level, false);
179 }
180
181 /**
182 * Creates a new compressor with the default compression level.
183 * Compressed data will be generated in ZLIB format.
184 */
185 public Deflater() {
186 this(DEFAULT_COMPRESSION, false);
187 }
188
189 /**
190 * Sets input data for compression. This should be called whenever
191 * needsInput() returns true indicating that more input data is required.
192 * @param b the input data bytes
193 * @param off the start offset of the data
194 * @param len the length of the data
195 * @see Deflater#needsInput
196 */
197 public void setInput(byte[] b, int off, int len) {
198 if (b== null) {
199 throw new NullPointerException();
200 }
201 if (off < 0 || len < 0 || off > b.length - len) {
202 throw new ArrayIndexOutOfBoundsException();
203 }
204 synchronized (zsRef) {
205 this.buf = b;
206 this.off = off;
207 this.len = len;
208 }
209 }
210
211 /**
212 * Sets input data for compression. This should be called whenever
213 * needsInput() returns true indicating that more input data is required.
214 * @param b the input data bytes
215 * @see Deflater#needsInput
216 */
217 public void setInput(byte[] b) {
218 setInput(b, 0, b.length);
219 }
220
221 /**
222 * Sets preset dictionary for compression. A preset dictionary is used
223 * when the history buffer can be predetermined. When the data is later
224 * uncompressed with Inflater.inflate(), Inflater.getAdler() can be called
225 * in order to get the Adler-32 value of the dictionary required for
226 * decompression.
227 * @param b the dictionary data bytes
228 * @param off the start offset of the data
229 * @param len the length of the data
230 * @see Inflater#inflate
231 * @see Inflater#getAdler
232 */
233 public void setDictionary(byte[] b, int off, int len) {
234 if (b == null) {
235 throw new NullPointerException();
236 }
237 if (off < 0 || len < 0 || off > b.length - len) {
238 throw new ArrayIndexOutOfBoundsException();
239 }
240 synchronized (zsRef) {
241 ensureOpen();
242 setDictionary(zsRef.address(), b, off, len);
243 }
244 }
245
246 /**
247 * Sets preset dictionary for compression. A preset dictionary is used
248 * when the history buffer can be predetermined. When the data is later
249 * uncompressed with Inflater.inflate(), Inflater.getAdler() can be called
250 * in order to get the Adler-32 value of the dictionary required for
251 * decompression.
252 * @param b the dictionary data bytes
253 * @see Inflater#inflate
254 * @see Inflater#getAdler
255 */
256 public void setDictionary(byte[] b) {
257 setDictionary(b, 0, b.length);
258 }
259
260 /**
261 * Sets the compression strategy to the specified value.
262 * @param strategy the new compression strategy
263 * @exception IllegalArgumentException if the compression strategy is
264 * invalid
265 */
266 public void setStrategy(int strategy) {
267 switch (strategy) {
268 case DEFAULT_STRATEGY:
269 case FILTERED:
270 case HUFFMAN_ONLY:
271 break;
272 default:
273 throw new IllegalArgumentException();
274 }
275 synchronized (zsRef) {
276 if (this.strategy != strategy) {
277 this.strategy = strategy;
278 setParams = true;
279 }
280 }
281 }
282
283 /**
284 * Sets the current compression level to the specified value.
285 * @param level the new compression level (0-9)
286 * @exception IllegalArgumentException if the compression level is invalid
287 */
288 public void setLevel(int level) {
289 if ((level < 0 || level > 9) && level != DEFAULT_COMPRESSION) {
290 throw new IllegalArgumentException("invalid compression level");
291 }
292 synchronized (zsRef) {
293 if (this.level != level) {
294 this.level = level;
295 setParams = true;
296 }
297 }
298 }
299
300 /**
301 * Returns true if the input data buffer is empty and setInput()
302 * should be called in order to provide more input.
303 * @return true if the input data buffer is empty and setInput()
304 * should be called in order to provide more input
305 */
306 public boolean needsInput() {
307 return len <= 0;
308 }
309
310 /**
311 * When called, indicates that compression should end with the current
312 * contents of the input buffer.
313 */
314 public void finish() {
315 synchronized (zsRef) {
316 finish = true;
317 }
318 }
319
320 /**
321 * Returns true if the end of the compressed data output stream has
322 * been reached.
323 * @return true if the end of the compressed data output stream has
324 * been reached
325 */
326 public boolean finished() {
327 synchronized (zsRef) {
328 return finished;
329 }
330 }
331
332 /**
333 * Compresses the input data and fills specified buffer with compressed
334 * data. Returns actual number of bytes of compressed data. A return value
335 * of 0 indicates that {@link #needsInput() needsInput} should be called
336 * in order to determine if more input data is required.
337 *
338 * <p>This method uses {@link #NO_FLUSH} as its compression flush mode.
339 * An invocation of this method of the form {@code deflater.deflate(b, off, len)}
340 * yields the same result as the invocation of
341 * {@code deflater.deflate(b, off, len, Deflater.NO_FLUSH)}.
342 *
343 * @param b the buffer for the compressed data
344 * @param off the start offset of the data
345 * @param len the maximum number of bytes of compressed data
346 * @return the actual number of bytes of compressed data written to the
347 * output buffer
348 */
349 public int deflate(byte[] b, int off, int len) {
350 return deflate(b, off, len, NO_FLUSH);
351 }
352
353 /**
354 * Compresses the input data and fills specified buffer with compressed
355 * data. Returns actual number of bytes of compressed data. A return value
356 * of 0 indicates that {@link #needsInput() needsInput} should be called
357 * in order to determine if more input data is required.
358 *
359 * <p>This method uses {@link #NO_FLUSH} as its compression flush mode.
360 * An invocation of this method of the form {@code deflater.deflate(b)}
361 * yields the same result as the invocation of
362 * {@code deflater.deflate(b, 0, b.length, Deflater.NO_FLUSH)}.
363 *
364 * @param b the buffer for the compressed data
365 * @return the actual number of bytes of compressed data written to the
366 * output buffer
367 */
368 public int deflate(byte[] b) {
369 return deflate(b, 0, b.length, NO_FLUSH);
370 }
371
372 /**
373 * Compresses the input data and fills the specified buffer with compressed
374 * data. Returns actual number of bytes of data compressed.
375 *
376 * <p>Compression flush mode is one of the following three modes:
377 *
378 * <ul>
379 * <li>{@link #NO_FLUSH}: allows the deflater to decide how much data
380 * to accumulate, before producing output, in order to achieve the best
381 * compression (should be used in normal use scenario). A return value
382 * of 0 in this flush mode indicates that {@link #needsInput()} should
383 * be called in order to determine if more input data is required.
384 *
385 * <li>{@link #SYNC_FLUSH}: all pending output in the deflater is flushed,
386 * to the specified output buffer, so that an inflater that works on
387 * compressed data can get all input data available so far (In particular
388 * the {@link #needsInput()} returns {@code true} after this invocation
389 * if enough output space is provided). Flushing with {@link #SYNC_FLUSH}
390 * may degrade compression for some compression algorithms and so it
391 * should be used only when necessary.
392 *
393 * <li>{@link #FULL_FLUSH}: all pending output is flushed out as with
394 * {@link #SYNC_FLUSH}. The compression state is reset so that the inflater
395 * that works on the compressed output data can restart from this point
396 * if previous compressed data has been damaged or if random access is
397 * desired. Using {@link #FULL_FLUSH} too often can seriously degrade
398 * compression.
399 * </ul>
400 *
401 * <p>In the case of {@link #FULL_FLUSH} or {@link #SYNC_FLUSH}, if
402 * the return value is {@code len}, the space available in output
403 * buffer {@code b}, this method should be invoked again with the same
404 * {@code flush} parameter and more output space.
405 *
406 * @param b the buffer for the compressed data
407 * @param off the start offset of the data
408 * @param len the maximum number of bytes of compressed data
409 * @param flush the compression flush mode
410 * @return the actual number of bytes of compressed data written to
411 * the output buffer
412 *
413 * @throws IllegalArgumentException if the flush mode is invalid
414 * @since 1.7
415 */
416 public int deflate(byte[] b, int off, int len, int flush) {
417 if (b == null) {
418 throw new NullPointerException();
419 }
420 if (off < 0 || len < 0 || off > b.length - len) {
421 throw new ArrayIndexOutOfBoundsException();
422 }
423 synchronized (zsRef) {
424 ensureOpen();
425 if (flush == NO_FLUSH || flush == SYNC_FLUSH ||
426 flush == FULL_FLUSH)
427 return deflateBytes(zsRef.address(), b, off, len, flush);
428 throw new IllegalArgumentException();
429 }
430 }
431
432 /**
433 * Returns the ADLER-32 value of the uncompressed data.
434 * @return the ADLER-32 value of the uncompressed data
435 */
436 public int getAdler() {
437 synchronized (zsRef) {
438 ensureOpen();
439 return getAdler(zsRef.address());
440 }
441 }
442
443 /**
444 * Returns the total number of uncompressed bytes input so far.
445 *
446 * <p>Since the number of bytes may be greater than
447 * Integer.MAX_VALUE, the {@link #getBytesRead()} method is now
448 * the preferred means of obtaining this information.</p>
449 *
450 * @return the total number of uncompressed bytes input so far
451 */
452 public int getTotalIn() {
453 return (int) getBytesRead();
454 }
455
456 /**
457 * Returns the total number of uncompressed bytes input so far.</p>
458 *
459 * @return the total (non-negative) number of uncompressed bytes input so far
460 * @since 1.5
461 */
462 public long getBytesRead() {
463 synchronized (zsRef) {
464 ensureOpen();
465 return getBytesRead(zsRef.address());
466 }
467 }
468
469 /**
470 * Returns the total number of compressed bytes output so far.
471 *
472 * <p>Since the number of bytes may be greater than
473 * Integer.MAX_VALUE, the {@link #getBytesWritten()} method is now
474 * the preferred means of obtaining this information.</p>
475 *
476 * @return the total number of compressed bytes output so far
477 */
478 public int getTotalOut() {
479 return (int) getBytesWritten();
480 }
481
482 /**
483 * Returns the total number of compressed bytes output so far.</p>
484 *
485 * @return the total (non-negative) number of compressed bytes output so far
486 * @since 1.5
487 */
488 public long getBytesWritten() {
489 synchronized (zsRef) {
490 ensureOpen();
491 return getBytesWritten(zsRef.address());
492 }
493 }
494
495 /**
496 * Resets deflater so that a new set of input data can be processed.
497 * Keeps current compression level and strategy settings.
498 */
499 public void reset() {
500 synchronized (zsRef) {
501 ensureOpen();
502 reset(zsRef.address());
503 finish = false;
504 finished = false;
505 off = len = 0;
506 }
507 }
508
509 /**
510 * Closes the compressor and discards any unprocessed input.
511 * This method should be called when the compressor is no longer
512 * being used, but will also be called automatically by the
513 * finalize() method. Once this method is called, the behavior
514 * of the Deflater object is undefined.
515 */
516 public void end() {
517 synchronized (zsRef) {
518 long addr = zsRef.address();
519 zsRef.clear();
520 if (addr != 0) {
521 end(addr);
522 buf = null;
523 }
524 }
525 }
526
527 /**
528 * Closes the compressor when garbage is collected.
529 */
530 protected void finalize() {
531 end();
532 }
533
534 private void ensureOpen() {
535 assert Thread.holdsLock(zsRef);
536 if (zsRef.address() == 0)
537 throw new NullPointerException("Deflater has been closed");
538 }
539
540 private static native void initIDs();
541 private native static long init(int level, int strategy, boolean nowrap);
542 private native static void setDictionary(long addr, byte[] b, int off, int len);
543 private native int deflateBytes(long addr, byte[] b, int off, int len,
544 int flush);
545 private native static int getAdler(long addr);
546 private native static long getBytesRead(long addr);
547 private native static long getBytesWritten(long addr);
548 private native static void reset(long addr);
549 private native static void end(long addr);
550}