/** * Deflates the current input block to the given array. It returns the number of bytes compressed, * or 0 if either needsInput() or finished() returns true or length is zero. * * @param output the buffer where to write the compressed data. * @param offset the offset into the output array. * @param length the maximum number of bytes that may be written. * @exception IllegalStateException if end() was called. * @exception IndexOutOfBoundsException if offset and/or length don't match the array length. */ public int deflate(byte[] output, int offset, int length) { int origLength = length; if (state == CLOSED_STATE) throw new IllegalStateException("Deflater closed"); if (state < BUSY_STATE) { /* output header */ int header = (DEFLATED + ((DeflaterConstants.MAX_WBITS - 8) << 4)) << 8; int level_flags = (level - 1) >> 1; if (level_flags < 0 || level_flags > 3) level_flags = 3; header |= level_flags << 6; if ((state & IS_SETDICT) != 0) /* Dictionary was set */ header |= DeflaterConstants.PRESET_DICT; header += 31 - (header % 31); pending.writeShortMSB(header); if ((state & IS_SETDICT) != 0) { int chksum = engine.getAdler(); engine.resetAdler(); pending.writeShortMSB(chksum >> 16); pending.writeShortMSB(chksum & 0xffff); } state = BUSY_STATE | (state & (IS_FLUSHING | IS_FINISHING)); } for (; ; ) { int count = pending.flush(output, offset, length); offset += count; totalOut += count; length -= count; if (length == 0 || state == FINISHED_STATE) break; if (!engine.deflate((state & IS_FLUSHING) != 0, (state & IS_FINISHING) != 0)) { if (state == BUSY_STATE) /* We need more input now */ return origLength - length; else if (state == FLUSHING_STATE) { if (level != NO_COMPRESSION) { /* We have to supply some lookahead. 8 bit lookahead * are needed by the zlib inflater, and we must fill * the next byte, so that all bits are flushed. */ int neededbits = 8 + ((-pending.getBitCount()) & 7); while (neededbits > 0) { /* write a static tree block consisting solely of * an EOF: */ pending.writeBits(2, 10); neededbits -= 10; } } state = BUSY_STATE; } else if (state == FINISHING_STATE) { pending.alignToByte(); /* We have completed the stream */ if (!noHeader) { int adler = engine.getAdler(); pending.writeShortMSB(adler >> 16); pending.writeShortMSB(adler & 0xffff); } state = FINISHED_STATE; } } } return origLength - length; }