com.github.junrar.unpack.ppm.PPMContext Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of junrar Show documentation
Show all versions of junrar Show documentation
rar decompression library in plain java
The newest version!
/*
* 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 com.github.junrar.unpack.ppm;
import com.github.junrar.io.Raw;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class PPMContext extends Pointer
{
private static final int unionSize = Math.max(FreqData.size, State.size);
public static final int size = 2 + unionSize + 4; // 12
// ushort NumStats;
private int numStats; // determines if feqData or onstate is used
// (1==onestate)
private final FreqData freqData; // -\
// |-> union
private final State oneState; // -/
private int suffix; // pointer ppmcontext
public final static int[] ExpEscape =
{ 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
// Temp fields
private final State tempState1 = new State(null);
private final State tempState2 = new State(null);
private final State tempState3 = new State(null);
private final State tempState4 = new State(null);
private final State tempState5 = new State(null);
private PPMContext tempPPMContext = null;
private final int[] ps = new int[256];
public PPMContext(byte[] mem)
{
super(mem);
oneState = new State(mem);
freqData = new FreqData(mem);
}
public PPMContext init(byte[] mem) {
this.mem = mem;
pos = 0;
oneState.init(mem);
freqData.init(mem);
return this;
}
public FreqData getFreqData()
{
return freqData;
}
public void setFreqData(FreqData freqData)
{
this.freqData.setSummFreq(freqData.getSummFreq());
this.freqData.setStats(freqData.getStats());
}
public final int getNumStats()
{
if (mem!=null){
numStats = Raw.readShortLittleEndian(mem, pos)&0xffff;
}
return numStats;
}
public final void setNumStats(int numStats)
{
this.numStats = numStats&0xffff;
if (mem != null) {
Raw.writeShortLittleEndian(mem, pos, (short)numStats);
}
}
public State getOneState()
{
return oneState;
}
public void setOneState(StateRef oneState)
{
this.oneState.setValues(oneState);
}
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)
{
this.suffix = suffix;
if (mem != null) {
Raw.writeIntLittleEndian(mem, pos + 8, suffix);
}
}
@Override
public void setAddress(int pos)
{
super.setAddress(pos);
oneState.setAddress(pos+2);
freqData.setAddress(pos+2);
}
private PPMContext getTempPPMContext(byte[] mem) {
if (tempPPMContext == null) {
tempPPMContext = new PPMContext(null);
}
return tempPPMContext.init(mem);
}
public int createChild(ModelPPM model, State pStats/* ptr */,
StateRef firstState /* ref */)
{
PPMContext pc = getTempPPMContext(model.getSubAlloc().getHeap());
pc.setAddress(model.getSubAlloc().allocContext());
if (pc != null) {
pc.setNumStats(1);
pc.setOneState(firstState);
pc.setSuffix(this);
pStats.setSuccessor(pc);
}
return pc.getAddress();
}
public void rescale(ModelPPM model)
{
int OldNS = getNumStats(), i = getNumStats() - 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.decAddress()) {
temp.setAddress(p.getAddress() - State.size);
State.ppmdSwap(p, temp);
}
temp.setAddress(freqData.getStats());
temp.incFreq(4);
freqData.incSummFreq(4);
EscFreq = freqData.getSummFreq() - p.getFreq();
Adder = (model.getOrderFall() != 0) ? 1 : 0;
p.setFreq((p.getFreq() + Adder) >>> 1);
freqData.setSummFreq(p.getFreq());
do {
p.incAddress();
EscFreq -= p.getFreq();
p.setFreq((p.getFreq() + Adder) >>> 1);
freqData.incSummFreq(p.getFreq());
temp.setAddress(p.getAddress() - State.size);
if (p.getFreq() > temp.getFreq()) {
p1.setAddress(p.getAddress());
StateRef tmp = new StateRef();
tmp.setValues(p1);
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);
p1.decAddress();
temp3.setAddress(p1.getAddress() - State.size);
} while (p1.getAddress() != freqData.getStats() && tmp.getFreq() > temp3.getFreq());
p1.setValues(tmp);
}
} while (--i != 0);
if (p.getFreq() == 0) {
do {
i++;
p.decAddress();
} while (p.getFreq() == 0);
EscFreq += i;
setNumStats(getNumStats() - i);
if (getNumStats() == 1) {
StateRef tmp = new StateRef();
temp.setAddress(freqData.getStats());
tmp.setValues(temp);
// STATE tmp=*U.Stats;
do {
// tmp.Freq-=(tmp.Freq >> 1)
tmp.decFreq(tmp.getFreq() >>> 1);
EscFreq >>>= 1;
} while (EscFreq > 1);
model.getSubAlloc().freeUnits(freqData.getStats(),(OldNS + 1) >>> 1);
oneState.setValues(tmp);
model.getFoundState().setAddress(oneState.getAddress());
return;
}
}
EscFreq -= EscFreq >>> 1;
freqData.incSummFreq(EscFreq);
int n0 = (OldNS + 1) >>> 1, n1 = (getNumStats() + 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 = getTempPPMContext(Model.getSubAlloc().getHeap());
tempSuffix.setAddress(getSuffix());
int ret = 0;
ret += Model.getPrevSuccess();
ret += Model.getNS2BSIndx()[tempSuffix.getNumStats() - 1];
ret += Model.getHiBitsFlag() + 2* Model.getHB2Flag()[rs.getSymbol()];
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 = tempState1.init(model.getHeap());
rs.setAddress(oneState.getAddress());// State&
model.setHiBitsFlag(model.getHB2Flag()[model.getFoundState().getSymbol()]);
int off1 = rs.getFreq() - 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.incFreq((rs.getFreq() < 128) ? 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] = bs;
model.setPrevSuccess(1);
model.incRunLength(1);
} else {
model.getCoder().getSubRange().setLowCount(bs);
bs = (bs - getMean(bs, ModelPPM.PERIOD_BITS, 2)) & 0xFFFF;
model.getBinSumm()[off1][off2] = bs;
model.getCoder().getSubRange().setHighCount(ModelPPM.BIN_SCALE);
model.setInitEsc(ExpEscape[bs >>> 10]);
model.setNumMasked(1);
model.getCharMask()[rs.getSymbol()] = model.getEscCount();
model.setPrevSuccess(0);
model.getFoundState().setAddress(0);
}
//int a = 0;//TODO just 4 debugging
}
// public static void ppmdSwap(ModelPPM model, StatePtr state1, StatePtr state2)
// {
// byte[] bytes = model.getSubAlloc().getHeap();
// int p1 = state1.getAddress();
// int p2 = state2.getAddress();
//
// for (int i = 0; i < StatePtr.size; i++) {
// byte 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().incFreq(4);
freqData.incSummFreq(4);
State p0 = tempState3.init(model.getHeap());
State p1 = tempState4.init(model.getHeap());
p0.setAddress(p);
p1.setAddress(p - State.size);
if (p0.getFreq() > p1.getFreq()) {
State.ppmdSwap(p0, p1);
model.getFoundState().setAddress(p1.getAddress());
if (p1.getFreq() > ModelPPM.MAX_FREQ)
rescale(model);
}
}
public boolean decodeSymbol2(ModelPPM model)
{
long count;
int hiCnt, i = getNumStats() - model.getNumMasked();
SEE2Context psee2c = makeEscFreq2(model, i);
RangeCoder coder = model.getCoder();
// STATE* ps[256], ** pps=ps, * p=U.Stats-1;
State p = tempState1.init(model.getHeap());
State temp = tempState2.init(model.getHeap());
p.setAddress(freqData.getStats() - State.size);
int pps = 0;
hiCnt = 0;
do {
do {
p.incAddress();// p++;
} while (model.getCharMask()[p.getSymbol()] == model.getEscCount());
hiCnt += p.getFreq();
ps[pps++] = p.getAddress();
} while (--i != 0);
coder.getSubRange().incScale(hiCnt);
count = coder.getCurrentCount();
if (count >= coder.getSubRange().getScale()) {
return false;
}
pps = 0;
p.setAddress(ps[pps]);
if (count < hiCnt) {
hiCnt = 0;
while ((hiCnt += p.getFreq()) <= 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 = getNumStats() - model.getNumMasked();// ->NumMasked;
pps--;
do {
temp.setAddress(ps[++pps]);// (*++pps)
model.getCharMask()[temp.getSymbol()] = model.getEscCount();
} while (--i != 0);
psee2c.incSumm((int)coder.getSubRange().getScale());
model.setNumMasked(getNumStats());
}
return (true);
}
public void update2(ModelPPM model, int p/* state ptr */)
{
State temp = tempState5.init(model.getHeap());
temp.setAddress(p);
model.getFoundState().setAddress(p);
model.getFoundState().incFreq(4);
freqData.incSummFreq(4);
if (temp.getFreq() > ModelPPM.MAX_FREQ) {
rescale(model);
}
model.incEscCount(1);
model.setRunLength(model.getInitRL());
}
private SEE2Context makeEscFreq2(ModelPPM model, int Diff)
{
SEE2Context psee2c;
int numStats = getNumStats();
if (numStats != 256) {
PPMContext suff = getTempPPMContext(model.getHeap());
suff.setAddress(getSuffix());
int idx1 = model.getNS2Indx()[Diff - 1];
int idx2 = 0;
idx2 += (Diff < suff.getNumStats() - numStats) ? 1 : 0;
idx2 += 2 * ((freqData.getSummFreq() < 11 * numStats) ? 1 : 0);
idx2 += 4 * ((model.getNumMasked() > Diff) ? 1 : 0);
idx2 += model.getHiBitsFlag();
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;
long count = coder.getCurrentCount();
if (count >= coder.getSubRange().getScale()) {
return false;
}
if (count < (HiCnt = p.getFreq())) {
coder.getSubRange().setHighCount(HiCnt);
model.setPrevSuccess((2 * HiCnt > coder.getSubRange().getScale()) ? 1 : 0);
model.incRunLength(model.getPrevSuccess());
HiCnt += 4;
model.getFoundState().setAddress(p.getAddress());
model.getFoundState().setFreq(HiCnt);
freqData.incSummFreq(4);
if (HiCnt > ModelPPM.MAX_FREQ) {
rescale(model);
}
coder.getSubRange().setLowCount(0);
return true;
} else {
if (model.getFoundState().getAddress() == 0) {
return (false);
}
}
model.setPrevSuccess(0);
int numStats = getNumStats();
i = numStats - 1;
while ((HiCnt += p.incAddress().getFreq()) <= count)
{
if (--i == 0) {
model.setHiBitsFlag(model.getHB2Flag()[model.getFoundState().getSymbol()]);
coder.getSubRange().setLowCount(HiCnt);
model.getCharMask()[p.getSymbol()] = 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);
}
public String toString() {
StringBuilder buffer = new StringBuilder();
buffer.append("PPMContext[");
buffer.append("\n pos=");
buffer.append(pos);
buffer.append("\n size=");
buffer.append(size);
buffer.append("\n numStats=");
buffer.append(getNumStats());
buffer.append("\n Suffix=");
buffer.append(getSuffix());
buffer.append("\n freqData=");
buffer.append(freqData);
buffer.append("\n oneState=");
buffer.append(oneState);
buffer.append("\n]");
return buffer.toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy