127 public Inflater() { |
144 public Inflater() { |
128 this(false); |
145 this(false); |
129 } |
146 } |
130 |
147 |
131 /** |
148 /** |
132 * Sets input data for decompression. Should be called whenever |
149 * Sets input data for decompression. |
133 * needsInput() returns true indicating that more input data is |
150 * <p> |
134 * required. |
151 * One of the {@code setInput()} methods should be called whenever |
135 * @param b the input data bytes |
152 * {@code needsInput()} returns true indicating that more input data |
|
153 * is required. |
|
154 * |
|
155 * @param input the input data bytes |
136 * @param off the start offset of the input data |
156 * @param off the start offset of the input data |
137 * @param len the length of the input data |
157 * @param len the length of the input data |
138 * @see Inflater#needsInput |
158 * @see Inflater#needsInput |
139 */ |
159 */ |
140 public void setInput(byte[] b, int off, int len) { |
160 public void setInput(byte[] input, int off, int len) { |
141 if (b == null) { |
161 if (off < 0 || len < 0 || off > input.length - len) { |
142 throw new NullPointerException(); |
|
143 } |
|
144 if (off < 0 || len < 0 || off > b.length - len) { |
|
145 throw new ArrayIndexOutOfBoundsException(); |
162 throw new ArrayIndexOutOfBoundsException(); |
146 } |
163 } |
147 synchronized (zsRef) { |
164 synchronized (zsRef) { |
148 this.buf = b; |
165 this.input = null; |
149 this.off = off; |
166 this.inputArray = input; |
150 this.len = len; |
167 this.inputPos = off; |
151 } |
168 this.inputLim = off + len; |
152 } |
169 } |
153 |
170 } |
154 /** |
171 |
155 * Sets input data for decompression. Should be called whenever |
172 /** |
156 * needsInput() returns true indicating that more input data is |
173 * Sets input data for decompression. |
157 * required. |
174 * <p> |
158 * @param b the input data bytes |
175 * One of the {@code setInput()} methods should be called whenever |
|
176 * {@code needsInput()} returns true indicating that more input data |
|
177 * is required. |
|
178 * |
|
179 * @param input the input data bytes |
159 * @see Inflater#needsInput |
180 * @see Inflater#needsInput |
160 */ |
181 */ |
161 public void setInput(byte[] b) { |
182 public void setInput(byte[] input) { |
162 setInput(b, 0, b.length); |
183 setInput(input, 0, input.length); |
|
184 } |
|
185 |
|
186 /** |
|
187 * Sets input data for decompression. |
|
188 * <p> |
|
189 * One of the {@code setInput()} methods should be called whenever |
|
190 * {@code needsInput()} returns true indicating that more input data |
|
191 * is required. |
|
192 * <p> |
|
193 * The given buffer's position will be advanced as inflate |
|
194 * operations are performed, up to the buffer's limit. |
|
195 * The input buffer may be modified (refilled) between inflate |
|
196 * operations; doing so is equivalent to creating a new buffer |
|
197 * and setting it with this method. |
|
198 * <p> |
|
199 * Modifying the input buffer's contents, position, or limit |
|
200 * concurrently with an inflate operation will result in |
|
201 * undefined behavior, which may include incorrect operation |
|
202 * results or operation failure. |
|
203 * |
|
204 * @param input the input data bytes |
|
205 * @see Inflater#needsInput |
|
206 * @since 11 |
|
207 */ |
|
208 public void setInput(ByteBuffer input) { |
|
209 Objects.requireNonNull(input); |
|
210 synchronized (zsRef) { |
|
211 this.input = input; |
|
212 this.inputArray = null; |
|
213 } |
163 } |
214 } |
164 |
215 |
165 /** |
216 /** |
166 * Sets the preset dictionary to the given array of bytes. Should be |
217 * Sets the preset dictionary to the given array of bytes. Should be |
167 * called when inflate() returns 0 and needsDictionary() returns true |
218 * called when inflate() returns 0 and needsDictionary() returns true |
168 * indicating that a preset dictionary is required. The method getAdler() |
219 * indicating that a preset dictionary is required. The method getAdler() |
169 * can be used to get the Adler-32 value of the dictionary needed. |
220 * can be used to get the Adler-32 value of the dictionary needed. |
170 * @param b the dictionary data bytes |
221 * @param dictionary the dictionary data bytes |
171 * @param off the start offset of the data |
222 * @param off the start offset of the data |
172 * @param len the length of the data |
223 * @param len the length of the data |
173 * @see Inflater#needsDictionary |
224 * @see Inflater#needsDictionary |
174 * @see Inflater#getAdler |
225 * @see Inflater#getAdler |
175 */ |
226 */ |
176 public void setDictionary(byte[] b, int off, int len) { |
227 public void setDictionary(byte[] dictionary, int off, int len) { |
177 if (b == null) { |
228 if (off < 0 || len < 0 || off > dictionary.length - len) { |
178 throw new NullPointerException(); |
|
179 } |
|
180 if (off < 0 || len < 0 || off > b.length - len) { |
|
181 throw new ArrayIndexOutOfBoundsException(); |
229 throw new ArrayIndexOutOfBoundsException(); |
182 } |
230 } |
183 synchronized (zsRef) { |
231 synchronized (zsRef) { |
184 ensureOpen(); |
232 ensureOpen(); |
185 setDictionary(zsRef.address(), b, off, len); |
233 setDictionary(zsRef.address(), dictionary, off, len); |
186 needDict = false; |
234 needDict = false; |
187 } |
235 } |
188 } |
236 } |
189 |
237 |
190 /** |
238 /** |
191 * Sets the preset dictionary to the given array of bytes. Should be |
239 * Sets the preset dictionary to the given array of bytes. Should be |
192 * called when inflate() returns 0 and needsDictionary() returns true |
240 * called when inflate() returns 0 and needsDictionary() returns true |
193 * indicating that a preset dictionary is required. The method getAdler() |
241 * indicating that a preset dictionary is required. The method getAdler() |
194 * can be used to get the Adler-32 value of the dictionary needed. |
242 * can be used to get the Adler-32 value of the dictionary needed. |
195 * @param b the dictionary data bytes |
243 * @param dictionary the dictionary data bytes |
196 * @see Inflater#needsDictionary |
244 * @see Inflater#needsDictionary |
197 * @see Inflater#getAdler |
245 * @see Inflater#getAdler |
198 */ |
246 */ |
199 public void setDictionary(byte[] b) { |
247 public void setDictionary(byte[] dictionary) { |
200 setDictionary(b, 0, b.length); |
248 setDictionary(dictionary, 0, dictionary.length); |
|
249 } |
|
250 |
|
251 /** |
|
252 * Sets the preset dictionary to the bytes in the given buffer. Should be |
|
253 * called when inflate() returns 0 and needsDictionary() returns true |
|
254 * indicating that a preset dictionary is required. The method getAdler() |
|
255 * can be used to get the Adler-32 value of the dictionary needed. |
|
256 * <p> |
|
257 * The bytes in given byte buffer will be fully consumed by this method. On |
|
258 * return, its position will equal its limit. |
|
259 * |
|
260 * @param dictionary the dictionary data bytes |
|
261 * @see Inflater#needsDictionary |
|
262 * @see Inflater#getAdler |
|
263 * @since 11 |
|
264 */ |
|
265 public void setDictionary(ByteBuffer dictionary) { |
|
266 synchronized (zsRef) { |
|
267 int position = dictionary.position(); |
|
268 int remaining = Math.max(dictionary.limit() - position, 0); |
|
269 ensureOpen(); |
|
270 if (dictionary.isDirect()) { |
|
271 long address = ((DirectBuffer) dictionary).address(); |
|
272 try { |
|
273 setDictionaryBuffer(zsRef.address(), address + position, remaining); |
|
274 } finally { |
|
275 Reference.reachabilityFence(dictionary); |
|
276 } |
|
277 } else { |
|
278 byte[] array = ZipUtils.getBufferArray(dictionary); |
|
279 int offset = ZipUtils.getBufferOffset(dictionary); |
|
280 setDictionary(zsRef.address(), array, offset + position, remaining); |
|
281 } |
|
282 dictionary.position(position + remaining); |
|
283 needDict = false; |
|
284 } |
201 } |
285 } |
202 |
286 |
203 /** |
287 /** |
204 * Returns the total number of bytes remaining in the input buffer. |
288 * Returns the total number of bytes remaining in the input buffer. |
205 * This can be used to find out what bytes still remain in the input |
289 * This can be used to find out what bytes still remain in the input |
206 * buffer after decompression has finished. |
290 * buffer after decompression has finished. |
207 * @return the total number of bytes remaining in the input buffer |
291 * @return the total number of bytes remaining in the input buffer |
208 */ |
292 */ |
209 public int getRemaining() { |
293 public int getRemaining() { |
210 synchronized (zsRef) { |
294 synchronized (zsRef) { |
211 return len; |
295 ByteBuffer input = this.input; |
|
296 return input == null ? inputLim - inputPos : input.remaining(); |
212 } |
297 } |
213 } |
298 } |
214 |
299 |
215 /** |
300 /** |
216 * Returns true if no data remains in the input buffer. This can |
301 * Returns true if no data remains in the input buffer. This can |
217 * be used to determine if #setInput should be called in order |
302 * be used to determine if one of the {@code setInput()} methods should be |
218 * to provide more input. |
303 * called in order to provide more input. |
|
304 * |
219 * @return true if no data remains in the input buffer |
305 * @return true if no data remains in the input buffer |
220 */ |
306 */ |
221 public boolean needsInput() { |
307 public boolean needsInput() { |
222 synchronized (zsRef) { |
308 synchronized (zsRef) { |
223 return len <= 0; |
309 ByteBuffer input = this.input; |
|
310 return input == null ? inputLim == inputPos : ! input.hasRemaining(); |
224 } |
311 } |
225 } |
312 } |
226 |
313 |
227 /** |
314 /** |
228 * Returns true if a preset dictionary is needed for decompression. |
315 * Returns true if a preset dictionary is needed for decompression. |
252 * of bytes uncompressed. A return value of 0 indicates that |
339 * of bytes uncompressed. A return value of 0 indicates that |
253 * needsInput() or needsDictionary() should be called in order to |
340 * needsInput() or needsDictionary() should be called in order to |
254 * determine if more input data or a preset dictionary is required. |
341 * determine if more input data or a preset dictionary is required. |
255 * In the latter case, getAdler() can be used to get the Adler-32 |
342 * In the latter case, getAdler() can be used to get the Adler-32 |
256 * value of the dictionary required. |
343 * value of the dictionary required. |
257 * @param b the buffer for the uncompressed data |
344 * <p> |
|
345 * If the {@link #setInput(ByteBuffer)} method was called to provide a buffer |
|
346 * for input, the input buffer's position will be advanced by the number of bytes |
|
347 * consumed by this operation, even in the event that a {@link DataFormatException} |
|
348 * is thrown. |
|
349 * <p> |
|
350 * The {@linkplain #getRemaining() remaining byte count} will be reduced by |
|
351 * the number of consumed input bytes. If the {@link #setInput(ByteBuffer)} |
|
352 * method was called to provide a buffer for input, the input buffer's position |
|
353 * will be advanced the number of consumed bytes. |
|
354 * <p> |
|
355 * These byte totals, as well as |
|
356 * the {@linkplain #getBytesRead() total bytes read} |
|
357 * and the {@linkplain #getBytesWritten() total bytes written} |
|
358 * values, will be updated even in the event that a {@link DataFormatException} |
|
359 * is thrown to reflect the amount of data consumed and produced before the |
|
360 * exception occurred. |
|
361 * |
|
362 * @param output the buffer for the uncompressed data |
258 * @param off the start offset of the data |
363 * @param off the start offset of the data |
259 * @param len the maximum number of uncompressed bytes |
364 * @param len the maximum number of uncompressed bytes |
260 * @return the actual number of uncompressed bytes |
365 * @return the actual number of uncompressed bytes |
261 * @exception DataFormatException if the compressed data format is invalid |
366 * @throws DataFormatException if the compressed data format is invalid |
262 * @see Inflater#needsInput |
367 * @see Inflater#needsInput |
263 * @see Inflater#needsDictionary |
368 * @see Inflater#needsDictionary |
264 */ |
369 */ |
265 public int inflate(byte[] b, int off, int len) |
370 public int inflate(byte[] output, int off, int len) |
266 throws DataFormatException |
371 throws DataFormatException |
267 { |
372 { |
268 if (b == null) { |
373 if (off < 0 || len < 0 || off > output.length - len) { |
269 throw new NullPointerException(); |
|
270 } |
|
271 if (off < 0 || len < 0 || off > b.length - len) { |
|
272 throw new ArrayIndexOutOfBoundsException(); |
374 throw new ArrayIndexOutOfBoundsException(); |
273 } |
375 } |
274 synchronized (zsRef) { |
376 synchronized (zsRef) { |
275 ensureOpen(); |
377 ensureOpen(); |
276 int thisLen = this.len; |
378 ByteBuffer input = this.input; |
277 int n = inflateBytes(zsRef.address(), b, off, len); |
379 long result; |
278 bytesWritten += n; |
380 int inputPos; |
279 bytesRead += (thisLen - this.len); |
381 try { |
280 return n; |
382 if (input == null) { |
|
383 inputPos = this.inputPos; |
|
384 try { |
|
385 result = inflateBytesBytes(zsRef.address(), |
|
386 inputArray, inputPos, inputLim - inputPos, |
|
387 output, off, len); |
|
388 } catch (DataFormatException e) { |
|
389 this.inputPos = inputPos + inputConsumed; |
|
390 throw e; |
|
391 } |
|
392 } else { |
|
393 inputPos = input.position(); |
|
394 try { |
|
395 int inputRem = Math.max(input.limit() - inputPos, 0); |
|
396 if (input.isDirect()) { |
|
397 try { |
|
398 long inputAddress = ((DirectBuffer) input).address(); |
|
399 result = inflateBufferBytes(zsRef.address(), |
|
400 inputAddress + inputPos, inputRem, |
|
401 output, off, len); |
|
402 } finally { |
|
403 Reference.reachabilityFence(input); |
|
404 } |
|
405 } else { |
|
406 byte[] inputArray = ZipUtils.getBufferArray(input); |
|
407 int inputOffset = ZipUtils.getBufferOffset(input); |
|
408 result = inflateBytesBytes(zsRef.address(), |
|
409 inputArray, inputOffset + inputPos, inputRem, |
|
410 output, off, len); |
|
411 } |
|
412 } catch (DataFormatException e) { |
|
413 input.position(inputPos + inputConsumed); |
|
414 throw e; |
|
415 } |
|
416 } |
|
417 } catch (DataFormatException e) { |
|
418 bytesRead += inputConsumed; |
|
419 inputConsumed = 0; |
|
420 int written = outputConsumed; |
|
421 bytesWritten += written; |
|
422 outputConsumed = 0; |
|
423 throw e; |
|
424 } |
|
425 int read = (int) (result & 0x7fff_ffffL); |
|
426 int written = (int) (result >>> 31 & 0x7fff_ffffL); |
|
427 if ((result >>> 62 & 1) != 0) { |
|
428 finished = true; |
|
429 } |
|
430 if ((result >>> 63 & 1) != 0) { |
|
431 needDict = true; |
|
432 } |
|
433 if (input != null) { |
|
434 input.position(inputPos + read); |
|
435 } else { |
|
436 this.inputPos = inputPos + read; |
|
437 } |
|
438 bytesWritten += written; |
|
439 bytesRead += read; |
|
440 return written; |
281 } |
441 } |
282 } |
442 } |
283 |
443 |
284 /** |
444 /** |
285 * Uncompresses bytes into specified buffer. Returns actual number |
445 * Uncompresses bytes into specified buffer. Returns actual number |
286 * of bytes uncompressed. A return value of 0 indicates that |
446 * of bytes uncompressed. A return value of 0 indicates that |
287 * needsInput() or needsDictionary() should be called in order to |
447 * needsInput() or needsDictionary() should be called in order to |
288 * determine if more input data or a preset dictionary is required. |
448 * determine if more input data or a preset dictionary is required. |
289 * In the latter case, getAdler() can be used to get the Adler-32 |
449 * In the latter case, getAdler() can be used to get the Adler-32 |
290 * value of the dictionary required. |
450 * value of the dictionary required. |
291 * @param b the buffer for the uncompressed data |
451 * <p> |
|
452 * The {@linkplain #getRemaining() remaining byte count} will be reduced by |
|
453 * the number of consumed input bytes. If the {@link #setInput(ByteBuffer)} |
|
454 * method was called to provide a buffer for input, the input buffer's position |
|
455 * will be advanced the number of consumed bytes. |
|
456 * <p> |
|
457 * These byte totals, as well as |
|
458 * the {@linkplain #getBytesRead() total bytes read} |
|
459 * and the {@linkplain #getBytesWritten() total bytes written} |
|
460 * values, will be updated even in the event that a {@link DataFormatException} |
|
461 * is thrown to reflect the amount of data consumed and produced before the |
|
462 * exception occurred. |
|
463 * |
|
464 * @param output the buffer for the uncompressed data |
292 * @return the actual number of uncompressed bytes |
465 * @return the actual number of uncompressed bytes |
293 * @exception DataFormatException if the compressed data format is invalid |
466 * @throws DataFormatException if the compressed data format is invalid |
294 * @see Inflater#needsInput |
467 * @see Inflater#needsInput |
295 * @see Inflater#needsDictionary |
468 * @see Inflater#needsDictionary |
296 */ |
469 */ |
297 public int inflate(byte[] b) throws DataFormatException { |
470 public int inflate(byte[] output) throws DataFormatException { |
298 return inflate(b, 0, b.length); |
471 return inflate(output, 0, output.length); |
|
472 } |
|
473 |
|
474 /** |
|
475 * Uncompresses bytes into specified buffer. Returns actual number |
|
476 * of bytes uncompressed. A return value of 0 indicates that |
|
477 * needsInput() or needsDictionary() should be called in order to |
|
478 * determine if more input data or a preset dictionary is required. |
|
479 * In the latter case, getAdler() can be used to get the Adler-32 |
|
480 * value of the dictionary required. |
|
481 * <p> |
|
482 * On success, the position of the given {@code output} byte buffer will be |
|
483 * advanced by as many bytes as were produced by the operation, which is equal |
|
484 * to the number returned by this method. Note that the position of the |
|
485 * {@code output} buffer will be advanced even in the event that a |
|
486 * {@link DataFormatException} is thrown. |
|
487 * <p> |
|
488 * The {@linkplain #getRemaining() remaining byte count} will be reduced by |
|
489 * the number of consumed input bytes. If the {@link #setInput(ByteBuffer)} |
|
490 * method was called to provide a buffer for input, the input buffer's position |
|
491 * will be advanced the number of consumed bytes. |
|
492 * <p> |
|
493 * These byte totals, as well as |
|
494 * the {@linkplain #getBytesRead() total bytes read} |
|
495 * and the {@linkplain #getBytesWritten() total bytes written} |
|
496 * values, will be updated even in the event that a {@link DataFormatException} |
|
497 * is thrown to reflect the amount of data consumed and produced before the |
|
498 * exception occurred. |
|
499 * |
|
500 * @param output the buffer for the uncompressed data |
|
501 * @return the actual number of uncompressed bytes |
|
502 * @throws DataFormatException if the compressed data format is invalid |
|
503 * @throws ReadOnlyBufferException if the given output buffer is read-only |
|
504 * @see Inflater#needsInput |
|
505 * @see Inflater#needsDictionary |
|
506 * @since 11 |
|
507 */ |
|
508 public int inflate(ByteBuffer output) throws DataFormatException { |
|
509 if (output.isReadOnly()) { |
|
510 throw new ReadOnlyBufferException(); |
|
511 } |
|
512 synchronized (zsRef) { |
|
513 ensureOpen(); |
|
514 ByteBuffer input = this.input; |
|
515 long result; |
|
516 int inputPos; |
|
517 int outputPos = output.position(); |
|
518 int outputRem = Math.max(output.limit() - outputPos, 0); |
|
519 try { |
|
520 if (input == null) { |
|
521 inputPos = this.inputPos; |
|
522 try { |
|
523 if (output.isDirect()) { |
|
524 long outputAddress = ((DirectBuffer) output).address(); |
|
525 try { |
|
526 result = inflateBytesBuffer(zsRef.address(), |
|
527 inputArray, inputPos, inputLim - inputPos, |
|
528 outputAddress + outputPos, outputRem); |
|
529 } finally { |
|
530 Reference.reachabilityFence(output); |
|
531 } |
|
532 } else { |
|
533 byte[] outputArray = ZipUtils.getBufferArray(output); |
|
534 int outputOffset = ZipUtils.getBufferOffset(output); |
|
535 result = inflateBytesBytes(zsRef.address(), |
|
536 inputArray, inputPos, inputLim - inputPos, |
|
537 outputArray, outputOffset + outputPos, outputRem); |
|
538 } |
|
539 } catch (DataFormatException e) { |
|
540 this.inputPos = inputPos + inputConsumed; |
|
541 throw e; |
|
542 } |
|
543 } else { |
|
544 inputPos = input.position(); |
|
545 int inputRem = Math.max(input.limit() - inputPos, 0); |
|
546 try { |
|
547 if (input.isDirect()) { |
|
548 long inputAddress = ((DirectBuffer) input).address(); |
|
549 try { |
|
550 if (output.isDirect()) { |
|
551 long outputAddress = ((DirectBuffer) output).address(); |
|
552 try { |
|
553 result = inflateBufferBuffer(zsRef.address(), |
|
554 inputAddress + inputPos, inputRem, |
|
555 outputAddress + outputPos, outputRem); |
|
556 } finally { |
|
557 Reference.reachabilityFence(output); |
|
558 } |
|
559 } else { |
|
560 byte[] outputArray = ZipUtils.getBufferArray(output); |
|
561 int outputOffset = ZipUtils.getBufferOffset(output); |
|
562 result = inflateBufferBytes(zsRef.address(), |
|
563 inputAddress + inputPos, inputRem, |
|
564 outputArray, outputOffset + outputPos, outputRem); |
|
565 } |
|
566 } finally { |
|
567 Reference.reachabilityFence(input); |
|
568 } |
|
569 } else { |
|
570 byte[] inputArray = ZipUtils.getBufferArray(input); |
|
571 int inputOffset = ZipUtils.getBufferOffset(input); |
|
572 if (output.isDirect()) { |
|
573 long outputAddress = ((DirectBuffer) output).address(); |
|
574 try { |
|
575 result = inflateBytesBuffer(zsRef.address(), |
|
576 inputArray, inputOffset + inputPos, inputRem, |
|
577 outputAddress + outputPos, outputRem); |
|
578 } finally { |
|
579 Reference.reachabilityFence(output); |
|
580 } |
|
581 } else { |
|
582 byte[] outputArray = ZipUtils.getBufferArray(output); |
|
583 int outputOffset = ZipUtils.getBufferOffset(output); |
|
584 result = inflateBytesBytes(zsRef.address(), |
|
585 inputArray, inputOffset + inputPos, inputRem, |
|
586 outputArray, outputOffset + outputPos, outputRem); |
|
587 } |
|
588 } |
|
589 } catch (DataFormatException e) { |
|
590 input.position(inputPos + inputConsumed); |
|
591 throw e; |
|
592 } |
|
593 } |
|
594 } catch (DataFormatException e) { |
|
595 bytesRead += inputConsumed; |
|
596 inputConsumed = 0; |
|
597 int written = outputConsumed; |
|
598 output.position(outputPos + written); |
|
599 bytesWritten += written; |
|
600 outputConsumed = 0; |
|
601 throw e; |
|
602 } |
|
603 int read = (int) (result & 0x7fff_ffffL); |
|
604 int written = (int) (result >>> 31 & 0x7fff_ffffL); |
|
605 if ((result >>> 62 & 1) != 0) { |
|
606 finished = true; |
|
607 } |
|
608 if ((result >>> 63 & 1) != 0) { |
|
609 needDict = true; |
|
610 } |
|
611 if (input != null) { |
|
612 input.position(inputPos + read); |
|
613 } else { |
|
614 this.inputPos = inputPos + read; |
|
615 } |
|
616 // Note: this method call also serves to keep the byteBuffer ref alive |
|
617 output.position(outputPos + written); |
|
618 bytesWritten += written; |
|
619 bytesRead += read; |
|
620 return written; |
|
621 } |
299 } |
622 } |
300 |
623 |
301 /** |
624 /** |
302 * Returns the ADLER-32 value of the uncompressed data. |
625 * Returns the ADLER-32 value of the uncompressed data. |
303 * @return the ADLER-32 value of the uncompressed data |
626 * @return the ADLER-32 value of the uncompressed data |