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 + -
显示快捷键?