📄 inflater.java
字号:
litlenTree = null; distTree = null; isLastBlock = false; adler.reset(); } /** * Sets the preset dictionary. This should only be called, if * needsDictionary() returns true and it should set the same * dictionary, that was used for deflating. The getAdler() * function returns the checksum of the dictionary needed. * @param buffer the dictionary. * @exception IllegalStateException if no dictionary is needed. * @exception IllegalArgumentException if the dictionary checksum is * wrong. */ public void setDictionary (byte[] buffer) { setDictionary(buffer, 0, buffer.length); } /** * Sets the preset dictionary. This should only be called, if * needsDictionary() returns true and it should set the same * dictionary, that was used for deflating. The getAdler() * function returns the checksum of the dictionary needed. * @param buffer the dictionary. * @param off the offset into buffer where the dictionary starts. * @param len the length of the dictionary. * @exception IllegalStateException if no dictionary is needed. * @exception IllegalArgumentException if the dictionary checksum is * wrong. * @exception IndexOutOfBoundsException if the off and/or len are wrong. */ public void setDictionary (byte[] buffer, int off, int len) { if (!needsDictionary()) throw new IllegalStateException(); adler.update(buffer, off, len); if ((int) adler.getValue() != readAdler) throw new IllegalArgumentException("Wrong adler checksum"); adler.reset(); outputWindow.copyDict(buffer, off, len); mode = DECODE_BLOCKS; } /** * Sets the input. This should only be called, if needsInput() * returns true. * @param buf the input. * @exception IllegalStateException if no input is needed. */ public void setInput (byte[] buf) { setInput (buf, 0, buf.length); } /** * Sets the input. This should only be called, if needsInput() * returns true. * @param buf the input. * @param off the offset into buffer where the input starts. * @param len the length of the input. * @exception IllegalStateException if no input is needed. * @exception IndexOutOfBoundsException if the off and/or len are wrong. */ public void setInput (byte[] buf, int off, int len) { input.setInput (buf, off, len); totalIn += len; } /** * Decodes the deflate header. * @return false if more input is needed. * @exception DataFormatException if header is invalid. */ private boolean decodeHeader () throws DataFormatException { int header = input.peekBits(16); if (header < 0) return false; input.dropBits(16); /* The header is written in "wrong" byte order */ header = ((header << 8) | (header >> 8)) & 0xffff; if (header % 31 != 0) throw new DataFormatException("Header checksum illegal"); if ((header & 0x0f00) != (Deflater.DEFLATED << 8)) throw new DataFormatException("Compression Method unknown"); /* Maximum size of the backwards window in bits. * We currently ignore this, but we could use it to make the * inflater window more space efficient. On the other hand the * full window (15 bits) is needed most times, anyway. int max_wbits = ((header & 0x7000) >> 12) + 8; */ if ((header & 0x0020) == 0) // Dictionary flag? { mode = DECODE_BLOCKS; } else { mode = DECODE_DICT; neededBits = 32; } return true; } /** * Decodes the dictionary checksum after the deflate header. * @return false if more input is needed. */ private boolean decodeDict () { while (neededBits > 0) { int dictByte = input.peekBits(8); if (dictByte < 0) return false; input.dropBits(8); readAdler = (readAdler << 8) | dictByte; neededBits -= 8; } return false; } /** * Decodes the huffman encoded symbols in the input stream. * @return false if more input is needed, true if output window is * full or the current block ends. * @exception DataFormatException if deflated stream is invalid. */ private boolean decodeHuffman () throws DataFormatException { int free = outputWindow.getFreeSpace(); while (free >= 258) { int symbol; switch (mode) { case DECODE_HUFFMAN: /* This is the inner loop so it is optimized a bit */ while (((symbol = litlenTree.getSymbol(input)) & ~0xff) == 0) { outputWindow.write(symbol); if (--free < 258) return true; } if (symbol < 257) { if (symbol < 0) return false; else { /* symbol == 256: end of block */ distTree = null; litlenTree = null; mode = DECODE_BLOCKS; return true; } } try { repLength = CPLENS[symbol - 257]; neededBits = CPLEXT[symbol - 257]; } catch (ArrayIndexOutOfBoundsException ex) { throw new DataFormatException("Illegal rep length code"); } /* fall through */ case DECODE_HUFFMAN_LENBITS: if (neededBits > 0) { mode = DECODE_HUFFMAN_LENBITS; int i = input.peekBits(neededBits); if (i < 0) return false; input.dropBits(neededBits); repLength += i; } mode = DECODE_HUFFMAN_DIST; /* fall through */ case DECODE_HUFFMAN_DIST: symbol = distTree.getSymbol(input); if (symbol < 0) return false; try { repDist = CPDIST[symbol]; neededBits = CPDEXT[symbol]; } catch (ArrayIndexOutOfBoundsException ex) { throw new DataFormatException("Illegal rep dist code"); } /* fall through */ case DECODE_HUFFMAN_DISTBITS: if (neededBits > 0) { mode = DECODE_HUFFMAN_DISTBITS; int i = input.peekBits(neededBits); if (i < 0) return false; input.dropBits(neededBits); repDist += i; } outputWindow.repeat(repLength, repDist); free -= repLength; mode = DECODE_HUFFMAN; break; default: throw new IllegalStateException(); } } return true; } /** * Decodes the adler checksum after the deflate stream. * @return false if more input is needed. * @exception DataFormatException if checksum doesn't match. */ private boolean decodeChksum () throws DataFormatException { while (neededBits > 0) { int chkByte = input.peekBits(8); if (chkByte < 0) return false; input.dropBits(8); readAdler = (readAdler << 8) | chkByte; neededBits -= 8; } if ((int) adler.getValue() != readAdler) throw new DataFormatException("Adler chksum doesn't match: " +Integer.toHexString((int)adler.getValue()) +" vs. "+Integer.toHexString(readAdler)); mode = FINISHED; return false; } /** * Decodes the deflated stream. * @return false if more input is needed, or if finished. * @exception DataFormatException if deflated stream is invalid. */ private boolean decode () throws DataFormatException { switch (mode) { case DECODE_HEADER: return decodeHeader(); case DECODE_DICT: return decodeDict(); case DECODE_CHKSUM: return decodeChksum(); case DECODE_BLOCKS: if (isLastBlock) { if (nowrap) { mode = FINISHED; return false; } else { input.skipToByteBoundary(); neededBits = 32; mode = DECODE_CHKSUM; return true; } } int type = input.peekBits(3); if (type < 0) return false; input.dropBits(3); if ((type & 1) != 0) isLastBlock = true; switch (type >> 1) { case DeflaterConstants.STORED_BLOCK: input.skipToByteBoundary(); mode = DECODE_STORED_LEN1; break; case DeflaterConstants.STATIC_TREES: litlenTree = InflaterHuffmanTree.defLitLenTree; distTree = InflaterHuffmanTree.defDistTree; mode = DECODE_HUFFMAN; break; case DeflaterConstants.DYN_TREES: dynHeader = new InflaterDynHeader(); mode = DECODE_DYN_HEADER; break; default: throw new DataFormatException("Unknown block type "+type); } return true; case DECODE_STORED_LEN1: { if ((uncomprLen = input.peekBits(16)) < 0) return false; input.dropBits(16); mode = DECODE_STORED_LEN2; } /* fall through */ case DECODE_STORED_LEN2: { int nlen = input.peekBits(16); if (nlen < 0) return false; input.dropBits(16); if (nlen != (uncomprLen ^ 0xffff)) throw new DataFormatException("broken uncompressed block"); mode = DECODE_STORED; } /* fall through */ case DECODE_STORED: { int more = outputWindow.copyStored(input, uncomprLen); uncomprLen -= more; if (uncomprLen == 0) { mode = DECODE_BLOCKS; return true; } return !input.needsInput(); } case DECODE_DYN_HEADER: if (!dynHeader.decode(input)) return false; litlenTree = dynHeader.buildLitLenTree(); distTree = dynHeader.buildDistTree(); mode = DECODE_HUFFMAN; /* fall through */ case DECODE_HUFFMAN: case DECODE_HUFFMAN_LENBITS: case DECODE_HUFFMAN_DIST: case DECODE_HUFFMAN_DISTBITS: return decodeHuffman(); case FINISHED: return false; default: throw new IllegalStateException(); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -