11e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan/*
21e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * RangeDecoderFromBuffer
31e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan *
41e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * Authors: Lasse Collin <lasse.collin@tukaani.org>
51e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan *          Igor Pavlov <http://7-zip.org/>
61e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan *
71e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * This file has been put into the public domain.
81e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * You can do whatever you want with this file.
91e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan */
101e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan
111e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnanpackage org.tukaani.xz.rangecoder;
121e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan
131e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnanimport java.io.DataInputStream;
141e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnanimport java.io.IOException;
151e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnanimport org.tukaani.xz.CorruptedInputException;
161e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan
171e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnanpublic final class RangeDecoderFromBuffer extends RangeDecoder {
181e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan    private static final int INIT_SIZE = 5;
191e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan
201e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan    private final byte[] buf;
211e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan    private int pos = 0;
221e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan    private int end = 0;
231e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan
241e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan    public RangeDecoderFromBuffer(int inputSizeMax) {
251e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan        buf = new byte[inputSizeMax - INIT_SIZE];
261e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan    }
271e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan
281e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan    public void prepareInputBuffer(DataInputStream in, int len)
291e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan            throws IOException {
301e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan        if (len < INIT_SIZE)
311e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan            throw new CorruptedInputException();
321e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan
331e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan        if (in.readUnsignedByte() != 0x00)
341e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan            throw new CorruptedInputException();
351e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan
361e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan        code = in.readInt();
371e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan        range = 0xFFFFFFFF;
381e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan
391e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan        pos = 0;
401e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan        end = len - INIT_SIZE;
411e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan        in.readFully(buf, 0, end);
421e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan    }
431e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan
441e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan    public boolean isInBufferOK() {
451e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan        return pos <= end;
461e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan    }
471e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan
481e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan    public boolean isFinished() {
491e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan        return pos == end && code == 0;
501e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan    }
511e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan
521e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan    public void normalize() throws IOException {
531e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan        if ((range & TOP_MASK) == 0) {
541e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan            try {
551e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan                // If the input is corrupt, this might throw
561e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan                // ArrayIndexOutOfBoundsException.
571e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan                code = (code << SHIFT_BITS) | (buf[pos++] & 0xFF);
581e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan                range <<= SHIFT_BITS;
591e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan            } catch (ArrayIndexOutOfBoundsException e) {
601e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan                throw new CorruptedInputException();
611e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan            }
621e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan        }
631e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan    }
641e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan}
65