Home | History | Annotate | Download | only in lzma
      1 /*
      2  * LZMACoder
      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.lzma;
     12 
     13 import org.tukaani.xz.rangecoder.RangeCoder;
     14 
     15 abstract class LZMACoder {
     16     static final int POS_STATES_MAX = 1 << 4;
     17 
     18     static final int MATCH_LEN_MIN = 2;
     19     static final int MATCH_LEN_MAX = MATCH_LEN_MIN + LengthCoder.LOW_SYMBOLS
     20                                      + LengthCoder.MID_SYMBOLS
     21                                      + LengthCoder.HIGH_SYMBOLS - 1;
     22 
     23     static final int DIST_STATES = 4;
     24     static final int DIST_SLOTS = 1 << 6;
     25     static final int DIST_MODEL_START = 4;
     26     static final int DIST_MODEL_END = 14;
     27     static final int FULL_DISTANCES = 1 << (DIST_MODEL_END / 2);
     28 
     29     static final int ALIGN_BITS = 4;
     30     static final int ALIGN_SIZE = 1 << ALIGN_BITS;
     31     static final int ALIGN_MASK = ALIGN_SIZE - 1;
     32 
     33     static final int REPS = 4;
     34 
     35     final int posMask;
     36 
     37     final int[] reps = new int[REPS];
     38     final State state = new State();
     39 
     40     final short[][] isMatch = new short[State.STATES][POS_STATES_MAX];
     41     final short[] isRep = new short[State.STATES];
     42     final short[] isRep0 = new short[State.STATES];
     43     final short[] isRep1 = new short[State.STATES];
     44     final short[] isRep2 = new short[State.STATES];
     45     final short[][] isRep0Long = new short[State.STATES][POS_STATES_MAX];
     46     final short[][] distSlots = new short[DIST_STATES][DIST_SLOTS];
     47     final short[][] distSpecial = { new short[2], new short[2],
     48                                     new short[4], new short[4],
     49                                     new short[8], new short[8],
     50                                     new short[16], new short[16],
     51                                     new short[32], new short[32] };
     52     final short[] distAlign = new short[ALIGN_SIZE];
     53 
     54     static final int getDistState(int len) {
     55         return len < DIST_STATES + MATCH_LEN_MIN
     56                ? len - MATCH_LEN_MIN
     57                : DIST_STATES - 1;
     58     }
     59 
     60     LZMACoder(int pb) {
     61         posMask = (1 << pb) - 1;
     62     }
     63 
     64     void reset() {
     65         reps[0] = 0;
     66         reps[1] = 0;
     67         reps[2] = 0;
     68         reps[3] = 0;
     69         state.reset();
     70 
     71         for (int i = 0; i < isMatch.length; ++i)
     72             RangeCoder.initProbs(isMatch[i]);
     73 
     74         RangeCoder.initProbs(isRep);
     75         RangeCoder.initProbs(isRep0);
     76         RangeCoder.initProbs(isRep1);
     77         RangeCoder.initProbs(isRep2);
     78 
     79         for (int i = 0; i < isRep0Long.length; ++i)
     80             RangeCoder.initProbs(isRep0Long[i]);
     81 
     82         for (int i = 0; i < distSlots.length; ++i)
     83             RangeCoder.initProbs(distSlots[i]);
     84 
     85         for (int i = 0; i < distSpecial.length; ++i)
     86             RangeCoder.initProbs(distSpecial[i]);
     87 
     88         RangeCoder.initProbs(distAlign);
     89     }
     90 
     91 
     92     abstract class LiteralCoder {
     93         private final int lc;
     94         private final int literalPosMask;
     95 
     96         LiteralCoder(int lc, int lp) {
     97             this.lc = lc;
     98             this.literalPosMask = (1 << lp) - 1;
     99         }
    100 
    101         final int getSubcoderIndex(int prevByte, int pos) {
    102             int low = prevByte >> (8 - lc);
    103             int high = (pos & literalPosMask) << lc;
    104             return low + high;
    105         }
    106 
    107 
    108         abstract class LiteralSubcoder {
    109             final short[] probs = new short[0x300];
    110 
    111             void reset() {
    112                 RangeCoder.initProbs(probs);
    113             }
    114         }
    115     }
    116 
    117 
    118     abstract class LengthCoder {
    119         static final int LOW_SYMBOLS = 1 << 3;
    120         static final int MID_SYMBOLS = 1 << 3;
    121         static final int HIGH_SYMBOLS = 1 << 8;
    122 
    123         final short[] choice = new short[2];
    124         final short[][] low = new short[POS_STATES_MAX][LOW_SYMBOLS];
    125         final short[][] mid = new short[POS_STATES_MAX][MID_SYMBOLS];
    126         final short[] high = new short[HIGH_SYMBOLS];
    127 
    128         void reset() {
    129             RangeCoder.initProbs(choice);
    130 
    131             for (int i = 0; i < low.length; ++i)
    132                 RangeCoder.initProbs(low[i]);
    133 
    134             for (int i = 0; i < low.length; ++i)
    135                 RangeCoder.initProbs(mid[i]);
    136 
    137             RangeCoder.initProbs(high);
    138         }
    139     }
    140 }
    141