midpinflate.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 685 行 · 第 1/2 页
C
685 行
/* * * * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. */#include <string.h>#include <jar.h>#include <midpInflateint.h>#include <midpInflatetables.h>static int decodeDynamicHuffmanTables(InflaterState *state, void** lcodesPtr, void** dcodesPtr);static int makeCodeTable(InflaterState *state, unsigned char *codelen, unsigned numElems, unsigned maxQuickBits, void** result);static int inflateHuffman(InflaterState *state, int fixedHuffman);static int inflateStored(InflaterState *state);#define INFLATER_EXTRA_BYTES 4/** * Inflates the data in a file. * <p> * NOTE: * The caller of this method must insure that this function can safely * up to INFLATER_EXTRA_BYTES beyond compData + compLen without causing * any problems. * The inflater algorithm occasionally reads one more byte than it needs * to. But it double checks that it doesn't actually care what's in that * extra byte.</p> * * @param fileObj File object for reading the compressed data with the * current file position set to the beginning of the data * @param heapManObj Heap manager object for temp data * @param method Compression method * @param compLen Length of the compressed data * @param decompBuffer where to store the uncompressed data * @param decompLen Expected length of the uncompressed data * @param bufferIsAHandle non-zero if decompBuffer is mem handle that must be * given to heapObj.addrFromHandle before using * * @return TRUE if the data was encoded in a supported <method> and the * size of the decoded data is exactly the same as <decompLen> * FALSE if an error occurs */int inflateData(FileObj* fileObj, HeapManObj* heapManObj, int compLen, unsigned char* decompBuffer, int decompLen, int bufferIsAHandle) { /* The macros LOAD_IN, LOAD_OUT,etc. use a variable called "state" */ InflaterState stateStruct; InflaterState* state = &stateStruct; int result = 0; state->outBuffer = decompBuffer; state->outOffset = 0; state->outLength = decompLen; state->outBufferIsAHandle = bufferIsAHandle; state->fileState = fileObj->state; state->getBytes = fileObj->read; state->heapState = heapManObj->state; state->mallocBytes = heapManObj->alloc; state->freeBytes = heapManObj->free; state->addrFromHandle = heapManObj->addrFromHandle; state->inData = 0; state->inDataSize = 0; state->inRemaining = compLen + INFLATER_EXTRA_BYTES; state->inflateBufferIndex = 0; state->inflateBufferCount = 0; for (; ; ) { int type; DECLARE_IN_VARIABLES LOAD_IN; NEEDBITS(3); type = NEXTBITS(3); DUMPBITS(3); STORE_IN; switch (type >> 1) { default: case BTYPE_INVALID: result = INFLATE_INVALID_BTYPE; break; case BTYPE_NO_COMPRESSION: result = inflateStored(state); break; case BTYPE_FIXED_HUFFMAN: result = inflateHuffman(state, 1); break; case BTYPE_DYNA_HUFFMAN: result = inflateHuffman(state, 0); break; } if (result != 0) { break; } if (type & 1) { if (state->inRemaining + (state->inDataSize >> 3) != INFLATER_EXTRA_BYTES) { result = INFLATE_INPUT_BIT_ERROR; break; } if (state->outOffset != state->outLength) { result = INFLATE_OUTPUT_BIT_ERROR; break; } /* Success */ break; } } return result;}static int inflateStored(InflaterState *state) { DECLARE_IN_VARIABLES DECLARE_OUT_VARIABLES long len, nlen; LOAD_IN; LOAD_OUT; DUMPBITS(inDataSize & 7); /* move to byte boundary */ NEEDBITS(32) len = NEXTBITS(16); DUMPBITS(16); nlen = NEXTBITS(16); DUMPBITS(16); ASSERT(inDataSize == 0); if (len + nlen != 0xFFFF) { return INFLATE_BAD_LENGTH_FIELD; } else if (inRemaining < len) { return INFLATE_INPUT_OVERFLOW; } else if (outOffset + len > outLength) { return INFLATE_OUTPUT_OVERFLOW; } else { int count; if (state->outBufferIsAHandle) { /* This is to support heaps with memory compaction. */ outBuffer = state->addrFromHandle(state->heapState, state->outBuffer); } while (len > 0) { if (state->inflateBufferCount > 0) { /* we have data buffered, copy it first */ memcpy(&outBuffer[outOffset], &(state->inflateBuffer[state->inflateBufferIndex]), (count = (state->inflateBufferCount <= len ? state->inflateBufferCount : len))); len -= count; (state->inflateBufferCount) -= count; (state->inflateBufferIndex) += count; outOffset += count; inRemaining -= count; } if (len > 0) { /* need more, refill the buffer */ outBuffer[outOffset++] = (unsigned char)(NEXTBYTE); len--; inRemaining--; } } } STORE_IN; STORE_OUT; return 0;}static int inflateHuffman(InflaterState *state, int fixedHuffman) { int error = 0; DECLARE_IN_VARIABLES DECLARE_OUT_VARIABLES unsigned int quickDataSize = 0; unsigned int quickDistanceSize = 0; unsigned int code; unsigned int litxlen; void* lcodesMemHandle = NULL; void* dcodesMemHandle = NULL; HuffmanCodeTable* lcodes = NULL; HuffmanCodeTable* dcodes = NULL; if (!fixedHuffman) { error = decodeDynamicHuffmanTables(state, &lcodesMemHandle, &dcodesMemHandle); if (error != 0) { return error; } /* This is to support heaps with memory compaction. */ lcodes = state->addrFromHandle(state->heapState, lcodesMemHandle); dcodes = state->addrFromHandle(state->heapState, dcodesMemHandle); quickDataSize = lcodes->h.quickBits; quickDistanceSize = dcodes->h.quickBits; } LOAD_IN; LOAD_OUT; if (state->outBufferIsAHandle) { /* This is to support heaps with memory compaction. */ outBuffer = state->addrFromHandle(state->heapState, state->outBuffer); } for (; ; ) { if (inRemaining < 0) { error = INFLATE_EARLY_END_OF_INPUT; break; } NEEDBITS(MAX_BITS + MAX_ZIP_EXTRA_LENGTH_BITS); if (fixedHuffman) { /* literal (hex) * 0x100 - 0x117 7 0.0000.00 - 0.0101.11 * 0 - 8f 8 0.0110.000 - 1.0111.111 * 118 - 11f 8 1.1000.000 - 1.1000.111 * 90 - ff 9 1.1001.0000 - 1.1111.1111 */ /* Get 9 bits, and reverse them. */ code = NEXTBITS(9); code = REVERSE_9BITS(code); if (code < 0x060) { /* A 7-bit code */ DUMPBITS(7); litxlen = 0x100 + (code >> 2); } else if (code < 0x190) { DUMPBITS(8); litxlen = (code >> 1) + ((code < 0x180) ? (0x000 - 0x030) : (0x118 - 0x0c0)); } else { DUMPBITS(9); litxlen = 0x90 + code - 0x190; } } else { GET_HUFFMAN_ENTRY(lcodes, quickDataSize, litxlen); } if (litxlen <= 255) { if (outOffset < outLength) { outBuffer[outOffset] = litxlen; outOffset++; } else { /* success */ break; } } else if (litxlen == 256) { /* end of block */ /* success */ break; } else if (litxlen > 285) { error = INFLATE_INVALID_LITERAL_OR_LENGTH; break; } else { unsigned int n = litxlen - LITXLEN_BASE; unsigned int length = ll_length_base[n]; unsigned int moreBits = ll_extra_bits[n]; unsigned int d0, distance; /* The NEEDBITS(..) above took care of this */ length += NEXTBITS(moreBits); DUMPBITS(moreBits); NEEDBITS(MAX_BITS); if (fixedHuffman) { d0 = REVERSE_5BITS(NEXTBITS(5)); DUMPBITS(5); } else { GET_HUFFMAN_ENTRY(dcodes, quickDistanceSize, d0); } if (d0 > MAX_ZIP_DISTANCE_CODE) { error = INFLATE_BAD_DISTANCE_CODE; break; } NEEDBITS(MAX_ZIP_EXTRA_DISTANCE_BITS) distance = dist_base[d0]; moreBits = dist_extra_bits[d0]; distance += NEXTBITS(moreBits); DUMPBITS(moreBits); if (outOffset < distance) { error = INFLATE_COPY_UNDERFLOW; break; } else if (outOffset + length > outLength) { error = INFLATE_OUTPUT_OVERFLOW; break; } else { unsigned long prev = outOffset - distance; unsigned long end = outOffset + length; unsigned char value; while (outOffset != end) { value = outBuffer[prev];
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?