?? modelppm.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 java.io.IOException;
import java.util.Arrays;
import de.innosystec.unrar.exception.RarException;
import de.innosystec.unrar.unpack.Unpack;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class ModelPPM
{
public static final int MAX_O = 64; /* maximum allowed model order */
public static final int INT_BITS = 7;
public static final int PERIOD_BITS = 7;
public static final int TOT_BITS = INT_BITS + PERIOD_BITS;
public static final int INTERVAL = 1 << INT_BITS;
public static final int BIN_SCALE = 1 << TOT_BITS;
public static final int MAX_FREQ = 124;
private SEE2Context[][] SEE2Cont = new SEE2Context[25][16];
private SEE2Context dummySEE2Cont;
private PPMContext minContext, medContext, maxContext;
private State foundState; // found next state transition
private int numMasked, initEsc, orderFall, maxOrder, runLength, initRL;
private int[] charMask = new int[256];
private int[] NS2Indx = new int[256];
private int[] NS2BSIndx = new int[256];
private int[] HB2Flag = new int[256];
// byte EscCount, PrevSuccess, HiBitsFlag;
private int escCount, prevSuccess, hiBitsFlag;
private int[][] binSumm = new int[128][64]; // binary SEE-contexts
private RangeCoder coder = new RangeCoder();
private SubAllocator subAlloc = new SubAllocator();
private static int InitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3,
0x64A1, 0x5ABC, 0x6632, 0x6051 };
// 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 StateRef tempStateRef1 = new StateRef();
private final StateRef tempStateRef2 = new StateRef();
private final PPMContext tempPPMContext1 = new PPMContext(null);
private final PPMContext tempPPMContext2 = new PPMContext(null);
private final PPMContext tempPPMContext3 = new PPMContext(null);
private final PPMContext tempPPMContext4 = new PPMContext(null);
private final int[] ps = new int[MAX_O];
public ModelPPM()
{
minContext = null;
maxContext = null;
medContext = null;
}
public SubAllocator getSubAlloc()
{
return subAlloc;
}
private void restartModelRare()
{
Arrays.fill(charMask, 0);
subAlloc.initSubAllocator();
initRL = -(maxOrder < 12 ? maxOrder : 12) - 1;
int addr = subAlloc.allocContext();
minContext.setAddress(addr);
maxContext.setAddress(addr);
minContext.setSuffix(0);
orderFall = maxOrder;
minContext.setNumStats(256);
minContext.getFreqData().setSummFreq(minContext.getNumStats()+1);
addr = subAlloc.allocUnits(256 / 2);
foundState.setAddress(addr);
minContext.getFreqData().setStats(addr);
State state = new State(subAlloc.getHeap());
addr = minContext.getFreqData().getStats();
runLength = initRL;
prevSuccess = 0;
for (int i = 0; i < 256; i++) {
state.setAddress(addr + i * State.size);
state.setSymbol(i);
state.setFreq(1);
state.setSuccessor(0);
}
for (int i = 0; i < 128; i++) {
for (int k = 0; k < 8; k++) {
for (int m = 0; m < 64; m += 8) {
binSumm[i][k + m] = BIN_SCALE - InitBinEsc[k] / (i + 2);
}
}
}
for (int i = 0; i < 25; i++) {
for (int k = 0; k < 16; k++) {
SEE2Cont[i][k].init(5 * i + 10);
}
}
}
private void startModelRare(int MaxOrder)
{
int i, k, m, Step;
escCount = 1;
this.maxOrder = MaxOrder;
restartModelRare();
// Bug Fixed
NS2BSIndx[0] = 0;
NS2BSIndx[1] = 2;
for (int j = 0; j < 9; j++) {
NS2BSIndx[2 + j] = 4;
}
for (int j = 0; j < 256 - 11; j++) {
NS2BSIndx[11 + j] = 6;
}
for (i = 0; i < 3; i++) {
NS2Indx[i] = i;
}
for (m = i, k = 1, Step = 1; i < 256; i++) {
NS2Indx[i] = m;
if ((--k) == 0) {
k = ++Step;
m++;
}
}
for (int j = 0; j < 0x40; j++) {
HB2Flag[j] = 0;
}
for (int j = 0; j < 0x100 - 0x40; j++) {
HB2Flag[0x40 + j] = 0x08;
}
dummySEE2Cont.setShift(PERIOD_BITS);
}
private void clearMask()
{
escCount = 1;
Arrays.fill(charMask, 0);
}
public boolean decodeInit(Unpack unpackRead, int escChar/* ref */)
throws IOException, RarException
{
int MaxOrder = unpackRead.getChar() & 0xff;
boolean reset = ((MaxOrder & 0x20) != 0);
int MaxMB = 0;
if (reset) {
MaxMB = unpackRead.getChar();
} else {
if (subAlloc.GetAllocatedMemory() == 0) {
return (false);
}
}
if ((MaxOrder & 0x40) != 0) {
escChar = unpackRead.getChar();
unpackRead.setPpmEscChar(escChar);
}
coder.initDecoder(unpackRead);
if (reset) {
MaxOrder = (MaxOrder & 0x1f) + 1;
if (MaxOrder > 16) {
MaxOrder = 16 + (MaxOrder - 16) * 3;
}
if (MaxOrder == 1) {
subAlloc.stopSubAllocator();
return (false);
}
subAlloc.startSubAllocator(MaxMB + 1);
minContext = new PPMContext(getHeap());
medContext = new PPMContext(getHeap());
maxContext = new PPMContext(getHeap());
foundState = new State(getHeap());
dummySEE2Cont = new SEE2Context();
for (int i = 0; i < 25; i++) {
for (int j = 0; j < 16; j++) {
SEE2Cont[i][j] = new SEE2Context();
}
}
startModelRare(MaxOrder);
}
return (minContext.getAddress() != 0);
}
public int decodeChar() throws IOException, RarException
{
// Debug
//subAlloc.dumpHeap();
if (minContext.getAddress() <= subAlloc.getPText()
|| minContext.getAddress() > subAlloc.getHeapEnd()) {
return (-1);
}
if (minContext.getNumStats() != 1) {
if (minContext.getFreqData().getStats() <= subAlloc.getPText()
|| minContext.getFreqData().getStats() > subAlloc.getHeapEnd()) {
return (-1);
}
if (!minContext.decodeSymbol1(this)) {
return (-1);
}
} else {
minContext.decodeBinSymbol(this);
}
coder.decode();
while (foundState.getAddress() == 0) {
coder.ariDecNormalize();
do {
orderFall++;
minContext.setAddress(minContext.getSuffix());// =MinContext->Suffix;
if (minContext.getAddress() <= subAlloc.getPText()
|| minContext.getAddress() > subAlloc.getHeapEnd()) {
return (-1);
}
} while (minContext.getNumStats() == numMasked);
if (!minContext.decodeSymbol2(this)) {
return (-1);
}
coder.decode();
}
int Symbol = foundState.getSymbol();
if ((orderFall == 0) && foundState.getSuccessor() > subAlloc.getPText()) {
// MinContext=MaxContext=FoundState->Successor;
int addr = foundState.getSuccessor();
minContext.setAddress(addr);
maxContext.setAddress(addr);
} else {
updateModel();
//this.foundState.setAddress(foundState.getAddress());//TODO just 4 debugging
if (escCount == 0) {
clearMask();
}
}
coder.ariDecNormalize();// ARI_DEC_NORMALIZE(Coder.code,Coder.low,Coder.range,Coder.UnpackRead);
return (Symbol);
}
public SEE2Context[][] getSEE2Cont()
{
return SEE2Cont;
}
public SEE2Context getDummySEE2Cont()
{
return dummySEE2Cont;
}
public int getInitRL()
{
return initRL;
}
public void setEscCount(int escCount)
{
this.escCount = escCount&0xff;
}
public int getEscCount()
{
return escCount;
}
public void incEscCount(int dEscCount) {
setEscCount(getEscCount() + dEscCount);
}
public int[] getCharMask()
{
return charMask;
}
public int getNumMasked()
{
return numMasked;
}
public void setNumMasked(int numMasked)
{
this.numMasked = numMasked;
}
public void setPrevSuccess(int prevSuccess)
{
this.prevSuccess = prevSuccess&0xff;
}
public int getInitEsc()
{
return initEsc;
}
public void setInitEsc(int initEsc)
{
this.initEsc = initEsc;
}
public void setRunLength(int runLength)
{
this.runLength = runLength;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -