• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * LZMACoder
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.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 
getDistState(int len)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 
LZMACoder(int pb)60     LZMACoder(int pb) {
61         posMask = (1 << pb) - 1;
62     }
63 
reset()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 
LiteralCoder(int lc, int lp)96         LiteralCoder(int lc, int lp) {
97             this.lc = lc;
98             this.literalPosMask = (1 << lp) - 1;
99         }
100 
getSubcoderIndex(int prevByte, int pos)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 
reset()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 
reset()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