1 /* 2 * RangeDecoderFromBuffer 3 * 4 * Authors: Lasse Collin <lasse.collin@tukaani.org> 5 * Igor Pavlov <http://7-zip.org/> 6 * 7 * This file has been put into the public domain. 8 * You can do whatever you want with this file. 9 */ 10 11 package org.tukaani.xz.rangecoder; 12 13 import java.io.DataInputStream; 14 import java.io.IOException; 15 import org.tukaani.xz.ArrayCache; 16 import org.tukaani.xz.CorruptedInputException; 17 18 public final class RangeDecoderFromBuffer extends RangeDecoder { 19 private static final int INIT_SIZE = 5; 20 21 private final byte[] buf; 22 private int pos; 23 RangeDecoderFromBuffer(int inputSizeMax, ArrayCache arrayCache)24 public RangeDecoderFromBuffer(int inputSizeMax, ArrayCache arrayCache) { 25 // We will use the *end* of the array so if the cache gives us 26 // a bigger-than-requested array, we still want to use buf.length. 27 buf = arrayCache.getByteArray(inputSizeMax - INIT_SIZE, false); 28 pos = buf.length; 29 } 30 putArraysToCache(ArrayCache arrayCache)31 public void putArraysToCache(ArrayCache arrayCache) { 32 arrayCache.putArray(buf); 33 } 34 prepareInputBuffer(DataInputStream in, int len)35 public void prepareInputBuffer(DataInputStream in, int len) 36 throws IOException { 37 if (len < INIT_SIZE) 38 throw new CorruptedInputException(); 39 40 if (in.readUnsignedByte() != 0x00) 41 throw new CorruptedInputException(); 42 43 code = in.readInt(); 44 range = 0xFFFFFFFF; 45 46 // Read the data to the end of the buffer. If the data is corrupt 47 // and the decoder, reading from buf, tries to read past the end of 48 // the data, ArrayIndexOutOfBoundsException will be thrown and 49 // the problem is detected immediately. 50 len -= INIT_SIZE; 51 pos = buf.length - len; 52 in.readFully(buf, pos, len); 53 } 54 isFinished()55 public boolean isFinished() { 56 return pos == buf.length && code == 0; 57 } 58 normalize()59 public void normalize() throws IOException { 60 if ((range & TOP_MASK) == 0) { 61 try { 62 // If the input is corrupt, this might throw 63 // ArrayIndexOutOfBoundsException. 64 code = (code << SHIFT_BITS) | (buf[pos++] & 0xFF); 65 range <<= SHIFT_BITS; 66 } catch (ArrayIndexOutOfBoundsException e) { 67 throw new CorruptedInputException(); 68 } 69 } 70 } 71 } 72