All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.xbib.io.compress.zlib.Inflate Maven / Gradle / Ivy

The newest version!

package org.xbib.io.compress.zlib;

public final class Inflate {

    // preset dictionary flag in zlib header
    private static final int PRESET_DICT = 0x20;
    private static final int Z_FINISH = 4;
    private static final int Z_DEFLATED = 8;
    private static final int Z_OK = 0;
    private static final int Z_STREAM_END = 1;
    private static final int Z_NEED_DICT = 2;
    private static final int Z_STREAM_ERROR = -2;
    private static final int Z_DATA_ERROR = -3;
    private static final int Z_BUF_ERROR = -5;
    private static final int METHOD = 0;   // waiting for method byte
    private static final int FLAG = 1;     // waiting for flag byte
    private static final int DICT4 = 2;    // four dictionary check bytes to go
    private static final int DICT3 = 3;    // three dictionary check bytes to go
    private static final int DICT2 = 4;    // two dictionary check bytes to go
    private static final int DICT1 = 5;    // one dictionary check byte to go
    private static final int DICT0 = 6;    // waiting for inflateSetDictionary
    private static final int BLOCKS = 7;   // decompressing blocks
    private static final int CHECK4 = 8;   // four check bytes to go
    private static final int CHECK3 = 9;   // three check bytes to go
    private static final int CHECK2 = 10;  // two check bytes to go
    private static final int CHECK1 = 11;  // one check byte to go
    private static final int DONE = 12;    // finished check, done
    private static final int BAD = 13;     // got an error--stay here
    private int mode;                            // current inflate mode
    // mode dependent information
    private int method;        // if FLAGS, method byte
    // if CHECK, check values to compare
    private long[] was = new long[1]; // computed check value
    private long need;               // stream check value
    // if BAD, inflateSync's marker bytes count
    private int marker;
    // mode independent information
    private int nowrap;          // flag for no wrapper
    private int wbits;            // log2(window size)  (8..15, defaults to 15)
    private InfBlocks blocks;     // current inflate_blocks state

    protected int inflateReset(ZStream z) {
        if (z == null || z.istate == null) {
            return Z_STREAM_ERROR;
        }

        z.totalin = z.totalout = 0;
        z.msg = null;
        z.istate.mode = z.istate.nowrap != 0 ? BLOCKS : METHOD;
        z.istate.blocks.reset(z, null);
        return Z_OK;
    }

    protected int inflateEnd(ZStream z) {
        if (blocks != null) {
            blocks.free(z);
        }
        blocks = null;
        //    ZFREE(z, z->state);
        return Z_OK;
    }

    protected int inflateInit(ZStream z, int w) {
        z.msg = null;
        blocks = null;

        // handle undocumented nowrap option (no zlib header or check)
        nowrap = 0;
        if (w < 0) {
            w = -w;
            nowrap = 1;
        }

        // set window size
        if (w < 8 || w > 15) {
            inflateEnd(z);
            return Z_STREAM_ERROR;
        }
        wbits = w;

        z.istate.blocks = new InfBlocks(z,
                z.istate.nowrap != 0 ? null : this,
                1 << w);

        // reset state
        inflateReset(z);
        return Z_OK;
    }

    protected int inflate(ZStream z, int f) {
        int r;
        int b;

        if (z == null || z.istate == null || z.nextin == null) {
            return Z_STREAM_ERROR;
        }
        f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
        r = Z_BUF_ERROR;
        while (true) {
            switch (z.istate.mode) {
                case METHOD:
                    if (z.availin == 0) {
                        return r;
                    }
                    r = f;
                    z.availin--;
                    z.totalin++;
                    if (((z.istate.method = z.nextin[z.nextinindex++]) & 0xf) != Z_DEFLATED) {
                        z.istate.mode = BAD;
                        z.msg = "unknown compression method";
                        z.istate.marker = 5;       // can't try inflateSync
                        break;
                    }
                    if ((z.istate.method >> 4) + 8 > z.istate.wbits) {
                        z.istate.mode = BAD;
                        z.msg = "invalid window size";
                        z.istate.marker = 5;       // can't try inflateSync
                        break;
                    }
                    z.istate.mode = FLAG;
                    break;
                case FLAG:
                    if (z.availin == 0) {
                        return r;
                    }
                    r = f;
                    z.availin--;
                    z.totalin++;
                    b = (z.nextin[z.nextinindex++]) & 0xff;
                    if ((((z.istate.method << 8) + b) % 31) != 0) {
                        z.istate.mode = BAD;
                        z.msg = "incorrect header check";
                        z.istate.marker = 5;       // can't try inflateSync
                        break;
                    }

                    if ((b & PRESET_DICT) == 0) {
                        z.istate.mode = BLOCKS;
                        break;
                    }
                    z.istate.mode = DICT4;
                    break;
                case DICT4:
                    if (z.availin == 0) {
                        return r;
                    }
                    r = f;
                    z.availin--;
                    z.totalin++;
                    z.istate.need = ((z.nextin[z.nextinindex++] & 0xff) << 24) & 0xff000000L;
                    z.istate.mode = DICT3;
                    break;
                case DICT3:
                    if (z.availin == 0) {
                        return r;
                    }
                    r = f;
                    z.availin--;
                    z.totalin++;
                    z.istate.need += ((z.nextin[z.nextinindex++] & 0xff) << 16) & 0xff0000L;
                    z.istate.mode = DICT2;
                    break;
                case DICT2:
                    if (z.availin == 0) {
                        return r;
                    }
                    r = f;
                    z.availin--;
                    z.totalin++;
                    z.istate.need += ((z.nextin[z.nextinindex++] & 0xff) << 8) & 0xff00L;
                    z.istate.mode = DICT1;
                    break;
                case DICT1:
                    if (z.availin == 0) {
                        return r;
                    }
                    r = f;
                    z.availin--;
                    z.totalin++;
                    z.istate.need += (z.nextin[z.nextinindex++] & 0xffL);
                    z.adler = z.istate.need;
                    z.istate.mode = DICT0;
                    return Z_NEED_DICT;
                case DICT0:
                    z.istate.mode = BAD;
                    z.msg = "need dictionary";
                    z.istate.marker = 0;       // can try inflateSync
                    return Z_STREAM_ERROR;
                case BLOCKS:
                    r = z.istate.blocks.proc(z, r);
                    if (r == Z_DATA_ERROR) {
                        z.istate.mode = BAD;
                        z.istate.marker = 0;     // can try inflateSync
                        break;
                    }
                    if (r == Z_OK) {
                        r = f;
                    }
                    if (r != Z_STREAM_END) {
                        return r;
                    }
                    r = f;
                    z.istate.blocks.reset(z, z.istate.was);
                    if (z.istate.nowrap != 0) {
                        z.istate.mode = DONE;
                        break;
                    }
                    z.istate.mode = CHECK4;
                    break;
                case CHECK4:
                    if (z.availin == 0) {
                        return r;
                    }
                    r = f;
                    z.availin--;
                    z.totalin++;
                    z.istate.need = ((z.nextin[z.nextinindex++] & 0xff) << 24) & 0xff000000L;
                    z.istate.mode = CHECK3;
                    break;
                case CHECK3:
                    if (z.availin == 0) {
                        return r;
                    }
                    r = f;
                    z.availin--;
                    z.totalin++;
                    z.istate.need += ((z.nextin[z.nextinindex++] & 0xff) << 16) & 0xff0000L;
                    z.istate.mode = CHECK2;
                    break;
                case CHECK2:
                    if (z.availin == 0) {
                        return r;
                    }
                    r = f;
                    z.availin--;
                    z.totalin++;
                    z.istate.need += ((z.nextin[z.nextinindex++] & 0xff) << 8) & 0xff00L;
                    z.istate.mode = CHECK1;
                    break;
                case CHECK1:
                    if (z.availin == 0) {
                        return r;
                    }
                    r = f;
                    z.availin--;
                    z.totalin++;
                    z.istate.need += (z.nextin[z.nextinindex++] & 0xffL);
                    if (((int) (z.istate.was[0])) != ((int) (z.istate.need))) {
                        z.istate.mode = BAD;
                        z.msg = "incorrect data check";
                        z.istate.marker = 5;       // can't try inflateSync
                        break;
                    }
                    z.istate.mode = DONE;
                    break;
                case DONE:
                    return Z_STREAM_END;
                case BAD:
                    return Z_DATA_ERROR;
                default:
                    return Z_STREAM_ERROR;
            }
        }
    }

    protected int inflateSetDictionary(ZStream z, byte[] dictionary, int dictLength) {
        int index = 0;
        int length = dictLength;
        if (z == null || z.istate == null || z.istate.mode != DICT0) {
            return Z_STREAM_ERROR;
        }

        if (Adler32.adler32(1L, dictionary, 0, dictLength) != z.adler) {
            return Z_DATA_ERROR;
        }

        z.adler = Adler32.adler32(0, null, 0, 0);

        if (length >= (1 << z.istate.wbits)) {
            length = (1 << z.istate.wbits) - 1;
            index = dictLength - length;
        }
        z.istate.blocks.setDictionary(dictionary, index, length);
        z.istate.mode = BLOCKS;
        return Z_OK;
    }

    private static byte[] mark = {(byte) 0, (byte) 0, (byte) 0xff, (byte) 0xff};

    protected int inflateSync(ZStream z) {
        int n;       // number of bytes to look at
        int p;       // pointer to bytes
        int m;       // number of marker bytes found in a row
        long r, w;   // temporaries to save total_in and total_out

        // set up
        if (z == null || z.istate == null) {
            return Z_STREAM_ERROR;
        }
        if (z.istate.mode != BAD) {
            z.istate.mode = BAD;
            z.istate.marker = 0;
        }
        if ((n = z.availin) == 0) {
            return Z_BUF_ERROR;
        }
        p = z.nextinindex;
        m = z.istate.marker;

        // search
        while (n != 0 && m < 4) {
            if (z.nextin[p] == mark[m]) {
                m++;
            } else if (z.nextin[p] != 0) {
                m = 0;
            } else {
                m = 4 - m;
            }
            p++;
            n--;
        }

        // restore
        z.totalin += p - z.nextinindex;
        z.nextinindex = p;
        z.availin = n;
        z.istate.marker = m;

        // return no joy or set up to restart on a new block
        if (m != 4) {
            return Z_DATA_ERROR;
        }
        r = z.totalin;
        w = z.totalout;
        inflateReset(z);
        z.totalin = r;
        z.totalout = w;
        z.istate.mode = BLOCKS;
        return Z_OK;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy