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

org.glassfish.grizzly.compression.lzma.LZMADecoder Maven / Gradle / Ivy

There is a newer version: 2.2.0
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 2011-2015 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

package org.glassfish.grizzly.compression.lzma;

import org.glassfish.grizzly.AbstractTransformer;
import org.glassfish.grizzly.Buffer;
import org.glassfish.grizzly.Cacheable;
import org.glassfish.grizzly.ThreadCache;
import org.glassfish.grizzly.TransformationException;
import org.glassfish.grizzly.TransformationResult;
import org.glassfish.grizzly.attributes.AttributeStorage;
import org.glassfish.grizzly.compression.lzma.impl.Decoder;
import org.glassfish.grizzly.memory.MemoryManager;

import java.io.IOException;
import org.glassfish.grizzly.compression.lzma.impl.Base;
import org.glassfish.grizzly.compression.lzma.impl.Decoder.LiteralDecoder;

public class LZMADecoder extends AbstractTransformer {

    private static final ThreadCache.CachedTypeIndex CACHE_IDX =
            ThreadCache.obtainIndex(LZMAInputState.class, 2);


    // ---------------------------------------- Methods from AbstractTransformer


    @Override
    public String getName() {
        return "lzma-decoder";
    }

    @Override
    public boolean hasInputRemaining(AttributeStorage storage, Buffer input) {
        return input.hasRemaining();
    }

    @Override
    protected TransformationResult transformImpl(AttributeStorage storage, Buffer input) throws TransformationException {
        final MemoryManager memoryManager = obtainMemoryManager(storage);

        final LZMAInputState state = (LZMAInputState) obtainStateObject(storage);
        state.setMemoryManager(memoryManager);

        Buffer decodedBuffer = null;
        Decoder.State decState = null;
        if (input.hasRemaining()) {
            decState = decodeBuffer(memoryManager, input, state);
            decodedBuffer = state.getDst();
        }

        final boolean hasRemainder = input.hasRemaining();

        if (decState == Decoder.State.NEED_MORE_DATA
                || decodedBuffer == null) {
            return TransformationResult.createIncompletedResult(hasRemainder ? input : null);
        }

        return TransformationResult.createCompletedResult(decodedBuffer.flip(),
                hasRemainder ? input : null);
    }

    @Override
    protected LastResultAwareState createStateObject() {
        return create();
    }

    // ---------------------------------------------------------- Public Methods


    public static LZMAInputState create() {
        final LZMAInputState state =
                ThreadCache.takeFromCache(CACHE_IDX);
        if (state != null) {
            return state;
        }

        return new LZMAInputState();
    }


    public void finish(AttributeStorage storage) {
        final LZMAInputState state = (LZMAInputState) obtainStateObject(storage);
        state.recycle();
    }


    // --------------------------------------------------------- Private Methods


    private Decoder.State decodeBuffer(final MemoryManager memoryManager,
                                       final Buffer buffer,
                                       final LZMAInputState state) {

        state.setSrc(buffer);

        Decoder.State decState;
        try {
            decState = state.getDecoder().code(state, -1);
        } catch (IOException e) {
            disposeDstBuffer(state);
            throw new IllegalStateException(e);
        }
        if (decState == Decoder.State.ERR) {
            disposeDstBuffer(state);
            throw new IllegalStateException("Invalid decoder state.");
        }

        return decState;

    }

    private static void disposeDstBuffer(LZMAInputState state) {
        final Buffer dstBuffer = state.getDst();
        if (dstBuffer != null) {
            dstBuffer.dispose();
            state.setDst(null);
        }
    }


    // ---------------------------------------------------------- Nested Classes


    public static class LZMAInputState extends LastResultAwareState implements Cacheable {

        private final Decoder decoder = new Decoder();
        private boolean initialized;
        private final byte[] decoderConfigBits = new byte[5];
        private Buffer src;
        private Buffer dst;
        private MemoryManager mm;

        public int state;
        public int rep0;
        public int rep1;
        public int rep2;
        public int rep3;
        public long nowPos64;
        public byte prevByte;
        public boolean decInitialized;
        
        public int posState;
        public int lastMethodResult;

        public int inner1State;
        public int inner2State;

        public LiteralDecoder.Decoder2 decoder2;

        // BitTreeDecoder static reverseDecode state
        public int staticReverseDecodeMethodState;
        public int staticM;
        public int staticBitIndex;
        public int staticSymbol;

        // Decoder.processState3 method state
        public int state3Len;
        
        // Decoder.processState31 method state
        public int state31;

        // Decoder.processState311 method state
        public int state311;
        public int state311Distance;

        // Decoder.processState32 method state
        public int state32;
        public int state32PosSlot;

        // Decoder.processState321 method state
        public int state321;
        public int state321NumDirectBits;

        // ------------------------------------------------------ Public Methods


        public boolean initialize(final Buffer buffer) {
            buffer.get(decoderConfigBits);
            initialized = decoder.setDecoderProperties(decoderConfigBits);
            state = Base.stateInit();
            return initialized;
        }

        public boolean isInitialized() {
            return initialized;
        }

        public Decoder getDecoder() {
            return decoder;
        }

        public Buffer getSrc() {
            return src;
        }

        public void setSrc(Buffer src) {
            this.src = src;
        }

        public Buffer getDst() {
            return dst;
        }

        public void setDst(Buffer dst) {
            this.dst = dst;
        }

        public MemoryManager getMemoryManager() {
            return mm;
        }

        public void setMemoryManager(MemoryManager mm) {
            this.mm = mm;
        }

        // ---------------------------------------------- Methods from Cacheable


        @Override
        public void recycle() {
            state = 0;
            rep0 = 0;
            rep1 = 0;
            rep2 = 0;
            rep3 = 0;
            nowPos64 = 0;
            prevByte = 0;
            src = null;
            dst = null;
            lastResult = null;
            initialized = false;
            decInitialized = false;
            mm = null;

            posState = 0;
            lastMethodResult = 0;

            inner1State = 0;
            inner2State = 0;

            decoder2 = null;

            staticReverseDecodeMethodState = 0;

            state31 = 0;
            state311 = 0;
            state32 = 0;
            state321 = 0;

            ThreadCache.putToCache(CACHE_IDX, this);
        }

    } // END LZMAInputState

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy