Home | History | Annotate | Download | only in lz
      1 /*
      2  * LZDecoder
      3  *
      4  * Authors: Lasse Collin <lasse.collin (at) 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.lz;
     12 
     13 import java.io.DataInputStream;
     14 import java.io.IOException;
     15 import org.tukaani.xz.CorruptedInputException;
     16 
     17 public final class LZDecoder {
     18     private final byte[] buf;
     19     private int start = 0;
     20     private int pos = 0;
     21     private int full = 0;
     22     private int limit = 0;
     23     private int pendingLen = 0;
     24     private int pendingDist = 0;
     25 
     26     public LZDecoder(int dictSize, byte[] presetDict) {
     27         buf = new byte[dictSize];
     28 
     29         if (presetDict != null) {
     30             pos = Math.min(presetDict.length, dictSize);
     31             full = pos;
     32             start = pos;
     33             System.arraycopy(presetDict, presetDict.length - pos, buf, 0, pos);
     34         }
     35     }
     36 
     37     public void reset() {
     38         start = 0;
     39         pos = 0;
     40         full = 0;
     41         limit = 0;
     42         buf[buf.length - 1] = 0x00;
     43     }
     44 
     45     public void setLimit(int outMax) {
     46         if (buf.length - pos <= outMax)
     47             limit = buf.length;
     48         else
     49             limit = pos + outMax;
     50     }
     51 
     52     public boolean hasSpace() {
     53         return pos < limit;
     54     }
     55 
     56     public boolean hasPending() {
     57         return pendingLen > 0;
     58     }
     59 
     60     public int getPos() {
     61         return pos;
     62     }
     63 
     64     public int getByte(int dist) {
     65         int offset = pos - dist - 1;
     66         if (dist >= pos)
     67             offset += buf.length;
     68 
     69         return buf[offset] & 0xFF;
     70     }
     71 
     72     public void putByte(byte b) {
     73         buf[pos++] = b;
     74 
     75         if (full < pos)
     76             full = pos;
     77     }
     78 
     79     public void repeat(int dist, int len) throws IOException {
     80         if (dist < 0 || dist >= full)
     81             throw new CorruptedInputException();
     82 
     83         int left = Math.min(limit - pos, len);
     84         pendingLen = len - left;
     85         pendingDist = dist;
     86 
     87         int back = pos - dist - 1;
     88         if (dist >= pos)
     89             back += buf.length;
     90 
     91         do {
     92             buf[pos++] = buf[back++];
     93             if (back == buf.length)
     94                 back = 0;
     95         } while (--left > 0);
     96 
     97         if (full < pos)
     98             full = pos;
     99     }
    100 
    101     public void repeatPending() throws IOException {
    102         if (pendingLen > 0)
    103             repeat(pendingDist, pendingLen);
    104     }
    105 
    106     public void copyUncompressed(DataInputStream inData, int len)
    107             throws IOException {
    108         int copySize = Math.min(buf.length - pos, len);
    109         inData.readFully(buf, pos, copySize);
    110         pos += copySize;
    111 
    112         if (full < pos)
    113             full = pos;
    114     }
    115 
    116     public int flush(byte[] out, int outOff) {
    117         int copySize = pos - start;
    118         if (pos == buf.length)
    119             pos = 0;
    120 
    121         System.arraycopy(buf, start, out, outOff, copySize);
    122         start = pos;
    123 
    124         return copySize;
    125     }
    126 }
    127