📄 ppmcontext.java
字号:
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 31.05.2007
*
* Source: $HeadURL$
* Last changed: $LastChangedDate$
*
* the unrar licence applies to all junrar source and binary distributions
* you are not allowed to use this source to re-create the RAR compression algorithm
*
* Here some html entities which can be used for escaping javadoc tags:
* "&": "&" or "&"
* "<": "<" or "<"
* ">": ">" or ">"
* "@": "@"
*/
package de.innosystec.unrar.unpack.ppm;
import de.innosystec.unrar.io.Raw;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class PPMContext extends Pointer
{
public static final int size = 12;
private short numStats; // determines if feqData or onstate is used
// (1==onestate)
private FreqData freqData; // -\
// |-> union
private State oneState; // -/
private int Suffix; // pointer ppmcontext
public static byte[] ExpEscape = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2,
2, 2, 2 };
public PPMContext(byte[] mem)
{
super(mem);
oneState = new State(mem);
freqData = new FreqData(mem);
}
public FreqData getFreqData()
{
freqData.setAddress(pos+2);
return freqData;
}
public void setFreqData(FreqData freqData)
{
this.freqData.setAddress(pos+2);
this.freqData.setSummFreq(freqData.getSummFreq());
this.freqData.setStats(freqData.getStats());
this.freqData.setAddress(pos+2);
oneState.setAddress(pos + 2);
}
public short getNumStats()
{
if(mem!=null){
numStats = Raw.readShortLittleEndian(mem, pos);
}
return numStats;
}
public void setNumStats(short numStats)
{
this.numStats = numStats;
if (mem != null) {
Raw.writeShortLittleEndian(mem, pos, numStats);
}
}
public State getOneState()
{
return oneState;
}
public void setOneState(State oneState)
{
this.oneState.setAddress(pos+2);
this.oneState.setFreq(oneState.getFreq());
this.oneState.setSuccessor(oneState.getSuccessor());
this.oneState.setSymbol(oneState.getSymbol());
this.oneState.setAddress(pos+2);
this.freqData.setAddress(pos + 2);
}
public int getSuffix()
{
if(mem!=null){
Suffix = Raw.readIntLittleEndian(mem, pos+8);
}
return Suffix;
}
public void setSuffix(PPMContext suffix)
{
setSuffix(suffix.getAddress());
}
public void setSuffix(int suffix)
{
Suffix = suffix;
if (mem != null) {
Raw.writeIntLittleEndian(mem, pos + 8, suffix);
}
}
@Override
public boolean setAddress(int pos)
{
if (mem == null) {
return false;
}
if (pos < 0 || pos >= mem.length) {
return false;
}
if (pos + size >= mem.length) {
return false;
}
this.pos = pos;
numStats = Raw.readShortLittleEndian(mem, pos);
pos += 2;
if (numStats == 1) {
oneState.setAddress(pos);
freqData.setAddress(pos);
pos += State.size;
} else {
freqData.setAddress(pos);
oneState.setAddress(pos);
pos += FreqData.size;
}
Suffix = Raw.readIntLittleEndian(mem, pos);
return true;
}
public int createChild(ModelPPM model, State pStats/* ptr */,
State firstState /* ref */)
{
PPMContext pc = new PPMContext(model.getSubAlloc().getHeap());
pc.setAddress(model.getSubAlloc().allocContext());
if (pc != null) {
pc.setNumStats((short) 1);
pc.setOneState(firstState);
pc.setSuffix(this);
pStats.setSuccessor(pc);
}
return pc.getAddress();
}
public void rescale(ModelPPM Model)
{
int OldNS = numStats, i = numStats - 1, Adder, EscFreq;
// STATE* p1, * p;
State p1 = new State(Model.getHeap());
State p = new State(Model.getHeap());
State temp = new State(Model.getHeap());
for (p.setAddress(Model.getFoundState().getAddress()); p.getAddress() != freqData
.getStats(); p.setAddress(p.getAddress() - State.size)) {
temp.setAddress(p.getAddress() - State.size);
ppmdSwap(Model, p, temp);
}
temp.setAddress(freqData.getStats());
temp.setFreq((byte) (temp.getFreq() + 4));
freqData.setSummFreq((short) (freqData.getSummFreq() + 4));
EscFreq = freqData.getSummFreq() - p.getFreq();
Adder = Model.getOrderFall() != 0 ? 1 : 0;
p.setFreq((byte) ((p.getFreq() + Adder) >>> 1));
freqData.setSummFreq(p.getFreq());
do {
temp.setAddress(p.getAddress() + State.size);
EscFreq -= temp.getFreq();
p.setFreq((byte) ((p.getFreq() + Adder) >>> 1));
freqData
.setSummFreq((short) (freqData.getSummFreq() + p.getFreq()));
temp.setAddress(p.getAddress() - State.size);
if (p.getFreq() > temp.getFreq()) {
temp.setAddress(p.getAddress());
p1.setAddress(p.getAddress());
State temp2 = new State(Model.getHeap());
State temp3 = new State(Model.getHeap());
do {
// p1[0]=p1[-1];
temp2.setAddress(p1.getAddress() - State.size);
p1.setValues(temp2);
temp3.setAddress(p1.getAddress());
} while (p1.decAddress().getAddress() != freqData.getStats()&& temp.getFreq() > temp3.getFreq());
p1.setValues(temp2);
}
} while (--i != 0);
if (p.getFreq() == 0) {
do {
i++;
p.decAddress();
} while (p.getFreq() == 0);
EscFreq += i;
if ((numStats -= i) == 1) {
State temp2 = new State(null);
temp.setAddress(freqData.getStats());
temp2.setValues(temp);
// STATE tmp=*U.Stats;
do {
temp.setFreq((byte) (temp.getFreq() - temp.getFreq() >>> 1));
EscFreq >>>= 1;
} while (EscFreq > 1);
Model.getSubAlloc().freeUnits(freqData.getStats(),(OldNS + 1) >>> 1);
oneState.setValues(temp);
Model.getFoundState().setAddress(oneState.getAddress());
return;
}
}
EscFreq -= EscFreq >>> 1;
freqData.setSummFreq((short) (freqData.getSummFreq() + EscFreq));
int n0 = (OldNS + 1) >>> 1, n1 = (numStats + 1) >>> 1;
if (n0 != n1) {
freqData.setStats(Model.getSubAlloc().shrinkUnits(freqData.getStats(), n0, n1));
}
Model.getFoundState().setAddress(freqData.getStats());
}
private int getArrayIndex(ModelPPM Model, State rs)
{
PPMContext tempSuffix = new PPMContext(Model.getSubAlloc().getHeap());
tempSuffix.setAddress(Suffix);
int ret = 0;
ret += Model.getPrevSuccess();
ret += Model.getNS2BSIndx()[tempSuffix.getNumStats() - 1];
ret += Model.getHiBitsFlag() + 2* Model.getHB2Flag()[(int) rs.getSymbol() & 0xFF];
ret += ((Model.getRunLength() >>> 26) & 0x20);
return ret;
}
public int getMean(int summ, int shift, int round)
{
return ( (summ + (1 << (shift - round) ) ) >>> (shift) );
}
public void decodeBinSymbol(ModelPPM Model)
{
State rs = new State(Model.getSubAlloc().getHeap());
rs.setAddress(oneState.getAddress());// State&
Model.setHiBitsFlag(Model.getHB2Flag()[(short)Model.getFoundState().getSymbol()&0xff]);
int off1 =(short)(rs.getFreq() & 0xFF) - 1;
int off2 = getArrayIndex(Model, rs);
int bs = Model.getBinSumm()[off1][off2];
if (Model.getCoder().getCurrentShiftCount(ModelPPM.TOT_BITS) < bs) {
Model.getFoundState().setAddress(rs.getAddress());
rs.setFreq((byte) (rs.getFreq() + ((rs.getFreq() <= 127) ? 1 : 0)));
Model.getCoder().getSubRange().setLowCount(0);
Model.getCoder().getSubRange().setHighCount(bs);
bs = ((bs + ModelPPM.INTERVAL - getMean(bs, ModelPPM.PERIOD_BITS, 2)) & 0xffff);
Model.getBinSumm()[off1][off2] = (short)bs;
Model.setPrevSuccess((byte) 1);
Model.setRunLength(Model.getRunLength() + 1);
} else {
Model.getCoder().getSubRange().setLowCount(bs);
bs = (bs - getMean(bs, ModelPPM.PERIOD_BITS, 2)) & 0xFFFF;
Model.getBinSumm()[off1][off2] = (short)bs;
Model.getCoder().getSubRange().setHighCount(ModelPPM.BIN_SCALE);
Model.setInitEsc(ExpEscape[bs >>> 10]);
Model.setNumMasked(1);
Model.getCharMask()[(short)rs.getSymbol()&0xff] = Model.getEscCount();
Model.setPrevSuccess((byte) 0);
Model.getFoundState().setAddress(0);
}
int a = 0;//TODO just 4 debugging
}
public static void ppmdSwap(ModelPPM Model, State state1, State state2)
{
byte temp = 0;
byte[] bytes = Model.getSubAlloc().getHeap();
int p1 = state1.getAddress();
int p2 = state2.getAddress();
for (int i = 0; i < State.size; i++) {
temp = bytes[p1+i];
bytes[p1+i] = bytes[p2+i];
bytes[p2+i] = temp;
}
state1.setAddress(p1);
state2.setAddress(p2);
}
public void update1(ModelPPM Model, int p/* ptr */)
{
Model.getFoundState().setAddress(p);
Model.getFoundState().setFreq((byte) (Model.getFoundState().getFreq() + 4));
freqData.setSummFreq((short) (freqData.getSummFreq() + 4));
State p0 = new State(Model.getSubAlloc().getHeap());
State p1 = new State(Model.getSubAlloc().getHeap());
p0.setAddress(p);
p1.setAddress(p - State.size);
if (p0.getFreq() > p1.getFreq()) {
ppmdSwap(Model, p0, p1);
Model.getFoundState().setAddress(p1.getAddress());
if (p0.getFreq() > ModelPPM.MAX_FREQ)
rescale(Model);
}
}
public boolean decodeSymbol2(ModelPPM Model)
{
int count, HiCnt, i = numStats - Model.getNumMasked();
SEE2Context psee2c = makeEscFreq2(Model, i);
RangeCoder coder = Model.getCoder();
// STATE* ps[256], ** pps=ps, * p=U.Stats-1;
int[] ps = new int[256];
State p = new State(Model.getHeap());
State temp = new State(Model.getHeap());
p.setAddress(freqData.getStats() - State.size);
int pps = 0;
HiCnt = 0;
do {
do {
p.incAddress();// p++;
} while (Model.getCharMask()[(int)p.getSymbol()&0xff] == Model.getEscCount());
HiCnt += (short)p.getFreq()&0xff;
ps[pps++] = p.getAddress();
} while (--i != 0);
coder.getSubRange().setScale(coder.getSubRange().getScale() + HiCnt);
count = (int) coder.getCurrentCount();
if (count >= coder.getSubRange().getScale()) {
return false;
}
pps = 0;
p.setAddress(ps[pps]);
if (count < HiCnt) {
HiCnt = 0;
while ((HiCnt += (short)p.getFreq()&0xff) <= count) {
p.setAddress(ps[++pps]);// p=*++pps;
}
coder.getSubRange().setHighCount(HiCnt);
coder.getSubRange().setLowCount(HiCnt - p.getFreq());
psee2c.update();
update2(Model, p.getAddress());
} else {
coder.getSubRange().setLowCount(HiCnt);
coder.getSubRange().setHighCount(coder.getSubRange().getScale());
i = numStats - Model.getNumMasked();// ->NumMasked;
pps--;
do {
temp.setAddress(++pps);
Model.getCharMask()[temp.getSymbol()] = Model.getEscCount();
} while (--i != 0);
psee2c.setSumm((short) (psee2c.getSumm() + coder.getSubRange()
.getScale()));
Model.setNumMasked(numStats);
}
return (true);
}
public void update2(ModelPPM Model, int p/* state ptr */)
{
State temp = new State(Model.getHeap());
temp.setAddress(p);
Model.getFoundState().setAddress(p);
Model.getFoundState().setFreq((byte) (Model.getFoundState().getFreq() + 4));
freqData.setSummFreq((short) (freqData.getSummFreq() + 4));
if (((short)temp.getFreq()&0xff) > ModelPPM.MAX_FREQ) {
rescale(Model);
}
Model.setEscCount((byte) (Model.getEscCount() + 1));
Model.setRunLength(Model.getInitRL());
}
public SEE2Context makeEscFreq2(ModelPPM Model, int Diff)
{
SEE2Context psee2c;
if (numStats != 256) {
PPMContext suff = new PPMContext(Model.getHeap());
suff.setAddress(Suffix);
int idx1 = 0, idx2 = 0;
int i = Model.getNS2Indx()[Diff - 1];
int offset = i * SEE2Context.size;
offset += (Diff < suff.getNumStats() - numStats) ? 1 : 0;
offset += 2 * ((freqData.getSummFreq() < 11 * numStats) ? 1 : 0);
offset += 4 * ((Model.getNumMasked() > Diff) ? 1 : 0);
offset += Model.getHiBitsFlag();
offset = offset / SEE2Context.size;
idx1 = offset / 25;
idx2 = offset % 25;
psee2c = Model.getSEE2Cont()[idx1][idx2];
Model.getCoder().getSubRange().setScale(psee2c.getMean());
} else {
psee2c = Model.getDummySEE2Cont();
Model.getCoder().getSubRange().setScale(1);
}
return psee2c;
}
public boolean decodeSymbol1(ModelPPM Model)
{
RangeCoder coder = Model.getCoder();
coder.getSubRange().setScale(freqData.getSummFreq());
State p = new State(Model.getHeap());
p.setAddress(freqData.getStats());
int i, HiCnt;
int count = (int) coder.getCurrentCount();
if (count >= coder.getSubRange().getScale()) {
return false;
}
if (count < (HiCnt = p.getFreq())) {
coder.getSubRange().setHighCount(HiCnt);
Model.setPrevSuccess((byte) (2 * ((HiCnt > coder.getSubRange().getScale()) ? 1 : 0)));
Model.setRunLength(Model.getRunLength() + Model.getPrevSuccess());
HiCnt += 4;
Model.getFoundState().setAddress(p.getAddress());
Model.getFoundState().setFreq((byte) HiCnt);
freqData.setSummFreq((short) (freqData.getSummFreq() + 4));
if (HiCnt > ModelPPM.MAX_FREQ) {
rescale(Model);
}
coder.getSubRange().setLowCount(0);
return true;
} else {
if (Model.getFoundState().getAddress() == 0) {
return (false);
}
}
Model.setPrevSuccess((byte) 0);
i = numStats - 1;
while ((HiCnt += ((short)p.incAddress().getFreq())&0xff) <= count)
{
if (--i == 0) {
Model.setHiBitsFlag(Model.getHB2Flag()[Model.getFoundState().getSymbol()]);
coder.getSubRange().setLowCount(HiCnt);
Model.getCharMask()[(short)p.getSymbol()&0xff] = Model.getEscCount();
Model.setNumMasked(numStats);
i = numStats - 1;
Model.getFoundState().setAddress(0);
do {
Model.getCharMask()[p.decAddress().getSymbol()] = Model.getEscCount();
} while (--i != 0);
coder.getSubRange().setHighCount(coder.getSubRange().getScale());
return (true);
}
}
coder.getSubRange().setLowCount(HiCnt-p.getFreq());
coder.getSubRange().setHighCount(HiCnt);
update1(Model, p.getAddress());
return (true);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -