mirror of
https://github.com/claunia/SabreTools.git
synced 2025-12-16 19:14:27 +00:00
Blind update of zip code to newest RVWorld version
This commit is contained in:
75
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/H/FreqData.cs
vendored
Normal file
75
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/H/FreqData.cs
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
using System.Text;
|
||||
|
||||
namespace Compress.SevenZip.Compress.PPmd.H
|
||||
{
|
||||
internal class FreqData : Pointer
|
||||
{
|
||||
internal const int Size = 6;
|
||||
|
||||
// struct FreqData
|
||||
// {
|
||||
// ushort SummFreq;
|
||||
// STATE _PACK_ATTR * Stats;
|
||||
// };
|
||||
|
||||
internal FreqData(byte[] Memory)
|
||||
: base(Memory)
|
||||
{
|
||||
}
|
||||
|
||||
internal int SummFreq
|
||||
{
|
||||
get
|
||||
{
|
||||
return Utility.readShortLittleEndian(Memory, Address) & 0xffff;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
Utility.WriteLittleEndian(Memory, Address, (short)value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal FreqData Initialize(byte[] mem)
|
||||
{
|
||||
return base.Initialize<FreqData>(mem);
|
||||
}
|
||||
|
||||
internal void IncrementSummFreq(int dSummFreq)
|
||||
{
|
||||
Utility.incShortLittleEndian(Memory, Address, (short)dSummFreq);
|
||||
}
|
||||
|
||||
internal int GetStats()
|
||||
{
|
||||
return Utility.readIntLittleEndian(Memory, Address + 2);
|
||||
}
|
||||
|
||||
internal virtual void SetStats(State state)
|
||||
{
|
||||
SetStats(state.Address);
|
||||
}
|
||||
|
||||
internal void SetStats(int state)
|
||||
{
|
||||
Utility.WriteLittleEndian(Memory, Address + 2, state);
|
||||
}
|
||||
|
||||
public override System.String ToString()
|
||||
{
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buffer.Append("FreqData[");
|
||||
buffer.Append("\n Address=");
|
||||
buffer.Append(Address);
|
||||
buffer.Append("\n size=");
|
||||
buffer.Append(Size);
|
||||
buffer.Append("\n summFreq=");
|
||||
buffer.Append(SummFreq);
|
||||
buffer.Append("\n stats=");
|
||||
buffer.Append(GetStats());
|
||||
buffer.Append("\n]");
|
||||
return buffer.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
945
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/H/ModelPPM.cs
vendored
Normal file
945
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/H/ModelPPM.cs
vendored
Normal file
@@ -0,0 +1,945 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Decoder = Compress.SevenZip.Compress.RangeCoder.Decoder;
|
||||
|
||||
namespace Compress.SevenZip.Compress.PPmd.H
|
||||
{
|
||||
internal class ModelPPM
|
||||
{
|
||||
private void InitBlock()
|
||||
{
|
||||
for (int i = 0; i < 25; i++)
|
||||
{
|
||||
SEE2Cont[i] = new SEE2Context[16];
|
||||
}
|
||||
for (int i2 = 0; i2 < 128; i2++)
|
||||
{
|
||||
binSumm[i2] = new int[64];
|
||||
}
|
||||
}
|
||||
public SubAllocator SubAlloc
|
||||
{
|
||||
get
|
||||
{
|
||||
return subAlloc;
|
||||
}
|
||||
|
||||
}
|
||||
virtual public SEE2Context DummySEE2Cont
|
||||
{
|
||||
get
|
||||
{
|
||||
return dummySEE2Cont;
|
||||
}
|
||||
|
||||
}
|
||||
virtual public int InitRL
|
||||
{
|
||||
get
|
||||
{
|
||||
return initRL;
|
||||
}
|
||||
|
||||
}
|
||||
virtual public int EscCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return escCount;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.escCount = value & 0xff;
|
||||
}
|
||||
|
||||
}
|
||||
virtual public int[] CharMask
|
||||
{
|
||||
get
|
||||
{
|
||||
return charMask;
|
||||
}
|
||||
|
||||
}
|
||||
virtual public int NumMasked
|
||||
{
|
||||
get
|
||||
{
|
||||
return numMasked;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.numMasked = value;
|
||||
}
|
||||
|
||||
}
|
||||
virtual public int PrevSuccess
|
||||
{
|
||||
get
|
||||
{
|
||||
return prevSuccess;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.prevSuccess = value & 0xff;
|
||||
}
|
||||
|
||||
}
|
||||
virtual public int InitEsc
|
||||
{
|
||||
get
|
||||
{
|
||||
return initEsc;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.initEsc = value;
|
||||
}
|
||||
|
||||
}
|
||||
virtual public int RunLength
|
||||
{
|
||||
get
|
||||
{
|
||||
return runLength;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.runLength = value;
|
||||
}
|
||||
|
||||
}
|
||||
virtual public int HiBitsFlag
|
||||
{
|
||||
get
|
||||
{
|
||||
return hiBitsFlag;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.hiBitsFlag = value & 0xff;
|
||||
}
|
||||
|
||||
}
|
||||
virtual public int[][] BinSumm
|
||||
{
|
||||
get
|
||||
{
|
||||
return binSumm;
|
||||
}
|
||||
|
||||
}
|
||||
internal RangeCoder Coder
|
||||
{
|
||||
get
|
||||
{
|
||||
return coder;
|
||||
}
|
||||
|
||||
}
|
||||
internal State FoundState
|
||||
{
|
||||
get
|
||||
{
|
||||
return foundState;
|
||||
}
|
||||
|
||||
}
|
||||
virtual public byte[] Heap
|
||||
{
|
||||
get
|
||||
{
|
||||
return subAlloc.Heap;
|
||||
}
|
||||
|
||||
}
|
||||
virtual public int OrderFall
|
||||
{
|
||||
get
|
||||
{
|
||||
return orderFall;
|
||||
}
|
||||
|
||||
}
|
||||
public const int MAX_O = 64; /* maximum allowed model order */
|
||||
|
||||
public const int INT_BITS = 7;
|
||||
|
||||
public const int PERIOD_BITS = 7;
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'TOT_BITS '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly int TOT_BITS = INT_BITS + PERIOD_BITS;
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'INTERVAL '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly int INTERVAL = 1 << INT_BITS;
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'BIN_SCALE '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly int BIN_SCALE = 1 << TOT_BITS;
|
||||
|
||||
public const int MAX_FREQ = 124;
|
||||
|
||||
private SEE2Context[][] SEE2Cont = new SEE2Context[25][];
|
||||
|
||||
private SEE2Context dummySEE2Cont;
|
||||
|
||||
private PPMContext minContext; //medContext
|
||||
|
||||
private PPMContext 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][]; // binary SEE-contexts
|
||||
|
||||
private RangeCoder coder;
|
||||
|
||||
private SubAllocator subAlloc = new SubAllocator();
|
||||
|
||||
private static int[] InitBinEsc = new int[] { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051 };
|
||||
|
||||
// Temp fields
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'tempState1 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private State tempState1 = new State(null);
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'tempState2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private State tempState2 = new State(null);
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'tempState3 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private State tempState3 = new State(null);
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'tempState4 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private State tempState4 = new State(null);
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'tempStateRef1 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private StateRef tempStateRef1 = new StateRef();
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'tempStateRef2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private StateRef tempStateRef2 = new StateRef();
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'tempPPMContext1 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private PPMContext tempPPMContext1 = new PPMContext(null);
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'tempPPMContext2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private PPMContext tempPPMContext2 = new PPMContext(null);
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'tempPPMContext3 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private PPMContext tempPPMContext3 = new PPMContext(null);
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'tempPPMContext4 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private PPMContext tempPPMContext4 = new PPMContext(null);
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'ps '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private int[] ps = new int[MAX_O];
|
||||
|
||||
public ModelPPM()
|
||||
{
|
||||
InitBlock();
|
||||
minContext = null;
|
||||
maxContext = null;
|
||||
//medContext = null;
|
||||
}
|
||||
|
||||
private void restartModelRare()
|
||||
{
|
||||
Utility.Fill(charMask, 0);
|
||||
subAlloc.initSubAllocator();
|
||||
initRL = -(maxOrder < 12 ? maxOrder : 12) - 1;
|
||||
int addr = subAlloc.allocContext();
|
||||
minContext.Address = addr;
|
||||
maxContext.Address = addr;
|
||||
minContext.setSuffix(0);
|
||||
orderFall = maxOrder;
|
||||
minContext.NumStats = 256;
|
||||
minContext.FreqData.SummFreq = minContext.NumStats + 1;
|
||||
|
||||
addr = subAlloc.allocUnits(256 / 2);
|
||||
foundState.Address = addr;
|
||||
minContext.FreqData.SetStats(addr);
|
||||
|
||||
State state = new State(subAlloc.Heap);
|
||||
addr = minContext.FreqData.GetStats();
|
||||
runLength = initRL;
|
||||
prevSuccess = 0;
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
state.Address = addr + i * State.Size;
|
||||
state.Symbol = i;
|
||||
state.Freq = 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].Initialize(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.Shift = PERIOD_BITS;
|
||||
}
|
||||
|
||||
private void clearMask()
|
||||
{
|
||||
escCount = 1;
|
||||
Utility.Fill(charMask, 0);
|
||||
}
|
||||
|
||||
|
||||
public virtual int decodeChar()
|
||||
{
|
||||
// Debug
|
||||
//subAlloc.dumpHeap();
|
||||
|
||||
if (minContext.Address <= subAlloc.PText || minContext.Address > subAlloc.HeapEnd)
|
||||
{
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (minContext.NumStats != 1)
|
||||
{
|
||||
if (minContext.FreqData.GetStats() <= subAlloc.PText || minContext.FreqData.GetStats() > subAlloc.HeapEnd)
|
||||
{
|
||||
return (-1);
|
||||
}
|
||||
if (!minContext.decodeSymbol1(this))
|
||||
{
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
minContext.decodeBinSymbol(this);
|
||||
}
|
||||
coder.Decode();
|
||||
while (foundState.Address == 0)
|
||||
{
|
||||
coder.AriDecNormalize();
|
||||
do
|
||||
{
|
||||
orderFall++;
|
||||
minContext.Address = minContext.getSuffix(); // =MinContext->Suffix;
|
||||
if (minContext.Address <= subAlloc.PText || minContext.Address > subAlloc.HeapEnd)
|
||||
{
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
while (minContext.NumStats == numMasked);
|
||||
if (!minContext.decodeSymbol2(this))
|
||||
{
|
||||
return (-1);
|
||||
}
|
||||
coder.Decode();
|
||||
}
|
||||
int Symbol = foundState.Symbol;
|
||||
if ((orderFall == 0) && foundState.GetSuccessor() > subAlloc.PText)
|
||||
{
|
||||
// MinContext=MaxContext=FoundState->Successor;
|
||||
int addr = foundState.GetSuccessor();
|
||||
minContext.Address = addr;
|
||||
maxContext.Address = addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
updateModel();
|
||||
//this.foundState.Address=foundState.Address);//TODO just 4 debugging
|
||||
if (escCount == 0)
|
||||
{
|
||||
clearMask();
|
||||
}
|
||||
}
|
||||
coder.AriDecNormalize(); // ARI_DEC_NORMALIZE(Coder.code,Coder.low,Coder.range,Coder.UnpackRead);
|
||||
return (Symbol);
|
||||
}
|
||||
|
||||
public virtual SEE2Context[][] getSEE2Cont()
|
||||
{
|
||||
return SEE2Cont;
|
||||
}
|
||||
|
||||
public virtual void incEscCount(int dEscCount)
|
||||
{
|
||||
EscCount = EscCount + dEscCount;
|
||||
}
|
||||
|
||||
public virtual void incRunLength(int dRunLength)
|
||||
{
|
||||
RunLength = RunLength + dRunLength;
|
||||
}
|
||||
|
||||
public virtual int[] getHB2Flag()
|
||||
{
|
||||
return HB2Flag;
|
||||
}
|
||||
|
||||
public virtual int[] getNS2BSIndx()
|
||||
{
|
||||
return NS2BSIndx;
|
||||
}
|
||||
|
||||
public virtual int[] getNS2Indx()
|
||||
{
|
||||
return NS2Indx;
|
||||
}
|
||||
|
||||
private int createSuccessors(bool Skip, State p1)
|
||||
{
|
||||
//State upState = tempState1.Initialize(null);
|
||||
StateRef upState = tempStateRef2;
|
||||
State tempState = tempState1.Initialize(Heap);
|
||||
|
||||
// PPM_CONTEXT* pc=MinContext, * UpBranch=FoundState->Successor;
|
||||
PPMContext pc = tempPPMContext1.Initialize(Heap);
|
||||
pc.Address = minContext.Address;
|
||||
PPMContext upBranch = tempPPMContext2.Initialize(Heap);
|
||||
upBranch.Address = foundState.GetSuccessor();
|
||||
|
||||
// STATE * p, * ps[MAX_O], ** pps=ps;
|
||||
State p = tempState2.Initialize(Heap);
|
||||
int pps = 0;
|
||||
|
||||
bool noLoop = false;
|
||||
|
||||
if (!Skip)
|
||||
{
|
||||
ps[pps++] = foundState.Address; // *pps++ = FoundState;
|
||||
if (pc.getSuffix() == 0)
|
||||
{
|
||||
noLoop = true;
|
||||
}
|
||||
}
|
||||
if (!noLoop)
|
||||
{
|
||||
bool loopEntry = false;
|
||||
if (p1.Address != 0)
|
||||
{
|
||||
p.Address = p1.Address;
|
||||
pc.Address = pc.getSuffix(); // =pc->Suffix;
|
||||
loopEntry = true;
|
||||
}
|
||||
do
|
||||
{
|
||||
if (!loopEntry)
|
||||
{
|
||||
pc.Address = pc.getSuffix(); // pc=pc->Suffix;
|
||||
if (pc.NumStats != 1)
|
||||
{
|
||||
p.Address = pc.FreqData.GetStats(); // p=pc->U.Stats
|
||||
if (p.Symbol != foundState.Symbol)
|
||||
{
|
||||
do
|
||||
{
|
||||
p.IncrementAddress();
|
||||
}
|
||||
while (p.Symbol != foundState.Symbol);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
p.Address = pc.getOneState().Address; // p=&(pc->OneState);
|
||||
}
|
||||
} // LOOP_ENTRY:
|
||||
loopEntry = false;
|
||||
if (p.GetSuccessor() != upBranch.Address)
|
||||
{
|
||||
pc.Address = p.GetSuccessor(); // =p->Successor;
|
||||
break;
|
||||
}
|
||||
ps[pps++] = p.Address;
|
||||
}
|
||||
while (pc.getSuffix() != 0);
|
||||
} // NO_LOOP:
|
||||
if (pps == 0)
|
||||
{
|
||||
return pc.Address;
|
||||
}
|
||||
upState.Symbol = Heap[upBranch.Address]; // UpState.Symbol=*(byte*)
|
||||
// UpBranch;
|
||||
// UpState.Successor=(PPM_CONTEXT*) (((byte*) UpBranch)+1);
|
||||
upState.SetSuccessor(upBranch.Address + 1); //TODO check if +1 necessary
|
||||
if (pc.NumStats != 1)
|
||||
{
|
||||
if (pc.Address <= subAlloc.PText)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
p.Address = pc.FreqData.GetStats();
|
||||
if (p.Symbol != upState.Symbol)
|
||||
{
|
||||
do
|
||||
{
|
||||
p.IncrementAddress();
|
||||
}
|
||||
while (p.Symbol != upState.Symbol);
|
||||
}
|
||||
int cf = p.Freq - 1;
|
||||
int s0 = pc.FreqData.SummFreq - pc.NumStats - cf;
|
||||
// UpState.Freq=1+((2*cf <= s0)?(5*cf > s0):((2*cf+3*s0-1)/(2*s0)));
|
||||
upState.Freq = 1 + ((2 * cf <= s0) ? (5 * cf > s0 ? 1 : 0) : ((2 * cf + 3 * s0 - 1) / (2 * s0)));
|
||||
}
|
||||
else
|
||||
{
|
||||
upState.Freq = pc.getOneState().Freq; // UpState.Freq=pc->OneState.Freq;
|
||||
}
|
||||
do
|
||||
{
|
||||
// pc = pc->createChild(this,*--pps,UpState);
|
||||
tempState.Address = ps[--pps];
|
||||
pc.Address = pc.createChild(this, tempState, upState);
|
||||
if (pc.Address == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
while (pps != 0);
|
||||
return pc.Address;
|
||||
}
|
||||
|
||||
private void updateModelRestart()
|
||||
{
|
||||
restartModelRare();
|
||||
escCount = 0;
|
||||
}
|
||||
|
||||
private void updateModel()
|
||||
{
|
||||
//System.out.println("ModelPPM.updateModel()");
|
||||
// STATE fs = *FoundState, *p = NULL;
|
||||
StateRef fs = tempStateRef1;
|
||||
fs.Values = foundState;
|
||||
State p = tempState3.Initialize(Heap);
|
||||
State tempState = tempState4.Initialize(Heap);
|
||||
|
||||
PPMContext pc = tempPPMContext3.Initialize(Heap);
|
||||
PPMContext successor = tempPPMContext4.Initialize(Heap);
|
||||
|
||||
int ns1, ns, cf, sf, s0;
|
||||
pc.Address = minContext.getSuffix();
|
||||
if (fs.Freq < MAX_FREQ / 4 && pc.Address != 0)
|
||||
{
|
||||
if (pc.NumStats != 1)
|
||||
{
|
||||
p.Address = pc.FreqData.GetStats();
|
||||
if (p.Symbol != fs.Symbol)
|
||||
{
|
||||
do
|
||||
{
|
||||
p.IncrementAddress();
|
||||
}
|
||||
while (p.Symbol != fs.Symbol);
|
||||
tempState.Address = p.Address - State.Size;
|
||||
if (p.Freq >= tempState.Freq)
|
||||
{
|
||||
State.PPMDSwap(p, tempState);
|
||||
p.DecrementAddress();
|
||||
}
|
||||
}
|
||||
if (p.Freq < MAX_FREQ - 9)
|
||||
{
|
||||
p.IncrementFreq(2);
|
||||
pc.FreqData.IncrementSummFreq(2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
p.Address = pc.getOneState().Address;
|
||||
if (p.Freq < 32)
|
||||
{
|
||||
p.IncrementFreq(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (orderFall == 0)
|
||||
{
|
||||
foundState.SetSuccessor(createSuccessors(true, p));
|
||||
minContext.Address = foundState.GetSuccessor();
|
||||
maxContext.Address = foundState.GetSuccessor();
|
||||
if (minContext.Address == 0)
|
||||
{
|
||||
updateModelRestart();
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
subAlloc.Heap[subAlloc.PText] = (byte)fs.Symbol;
|
||||
subAlloc.incPText();
|
||||
successor.Address = subAlloc.PText;
|
||||
if (subAlloc.PText >= subAlloc.FakeUnitsStart)
|
||||
{
|
||||
updateModelRestart();
|
||||
return;
|
||||
}
|
||||
// // Debug
|
||||
// subAlloc.dumpHeap();
|
||||
if (fs.GetSuccessor() != 0)
|
||||
{
|
||||
if (fs.GetSuccessor() <= subAlloc.PText)
|
||||
{
|
||||
fs.SetSuccessor(createSuccessors(false, p));
|
||||
if (fs.GetSuccessor() == 0)
|
||||
{
|
||||
updateModelRestart();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (--orderFall == 0)
|
||||
{
|
||||
successor.Address = fs.GetSuccessor();
|
||||
if (maxContext.Address != minContext.Address)
|
||||
{
|
||||
subAlloc.decPText(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foundState.SetSuccessor(successor.Address);
|
||||
fs.SetSuccessor(minContext);
|
||||
}
|
||||
// // Debug
|
||||
// subAlloc.dumpHeap();
|
||||
ns = minContext.NumStats;
|
||||
s0 = minContext.FreqData.SummFreq - (ns) - (fs.Freq - 1);
|
||||
for (pc.Address = maxContext.Address; pc.Address != minContext.Address; pc.Address = pc.getSuffix())
|
||||
{
|
||||
if ((ns1 = pc.NumStats) != 1)
|
||||
{
|
||||
if ((ns1 & 1) == 0)
|
||||
{
|
||||
//System.out.println(ns1);
|
||||
pc.FreqData.SetStats(subAlloc.expandUnits(pc.FreqData.GetStats(), Utility.URShift(ns1, 1)));
|
||||
if (pc.FreqData.GetStats() == 0)
|
||||
{
|
||||
updateModelRestart();
|
||||
return;
|
||||
}
|
||||
}
|
||||
// bug fixed
|
||||
// int sum = ((2 * ns1 < ns) ? 1 : 0) +
|
||||
// 2 * ((4 * ((ns1 <= ns) ? 1 : 0)) & ((pc.getFreqData()
|
||||
// .getSummFreq() <= 8 * ns1) ? 1 : 0));
|
||||
int sum = ((2 * ns1 < ns) ? 1 : 0) + 2 * (((4 * ns1 <= ns) ? 1 : 0) & ((pc.FreqData.SummFreq <= 8 * ns1) ? 1 : 0));
|
||||
pc.FreqData.IncrementSummFreq(sum);
|
||||
}
|
||||
else
|
||||
{
|
||||
p.Address = subAlloc.allocUnits(1);
|
||||
if (p.Address == 0)
|
||||
{
|
||||
updateModelRestart();
|
||||
return;
|
||||
}
|
||||
p.SetValues(pc.getOneState());
|
||||
pc.FreqData.SetStats(p);
|
||||
if (p.Freq < MAX_FREQ / 4 - 1)
|
||||
{
|
||||
p.IncrementFreq(p.Freq);
|
||||
}
|
||||
else
|
||||
{
|
||||
p.Freq = MAX_FREQ - 4;
|
||||
}
|
||||
pc.FreqData.SummFreq = (p.Freq + initEsc + (ns > 3 ? 1 : 0));
|
||||
}
|
||||
cf = 2 * fs.Freq * (pc.FreqData.SummFreq + 6);
|
||||
sf = s0 + pc.FreqData.SummFreq;
|
||||
if (cf < 6 * sf)
|
||||
{
|
||||
cf = 1 + (cf > sf ? 1 : 0) + (cf >= 4 * sf ? 1 : 0);
|
||||
pc.FreqData.IncrementSummFreq(3);
|
||||
}
|
||||
else
|
||||
{
|
||||
cf = 4 + (cf >= 9 * sf ? 1 : 0) + (cf >= 12 * sf ? 1 : 0) + (cf >= 15 * sf ? 1 : 0);
|
||||
pc.FreqData.IncrementSummFreq(cf);
|
||||
}
|
||||
p.Address = pc.FreqData.GetStats() + ns1 * State.Size;
|
||||
p.SetSuccessor(successor);
|
||||
p.Symbol = fs.Symbol;
|
||||
p.Freq = cf;
|
||||
pc.NumStats = ++ns1;
|
||||
}
|
||||
|
||||
int address = fs.GetSuccessor();
|
||||
maxContext.Address = address;
|
||||
minContext.Address = address;
|
||||
//TODO-----debug
|
||||
// int pos = minContext.getFreqData().getStats();
|
||||
// State a = new State(getHeap());
|
||||
// a.Address=pos);
|
||||
// pos+=State.size;
|
||||
// a.Address=pos);
|
||||
//--dbg end
|
||||
return;
|
||||
}
|
||||
|
||||
// Debug
|
||||
public override System.String ToString()
|
||||
{
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buffer.Append("ModelPPM[");
|
||||
buffer.Append("\n numMasked=");
|
||||
buffer.Append(numMasked);
|
||||
buffer.Append("\n initEsc=");
|
||||
buffer.Append(initEsc);
|
||||
buffer.Append("\n orderFall=");
|
||||
buffer.Append(orderFall);
|
||||
buffer.Append("\n maxOrder=");
|
||||
buffer.Append(maxOrder);
|
||||
buffer.Append("\n runLength=");
|
||||
buffer.Append(runLength);
|
||||
buffer.Append("\n initRL=");
|
||||
buffer.Append(initRL);
|
||||
buffer.Append("\n escCount=");
|
||||
buffer.Append(escCount);
|
||||
buffer.Append("\n prevSuccess=");
|
||||
buffer.Append(prevSuccess);
|
||||
buffer.Append("\n foundState=");
|
||||
buffer.Append(foundState);
|
||||
buffer.Append("\n coder=");
|
||||
buffer.Append(coder);
|
||||
buffer.Append("\n subAlloc=");
|
||||
buffer.Append(subAlloc);
|
||||
buffer.Append("\n]");
|
||||
return buffer.ToString();
|
||||
}
|
||||
|
||||
// Debug
|
||||
// public void dumpHeap() {
|
||||
// subAlloc.dumpHeap();
|
||||
// }
|
||||
|
||||
internal bool decodeInit(Stream stream, int maxOrder, int maxMemory)
|
||||
{
|
||||
if (stream != null)
|
||||
coder = new RangeCoder(stream);
|
||||
|
||||
if (maxOrder == 1)
|
||||
{
|
||||
subAlloc.stopSubAllocator();
|
||||
return (false);
|
||||
}
|
||||
subAlloc.startSubAllocator(maxMemory);
|
||||
minContext = new PPMContext(Heap);
|
||||
//medContext = new PPMContext(Heap);
|
||||
maxContext = new PPMContext(Heap);
|
||||
foundState = new State(Heap);
|
||||
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.Address != 0);
|
||||
}
|
||||
|
||||
internal void nextContext()
|
||||
{
|
||||
int addr = foundState.GetSuccessor();
|
||||
if (orderFall == 0 && addr > subAlloc.PText)
|
||||
{
|
||||
minContext.Address = addr;
|
||||
maxContext.Address = addr;
|
||||
}
|
||||
else
|
||||
updateModel();
|
||||
}
|
||||
|
||||
public int decodeChar(Decoder decoder)
|
||||
{
|
||||
if (minContext.NumStats != 1)
|
||||
{
|
||||
State s = tempState1.Initialize(Heap);
|
||||
s.Address = minContext.FreqData.GetStats();
|
||||
int i;
|
||||
int count, hiCnt;
|
||||
if ((count = (int)decoder.GetThreshold((uint)minContext.FreqData.SummFreq)) < (hiCnt = s.Freq))
|
||||
{
|
||||
byte symbol;
|
||||
decoder.Decode(0, (uint)s.Freq);
|
||||
symbol = (byte)s.Symbol;
|
||||
minContext.update1_0(this, s.Address);
|
||||
nextContext();
|
||||
return symbol;
|
||||
}
|
||||
prevSuccess = 0;
|
||||
i = minContext.NumStats - 1;
|
||||
do
|
||||
{
|
||||
s.IncrementAddress();
|
||||
if ((hiCnt += s.Freq) > count)
|
||||
{
|
||||
byte symbol;
|
||||
decoder.Decode((uint)(hiCnt - s.Freq), (uint)s.Freq);
|
||||
symbol = (byte)s.Symbol;
|
||||
minContext.update1(this, s.Address);
|
||||
nextContext();
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
while (--i > 0);
|
||||
if (count >= minContext.FreqData.SummFreq)
|
||||
return -2;
|
||||
hiBitsFlag = HB2Flag[foundState.Symbol];
|
||||
decoder.Decode((uint)hiCnt, (uint)(minContext.FreqData.SummFreq - hiCnt));
|
||||
for (i = 0; i < 256; i++)
|
||||
charMask[i] = -1;
|
||||
charMask[s.Symbol] = 0;
|
||||
i = minContext.NumStats - 1;
|
||||
do
|
||||
{
|
||||
s.DecrementAddress();
|
||||
charMask[s.Symbol] = 0;
|
||||
}
|
||||
while (--i > 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
State rs = tempState1.Initialize(Heap);
|
||||
rs.Address = minContext.getOneState().Address;
|
||||
hiBitsFlag = getHB2Flag()[foundState.Symbol];
|
||||
int off1 = rs.Freq - 1;
|
||||
int off2 = minContext.getArrayIndex(this, rs);
|
||||
int bs = binSumm[off1][off2];
|
||||
if (decoder.DecodeBit((uint)bs, 14) == 0)
|
||||
{
|
||||
byte symbol;
|
||||
binSumm[off1][off2] = (bs + INTERVAL - minContext.getMean(bs, PERIOD_BITS, 2)) & 0xFFFF;
|
||||
foundState.Address = rs.Address;
|
||||
symbol = (byte)rs.Symbol;
|
||||
rs.IncrementFreq((rs.Freq < 128) ? 1 : 0);
|
||||
prevSuccess = 1;
|
||||
incRunLength(1);
|
||||
nextContext();
|
||||
return symbol;
|
||||
}
|
||||
bs = (bs - minContext.getMean(bs, PERIOD_BITS, 2)) & 0xFFFF;
|
||||
binSumm[off1][off2] = bs;
|
||||
initEsc = PPMContext.ExpEscape[Utility.URShift(bs, 10)];
|
||||
int i;
|
||||
for (i = 0; i < 256; i++)
|
||||
charMask[i] = -1;
|
||||
charMask[rs.Symbol] = 0;
|
||||
prevSuccess = 0;
|
||||
}
|
||||
for (;;)
|
||||
{
|
||||
State s = tempState1.Initialize(Heap);
|
||||
int i;
|
||||
int freqSum, count, hiCnt;
|
||||
SEE2Context see;
|
||||
int num, numMasked = minContext.NumStats;
|
||||
do
|
||||
{
|
||||
orderFall++;
|
||||
minContext.Address = minContext.getSuffix();
|
||||
if (minContext.Address <= subAlloc.PText || minContext.Address > subAlloc.HeapEnd)
|
||||
return -1;
|
||||
}
|
||||
while (minContext.NumStats == numMasked);
|
||||
hiCnt = 0;
|
||||
s.Address = minContext.FreqData.GetStats();
|
||||
i = 0;
|
||||
num = minContext.NumStats - numMasked;
|
||||
do
|
||||
{
|
||||
int k = charMask[s.Symbol];
|
||||
hiCnt += s.Freq & k;
|
||||
minContext.ps[i] = s.Address;
|
||||
s.IncrementAddress();
|
||||
i -= k;
|
||||
}
|
||||
while (i != num);
|
||||
|
||||
see = minContext.makeEscFreq(this, numMasked, out freqSum);
|
||||
freqSum += hiCnt;
|
||||
count = (int)decoder.GetThreshold((uint)freqSum);
|
||||
|
||||
if (count < hiCnt)
|
||||
{
|
||||
byte symbol;
|
||||
State ps = tempState2.Initialize(Heap);
|
||||
for (hiCnt = 0, i = 0, ps.Address = minContext.ps[i]; (hiCnt += ps.Freq) <= count; i++, ps.Address = minContext.ps[i]);
|
||||
s.Address = ps.Address;
|
||||
decoder.Decode((uint)(hiCnt - s.Freq), (uint)s.Freq);
|
||||
see.update();
|
||||
symbol = (byte)s.Symbol;
|
||||
minContext.update2(this, s.Address);
|
||||
updateModel();
|
||||
return symbol;
|
||||
}
|
||||
if (count >= freqSum)
|
||||
return -2;
|
||||
decoder.Decode((uint)hiCnt, (uint)(freqSum - hiCnt));
|
||||
see.Summ = see.Summ + freqSum;
|
||||
do
|
||||
{
|
||||
s.Address = minContext.ps[--i];
|
||||
charMask[s.Symbol] = 0;
|
||||
}
|
||||
while (i != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
563
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/H/PPMContext.cs
vendored
Normal file
563
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/H/PPMContext.cs
vendored
Normal file
@@ -0,0 +1,563 @@
|
||||
using System.Text;
|
||||
|
||||
namespace Compress.SevenZip.Compress.PPmd.H
|
||||
{
|
||||
internal class PPMContext : Pointer
|
||||
{
|
||||
internal FreqData FreqData
|
||||
{
|
||||
get
|
||||
{
|
||||
return freqData;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.freqData.SummFreq = value.SummFreq;
|
||||
this.freqData.SetStats(value.GetStats());
|
||||
}
|
||||
|
||||
}
|
||||
virtual public int NumStats
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Memory != null)
|
||||
{
|
||||
numStats = Utility.readShortLittleEndian(Memory, Address) & 0xffff;
|
||||
}
|
||||
return numStats;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.numStats = value & 0xffff;
|
||||
if (Memory != null)
|
||||
{
|
||||
Utility.WriteLittleEndian(Memory, Address, (short)value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'unionSize '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
//UPGRADE_NOTE: The initialization of 'unionSize' was moved to static method 'SharpCompress.Unpack.PPM.PPMContext'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
|
||||
private static readonly int unionSize;
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'size '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly int size = 2 + unionSize + 4; // 12
|
||||
|
||||
// ushort NumStats;
|
||||
private int numStats; // determines if feqData or onstate is used
|
||||
|
||||
// (1==onestate)
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'freqData '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private FreqData freqData; // -\
|
||||
|
||||
// |-> union
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'oneState '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private State oneState; // -/
|
||||
|
||||
private int suffix; // pointer ppmcontext
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'ExpEscape'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly int[] ExpEscape = new int[] { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
|
||||
|
||||
// Temp fields
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'tempState1 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private State tempState1 = new State(null);
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'tempState2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private State tempState2 = new State(null);
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'tempState3 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private State tempState3 = new State(null);
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'tempState4 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private State tempState4 = new State(null);
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'tempState5 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private State tempState5 = new State(null);
|
||||
private PPMContext tempPPMContext = null;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'ps '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
internal int[] ps = new int[256];
|
||||
|
||||
public PPMContext(byte[] Memory)
|
||||
: base(Memory)
|
||||
{
|
||||
oneState = new State(Memory);
|
||||
freqData = new FreqData(Memory);
|
||||
}
|
||||
|
||||
internal PPMContext Initialize(byte[] mem)
|
||||
{
|
||||
oneState.Initialize(mem);
|
||||
freqData.Initialize(mem);
|
||||
return base.Initialize<PPMContext>(mem);
|
||||
}
|
||||
|
||||
internal State getOneState()
|
||||
{
|
||||
return oneState;
|
||||
}
|
||||
|
||||
internal void setOneState(StateRef oneState)
|
||||
{
|
||||
this.oneState.SetValues(oneState);
|
||||
}
|
||||
|
||||
internal int getSuffix()
|
||||
{
|
||||
if (Memory != null)
|
||||
{
|
||||
suffix = Utility.readIntLittleEndian(Memory, Address + 8);
|
||||
}
|
||||
return suffix;
|
||||
}
|
||||
|
||||
internal void setSuffix(PPMContext suffix)
|
||||
{
|
||||
setSuffix(suffix.Address);
|
||||
}
|
||||
|
||||
internal void setSuffix(int suffix)
|
||||
{
|
||||
this.suffix = suffix;
|
||||
if (Memory != null)
|
||||
{
|
||||
Utility.WriteLittleEndian(Memory, Address + 8, suffix);
|
||||
}
|
||||
}
|
||||
|
||||
internal override int Address
|
||||
{
|
||||
get
|
||||
{
|
||||
return base.Address;
|
||||
}
|
||||
set
|
||||
{
|
||||
base.Address = value;
|
||||
oneState.Address = value + 2;
|
||||
freqData.Address = value + 2;
|
||||
}
|
||||
}
|
||||
|
||||
private PPMContext getTempPPMContext(byte[] Memory)
|
||||
{
|
||||
if (tempPPMContext == null)
|
||||
{
|
||||
tempPPMContext = new PPMContext(null);
|
||||
}
|
||||
return tempPPMContext.Initialize(Memory);
|
||||
}
|
||||
|
||||
internal int createChild(ModelPPM model, State pStats, StateRef firstState)
|
||||
{
|
||||
PPMContext pc = getTempPPMContext(model.SubAlloc.Heap);
|
||||
pc.Address = model.SubAlloc.allocContext();
|
||||
if (pc != null)
|
||||
{
|
||||
pc.NumStats = 1;
|
||||
pc.setOneState(firstState);
|
||||
pc.setSuffix(this);
|
||||
pStats.SetSuccessor(pc);
|
||||
}
|
||||
return pc.Address;
|
||||
}
|
||||
|
||||
internal void rescale(ModelPPM model)
|
||||
{
|
||||
int OldNS = NumStats, i = NumStats - 1, Adder, EscFreq;
|
||||
// STATE* p1, * p;
|
||||
State p1 = new State(model.Heap);
|
||||
State p = new State(model.Heap);
|
||||
State temp = new State(model.Heap);
|
||||
|
||||
for (p.Address = model.FoundState.Address; p.Address != freqData.GetStats(); p.DecrementAddress())
|
||||
{
|
||||
temp.Address = p.Address - State.Size;
|
||||
State.PPMDSwap(p, temp);
|
||||
}
|
||||
temp.Address = freqData.GetStats();
|
||||
temp.IncrementFreq(4);
|
||||
freqData.IncrementSummFreq(4);
|
||||
EscFreq = freqData.SummFreq - p.Freq;
|
||||
Adder = (model.OrderFall != 0) ? 1 : 0;
|
||||
p.Freq = Utility.URShift((p.Freq + Adder), 1);
|
||||
freqData.SummFreq = p.Freq;
|
||||
do
|
||||
{
|
||||
p.IncrementAddress();
|
||||
EscFreq -= p.Freq;
|
||||
p.Freq = Utility.URShift((p.Freq + Adder), 1);
|
||||
freqData.IncrementSummFreq(p.Freq);
|
||||
temp.Address = p.Address - State.Size;
|
||||
if (p.Freq > temp.Freq)
|
||||
{
|
||||
p1.Address = p.Address;
|
||||
StateRef tmp = new StateRef();
|
||||
tmp.Values = p1;
|
||||
State temp2 = new State(model.Heap);
|
||||
State temp3 = new State(model.Heap);
|
||||
do
|
||||
{
|
||||
// p1[0]=p1[-1];
|
||||
temp2.Address = p1.Address - State.Size;
|
||||
p1.SetValues(temp2);
|
||||
p1.DecrementAddress();
|
||||
temp3.Address = p1.Address - State.Size;
|
||||
}
|
||||
while (p1.Address != freqData.GetStats() && tmp.Freq > temp3.Freq);
|
||||
p1.SetValues(tmp);
|
||||
}
|
||||
}
|
||||
while (--i != 0);
|
||||
if (p.Freq == 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
i++;
|
||||
p.DecrementAddress();
|
||||
}
|
||||
while (p.Freq == 0);
|
||||
EscFreq += i;
|
||||
NumStats = NumStats - i;
|
||||
if (NumStats == 1)
|
||||
{
|
||||
StateRef tmp = new StateRef();
|
||||
temp.Address = freqData.GetStats();
|
||||
tmp.Values = temp;
|
||||
// STATE tmp=*U.Stats;
|
||||
do
|
||||
{
|
||||
// tmp.Freq-=(tmp.Freq >> 1)
|
||||
tmp.DecrementFreq(Utility.URShift(tmp.Freq, 1));
|
||||
EscFreq = Utility.URShift(EscFreq, 1);
|
||||
}
|
||||
while (EscFreq > 1);
|
||||
model.SubAlloc.freeUnits(freqData.GetStats(), Utility.URShift((OldNS + 1), 1));
|
||||
oneState.SetValues(tmp);
|
||||
model.FoundState.Address = oneState.Address;
|
||||
return;
|
||||
}
|
||||
}
|
||||
EscFreq -= Utility.URShift(EscFreq, 1);
|
||||
freqData.IncrementSummFreq(EscFreq);
|
||||
int n0 = Utility.URShift((OldNS + 1), 1), n1 = Utility.URShift((NumStats + 1), 1);
|
||||
if (n0 != n1)
|
||||
{
|
||||
freqData.SetStats(model.SubAlloc.shrinkUnits(freqData.GetStats(), n0, n1));
|
||||
}
|
||||
model.FoundState.Address = freqData.GetStats();
|
||||
}
|
||||
|
||||
internal int getArrayIndex(ModelPPM Model, State rs)
|
||||
{
|
||||
PPMContext tempSuffix = getTempPPMContext(Model.SubAlloc.Heap);
|
||||
tempSuffix.Address = getSuffix();
|
||||
int ret = 0;
|
||||
ret += Model.PrevSuccess;
|
||||
ret += Model.getNS2BSIndx()[tempSuffix.NumStats - 1];
|
||||
ret += Model.HiBitsFlag + 2 * Model.getHB2Flag()[rs.Symbol];
|
||||
ret += ((Utility.URShift(Model.RunLength, 26)) & 0x20);
|
||||
return ret;
|
||||
}
|
||||
|
||||
internal int getMean(int summ, int shift, int round)
|
||||
{
|
||||
return (Utility.URShift((summ + (1 << (shift - round))), (shift)));
|
||||
}
|
||||
|
||||
internal void decodeBinSymbol(ModelPPM model)
|
||||
{
|
||||
State rs = tempState1.Initialize(model.Heap);
|
||||
rs.Address = oneState.Address; // State&
|
||||
model.HiBitsFlag = model.getHB2Flag()[model.FoundState.Symbol];
|
||||
int off1 = rs.Freq - 1;
|
||||
int off2 = getArrayIndex(model, rs);
|
||||
int bs = model.BinSumm[off1][off2];
|
||||
if (model.Coder.GetCurrentShiftCount(ModelPPM.TOT_BITS) < bs)
|
||||
{
|
||||
model.FoundState.Address = rs.Address;
|
||||
rs.IncrementFreq((rs.Freq < 128) ? 1 : 0);
|
||||
model.Coder.SubRange.LowCount = 0;
|
||||
model.Coder.SubRange.HighCount = bs;
|
||||
bs = ((bs + ModelPPM.INTERVAL - getMean(bs, ModelPPM.PERIOD_BITS, 2)) & 0xffff);
|
||||
model.BinSumm[off1][off2] = bs;
|
||||
model.PrevSuccess = 1;
|
||||
model.incRunLength(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
model.Coder.SubRange.LowCount = bs;
|
||||
bs = (bs - getMean(bs, ModelPPM.PERIOD_BITS, 2)) & 0xFFFF;
|
||||
model.BinSumm[off1][off2] = bs;
|
||||
model.Coder.SubRange.HighCount = ModelPPM.BIN_SCALE;
|
||||
model.InitEsc = ExpEscape[Utility.URShift(bs, 10)];
|
||||
model.NumMasked = 1;
|
||||
model.CharMask[rs.Symbol] = model.EscCount;
|
||||
model.PrevSuccess = 0;
|
||||
model.FoundState.Address = 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.Address;
|
||||
// int p2 = state2.Address;
|
||||
//
|
||||
// for (int i = 0; i < StatePtr.size; i++) {
|
||||
// byte temp = bytes[p1+i];
|
||||
// bytes[p1+i] = bytes[p2+i];
|
||||
// bytes[p2+i] = temp;
|
||||
// }
|
||||
// state1.Address=p1);
|
||||
// state2.Address=p2);
|
||||
// }
|
||||
|
||||
internal void update1(ModelPPM model, int p)
|
||||
{
|
||||
model.FoundState.Address = p;
|
||||
model.FoundState.IncrementFreq(4);
|
||||
freqData.IncrementSummFreq(4);
|
||||
State p0 = tempState3.Initialize(model.Heap);
|
||||
State p1 = tempState4.Initialize(model.Heap);
|
||||
p0.Address = p;
|
||||
p1.Address = p - State.Size;
|
||||
if (p0.Freq > p1.Freq)
|
||||
{
|
||||
State.PPMDSwap(p0, p1);
|
||||
model.FoundState.Address = p1.Address;
|
||||
if (p1.Freq > ModelPPM.MAX_FREQ)
|
||||
rescale(model);
|
||||
}
|
||||
}
|
||||
|
||||
internal void update1_0(ModelPPM model, int p)
|
||||
{
|
||||
model.FoundState.Address = p;
|
||||
model.PrevSuccess = 2 * model.FoundState.Freq > freqData.SummFreq ? 1 : 0;
|
||||
model.incRunLength(model.PrevSuccess);
|
||||
freqData.IncrementSummFreq(4);
|
||||
model.FoundState.IncrementFreq(4);
|
||||
if (model.FoundState.Freq > ModelPPM.MAX_FREQ)
|
||||
rescale(model);
|
||||
}
|
||||
|
||||
internal bool decodeSymbol2(ModelPPM model)
|
||||
{
|
||||
long count;
|
||||
int hiCnt, i = NumStats - model.NumMasked;
|
||||
SEE2Context psee2c = makeEscFreq2(model, i);
|
||||
RangeCoder coder = model.Coder;
|
||||
// STATE* ps[256], ** pps=ps, * p=U.Stats-1;
|
||||
State p = tempState1.Initialize(model.Heap);
|
||||
State temp = tempState2.Initialize(model.Heap);
|
||||
p.Address = freqData.GetStats() - State.Size;
|
||||
int pps = 0;
|
||||
hiCnt = 0;
|
||||
|
||||
do
|
||||
{
|
||||
do
|
||||
{
|
||||
p.IncrementAddress(); // p++;
|
||||
}
|
||||
while (model.CharMask[p.Symbol] == model.EscCount);
|
||||
hiCnt += p.Freq;
|
||||
ps[pps++] = p.Address;
|
||||
}
|
||||
while (--i != 0);
|
||||
coder.SubRange.incScale(hiCnt);
|
||||
count = coder.CurrentCount;
|
||||
if (count >= coder.SubRange.Scale)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
pps = 0;
|
||||
p.Address = ps[pps];
|
||||
if (count < hiCnt)
|
||||
{
|
||||
hiCnt = 0;
|
||||
while ((hiCnt += p.Freq) <= count)
|
||||
{
|
||||
p.Address = ps[++pps]; // p=*++pps;
|
||||
}
|
||||
coder.SubRange.HighCount = hiCnt;
|
||||
coder.SubRange.LowCount = hiCnt - p.Freq;
|
||||
psee2c.update();
|
||||
update2(model, p.Address);
|
||||
}
|
||||
else
|
||||
{
|
||||
coder.SubRange.LowCount = hiCnt;
|
||||
coder.SubRange.HighCount = coder.SubRange.Scale;
|
||||
i = NumStats - model.NumMasked; // ->NumMasked;
|
||||
pps--;
|
||||
do
|
||||
{
|
||||
temp.Address = ps[++pps]; // (*++pps)
|
||||
model.CharMask[temp.Symbol] = model.EscCount;
|
||||
}
|
||||
while (--i != 0);
|
||||
psee2c.incSumm((int)coder.SubRange.Scale);
|
||||
model.NumMasked = NumStats;
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
|
||||
internal void update2(ModelPPM model, int p)
|
||||
{
|
||||
State temp = tempState5.Initialize(model.Heap);
|
||||
temp.Address = p;
|
||||
model.FoundState.Address = p;
|
||||
model.FoundState.IncrementFreq(4);
|
||||
freqData.IncrementSummFreq(4);
|
||||
if (temp.Freq > ModelPPM.MAX_FREQ)
|
||||
{
|
||||
rescale(model);
|
||||
}
|
||||
model.incEscCount(1);
|
||||
model.RunLength = model.InitRL;
|
||||
}
|
||||
|
||||
private SEE2Context makeEscFreq2(ModelPPM model, int Diff)
|
||||
{
|
||||
SEE2Context psee2c;
|
||||
int numStats = NumStats;
|
||||
if (numStats != 256)
|
||||
{
|
||||
PPMContext suff = getTempPPMContext(model.Heap);
|
||||
suff.Address = getSuffix();
|
||||
int idx1 = model.getNS2Indx()[Diff - 1];
|
||||
int idx2 = 0;
|
||||
idx2 += ((Diff < suff.NumStats - numStats) ? 1 : 0);
|
||||
idx2 += 2 * ((freqData.SummFreq < 11 * numStats) ? 1 : 0);
|
||||
idx2 += 4 * ((model.NumMasked > Diff) ? 1 : 0);
|
||||
idx2 += model.HiBitsFlag;
|
||||
psee2c = model.getSEE2Cont()[idx1][idx2];
|
||||
model.Coder.SubRange.Scale = psee2c.Mean;
|
||||
}
|
||||
else
|
||||
{
|
||||
psee2c = model.DummySEE2Cont;
|
||||
model.Coder.SubRange.Scale = 1;
|
||||
}
|
||||
return psee2c;
|
||||
}
|
||||
|
||||
internal SEE2Context makeEscFreq(ModelPPM model, int numMasked, out int escFreq)
|
||||
{
|
||||
SEE2Context psee2c;
|
||||
int numStats = NumStats;
|
||||
int nonMasked = numStats - numMasked;
|
||||
if (numStats != 256)
|
||||
{
|
||||
PPMContext suff = getTempPPMContext(model.Heap);
|
||||
suff.Address = getSuffix();
|
||||
int idx1 = model.getNS2Indx()[nonMasked - 1];
|
||||
int idx2 = 0;
|
||||
idx2 += ((nonMasked < suff.NumStats - numStats) ? 1 : 0);
|
||||
idx2 += 2 * ((freqData.SummFreq < 11 * numStats) ? 1 : 0);
|
||||
idx2 += 4 * ((numMasked > nonMasked) ? 1 : 0);
|
||||
idx2 += model.HiBitsFlag;
|
||||
psee2c = model.getSEE2Cont()[idx1][idx2];
|
||||
escFreq = psee2c.Mean;
|
||||
}
|
||||
else
|
||||
{
|
||||
psee2c = model.DummySEE2Cont;
|
||||
escFreq = 1;
|
||||
}
|
||||
return psee2c;
|
||||
}
|
||||
|
||||
internal bool decodeSymbol1(ModelPPM model)
|
||||
{
|
||||
|
||||
RangeCoder coder = model.Coder;
|
||||
coder.SubRange.Scale = freqData.SummFreq;
|
||||
State p = new State(model.Heap);
|
||||
p.Address = freqData.GetStats();
|
||||
int i, HiCnt;
|
||||
long count = coder.CurrentCount;
|
||||
if (count >= coder.SubRange.Scale)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (count < (HiCnt = p.Freq))
|
||||
{
|
||||
coder.SubRange.HighCount = HiCnt;
|
||||
model.PrevSuccess = (2 * HiCnt > coder.SubRange.Scale) ? 1 : 0;
|
||||
model.incRunLength(model.PrevSuccess);
|
||||
HiCnt += 4;
|
||||
model.FoundState.Address = p.Address;
|
||||
model.FoundState.Freq = HiCnt;
|
||||
freqData.IncrementSummFreq(4);
|
||||
if (HiCnt > ModelPPM.MAX_FREQ)
|
||||
{
|
||||
rescale(model);
|
||||
}
|
||||
coder.SubRange.LowCount = 0;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (model.FoundState.Address == 0)
|
||||
{
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
model.PrevSuccess = 0;
|
||||
int numStats = NumStats;
|
||||
i = numStats - 1;
|
||||
while ((HiCnt += p.IncrementAddress().Freq) <= count)
|
||||
{
|
||||
if (--i == 0)
|
||||
{
|
||||
model.HiBitsFlag = model.getHB2Flag()[model.FoundState.Symbol];
|
||||
coder.SubRange.LowCount = HiCnt;
|
||||
model.CharMask[p.Symbol] = model.EscCount;
|
||||
model.NumMasked = numStats;
|
||||
i = numStats - 1;
|
||||
model.FoundState.Address = 0;
|
||||
do
|
||||
{
|
||||
model.CharMask[p.DecrementAddress().Symbol] = model.EscCount;
|
||||
}
|
||||
while (--i != 0);
|
||||
coder.SubRange.HighCount = coder.SubRange.Scale;
|
||||
return (true);
|
||||
}
|
||||
}
|
||||
coder.SubRange.LowCount = HiCnt - p.Freq;
|
||||
coder.SubRange.HighCount = HiCnt;
|
||||
update1(model, p.Address);
|
||||
return (true);
|
||||
}
|
||||
|
||||
public override System.String ToString()
|
||||
{
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buffer.Append("PPMContext[");
|
||||
buffer.Append("\n Address=");
|
||||
buffer.Append(Address);
|
||||
buffer.Append("\n size=");
|
||||
buffer.Append(size);
|
||||
buffer.Append("\n numStats=");
|
||||
buffer.Append(NumStats);
|
||||
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();
|
||||
}
|
||||
static PPMContext()
|
||||
{
|
||||
unionSize = System.Math.Max(FreqData.Size, State.Size);
|
||||
}
|
||||
}
|
||||
}
|
||||
34
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/H/Pointer.cs
vendored
Normal file
34
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/H/Pointer.cs
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
namespace Compress.SevenZip.Compress.PPmd.H
|
||||
{
|
||||
internal abstract class Pointer
|
||||
{
|
||||
/// <summary> Initialize the object with the array (may be null)</summary>
|
||||
/// <param name="mem">the byte array
|
||||
/// </param>
|
||||
internal Pointer(byte[] mem)
|
||||
{
|
||||
Memory = mem;
|
||||
}
|
||||
|
||||
internal byte[] Memory
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
internal virtual int Address
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
protected T Initialize<T>(byte[] mem)
|
||||
where T : Pointer
|
||||
{
|
||||
Memory = mem;
|
||||
Address = 0;
|
||||
return this as T;
|
||||
}
|
||||
}
|
||||
}
|
||||
183
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/H/RangeCoder.cs
vendored
Normal file
183
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/H/RangeCoder.cs
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace Compress.SevenZip.Compress.PPmd.H
|
||||
{
|
||||
internal class RangeCoder
|
||||
{
|
||||
internal const int TOP = 1 << 24;
|
||||
internal const int BOT = 1 << 15;
|
||||
internal const long UintMask = 0xFFFFffffL;
|
||||
|
||||
// uint low, code, range;
|
||||
private long low, code, range;
|
||||
private Stream stream;
|
||||
|
||||
internal RangeCoder(Stream stream)
|
||||
{
|
||||
this.stream = stream;
|
||||
Init();
|
||||
}
|
||||
|
||||
private void Init()
|
||||
{
|
||||
this.SubRange = new SubRange();
|
||||
|
||||
low = code = 0L;
|
||||
range = 0xFFFFffffL;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
code = ((code << 8) | Char) & UintMask;
|
||||
}
|
||||
}
|
||||
|
||||
internal int CurrentCount
|
||||
{
|
||||
get
|
||||
{
|
||||
range = (range / SubRange.Scale) & UintMask;
|
||||
return (int)((code - low) / (range));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private long Char
|
||||
{
|
||||
get
|
||||
{
|
||||
if (stream != null)
|
||||
return stream.ReadByte();
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal SubRange SubRange
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
|
||||
internal long GetCurrentShiftCount(int SHIFT)
|
||||
{
|
||||
range = Utility.URShift(range, SHIFT);
|
||||
return ((code - low) / (range)) & UintMask;
|
||||
}
|
||||
|
||||
internal void Decode()
|
||||
{
|
||||
low = (low + (range * SubRange.LowCount)) & UintMask;
|
||||
range = (range * (SubRange.HighCount - SubRange.LowCount)) & UintMask;
|
||||
}
|
||||
|
||||
internal void AriDecNormalize()
|
||||
{
|
||||
// while ((low ^ (low + range)) < TOP || range < BOT && ((range = -low & (BOT - 1)) != 0 ? true : true))
|
||||
// {
|
||||
// code = ((code << 8) | unpackRead.getChar()&0xff)&uintMask;
|
||||
// range = (range << 8)&uintMask;
|
||||
// low = (low << 8)&uintMask;
|
||||
// }
|
||||
|
||||
// Rewrote for clarity
|
||||
bool c2 = false;
|
||||
while ((low ^ (low + range)) < TOP || (c2 = range < BOT))
|
||||
{
|
||||
if (c2)
|
||||
{
|
||||
range = (-low & (BOT - 1)) & UintMask;
|
||||
c2 = false;
|
||||
}
|
||||
code = ((code << 8) | Char) & UintMask;
|
||||
range = (range << 8) & UintMask;
|
||||
low = (low << 8) & UintMask;
|
||||
}
|
||||
}
|
||||
|
||||
// Debug
|
||||
public override System.String ToString()
|
||||
{
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buffer.Append("RangeCoder[");
|
||||
buffer.Append("\n low=");
|
||||
buffer.Append(low);
|
||||
buffer.Append("\n code=");
|
||||
buffer.Append(code);
|
||||
buffer.Append("\n range=");
|
||||
buffer.Append(range);
|
||||
buffer.Append("\n subrange=");
|
||||
buffer.Append(SubRange);
|
||||
buffer.Append("]");
|
||||
return buffer.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
internal class SubRange
|
||||
{
|
||||
// uint LowCount, HighCount, scale;
|
||||
private long lowCount, highCount, scale;
|
||||
|
||||
internal void incScale(int dScale)
|
||||
{
|
||||
Scale = Scale + dScale;
|
||||
}
|
||||
|
||||
internal long HighCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return highCount;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.highCount = value & RangeCoder.UintMask;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal long LowCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return lowCount & RangeCoder.UintMask;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.lowCount = value & RangeCoder.UintMask;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal long Scale
|
||||
{
|
||||
get
|
||||
{
|
||||
return scale;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.scale = value & RangeCoder.UintMask;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Debug
|
||||
public override System.String ToString()
|
||||
{
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buffer.Append("SubRange[");
|
||||
buffer.Append("\n lowCount=");
|
||||
buffer.Append(lowCount);
|
||||
buffer.Append("\n highCount=");
|
||||
buffer.Append(highCount);
|
||||
buffer.Append("\n scale=");
|
||||
buffer.Append(scale);
|
||||
buffer.Append("]");
|
||||
return buffer.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
125
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/H/RarMemBlock.cs
vendored
Normal file
125
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/H/RarMemBlock.cs
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
|
||||
namespace Compress.SevenZip.Compress.PPmd.H
|
||||
{
|
||||
internal class RarMemBlock : Pointer
|
||||
{
|
||||
public const int size = 12;
|
||||
|
||||
private int stamp, NU;
|
||||
|
||||
private int next, prev; // Pointer RarMemBlock
|
||||
|
||||
public RarMemBlock(byte[] Memory)
|
||||
: base(Memory)
|
||||
{
|
||||
}
|
||||
|
||||
internal int Stamp
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Memory != null)
|
||||
{
|
||||
stamp = Utility.readShortLittleEndian(Memory, Address) & 0xffff;
|
||||
}
|
||||
return stamp;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.stamp = value;
|
||||
if (Memory != null)
|
||||
{
|
||||
Utility.WriteLittleEndian(Memory, Address, (short)value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal void InsertAt(RarMemBlock p)
|
||||
{
|
||||
RarMemBlock temp = new RarMemBlock(Memory);
|
||||
SetPrev(p.Address);
|
||||
temp.Address = GetPrev();
|
||||
SetNext(temp.GetNext()); // prev.getNext();
|
||||
temp.SetNext(this); // prev.setNext(this);
|
||||
temp.Address = GetNext();
|
||||
temp.SetPrev(this); // next.setPrev(this);
|
||||
}
|
||||
|
||||
internal void Remove()
|
||||
{
|
||||
RarMemBlock temp = new RarMemBlock(Memory);
|
||||
temp.Address = GetPrev();
|
||||
temp.SetNext(GetNext()); // prev.setNext(next);
|
||||
temp.Address = GetNext();
|
||||
temp.SetPrev(GetPrev()); // next.setPrev(prev);
|
||||
// next = -1;
|
||||
// prev = -1;
|
||||
}
|
||||
|
||||
internal int GetNext()
|
||||
{
|
||||
if (Memory != null)
|
||||
{
|
||||
next = Utility.readIntLittleEndian(Memory, Address + 4);
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
internal void SetNext(RarMemBlock next)
|
||||
{
|
||||
SetNext(next.Address);
|
||||
}
|
||||
|
||||
internal void SetNext(int next)
|
||||
{
|
||||
this.next = next;
|
||||
if (Memory != null)
|
||||
{
|
||||
Utility.WriteLittleEndian(Memory, Address + 4, next);
|
||||
}
|
||||
}
|
||||
|
||||
internal int GetNU()
|
||||
{
|
||||
if (Memory != null)
|
||||
{
|
||||
NU = Utility.readShortLittleEndian(Memory, Address + 2) & 0xffff;
|
||||
}
|
||||
return NU;
|
||||
}
|
||||
|
||||
internal void SetNU(int nu)
|
||||
{
|
||||
NU = nu & 0xffff;
|
||||
if (Memory != null)
|
||||
{
|
||||
Utility.WriteLittleEndian(Memory, Address + 2, (short)nu);
|
||||
}
|
||||
}
|
||||
|
||||
internal int GetPrev()
|
||||
{
|
||||
if (Memory != null)
|
||||
{
|
||||
prev = Utility.readIntLittleEndian(Memory, Address + 8);
|
||||
}
|
||||
return prev;
|
||||
}
|
||||
|
||||
internal void SetPrev(RarMemBlock prev)
|
||||
{
|
||||
SetPrev(prev.Address);
|
||||
}
|
||||
|
||||
internal void SetPrev(int prev)
|
||||
{
|
||||
this.prev = prev;
|
||||
if (Memory != null)
|
||||
{
|
||||
Utility.WriteLittleEndian(Memory, Address + 8, prev);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
53
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/H/RarNode.cs
vendored
Normal file
53
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/H/RarNode.cs
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
using System.Text;
|
||||
|
||||
namespace Compress.SevenZip.Compress.PPmd.H
|
||||
{
|
||||
internal class RarNode : Pointer
|
||||
{
|
||||
private int next; //rarnode pointer
|
||||
|
||||
public const int size = 4;
|
||||
|
||||
public RarNode(byte[] Memory)
|
||||
: base(Memory)
|
||||
{
|
||||
}
|
||||
|
||||
internal int GetNext()
|
||||
{
|
||||
if (Memory != null)
|
||||
{
|
||||
next = Utility.readIntLittleEndian(Memory, Address);
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
internal void SetNext(RarNode next)
|
||||
{
|
||||
SetNext(next.Address);
|
||||
}
|
||||
|
||||
internal void SetNext(int next)
|
||||
{
|
||||
this.next = next;
|
||||
if (Memory != null)
|
||||
{
|
||||
Utility.WriteLittleEndian(Memory, Address, next);
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buffer.Append("State[");
|
||||
buffer.Append("\n Address=");
|
||||
buffer.Append(Address);
|
||||
buffer.Append("\n size=");
|
||||
buffer.Append(size);
|
||||
buffer.Append("\n next=");
|
||||
buffer.Append(GetNext());
|
||||
buffer.Append("\n]");
|
||||
return buffer.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
107
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/H/SEE2Context.cs
vendored
Normal file
107
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/H/SEE2Context.cs
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
using System.Text;
|
||||
|
||||
namespace Compress.SevenZip.Compress.PPmd.H
|
||||
{
|
||||
internal class SEE2Context
|
||||
{
|
||||
virtual public int Mean
|
||||
{
|
||||
get
|
||||
{
|
||||
int retVal = Utility.URShift(summ, shift);
|
||||
summ -= retVal;
|
||||
return retVal + ((retVal == 0) ? 1 : 0);
|
||||
}
|
||||
|
||||
}
|
||||
virtual public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.count = value & 0xff;
|
||||
}
|
||||
|
||||
}
|
||||
virtual public int Shift
|
||||
{
|
||||
get
|
||||
{
|
||||
return shift;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.shift = value & 0xff;
|
||||
}
|
||||
|
||||
}
|
||||
virtual public int Summ
|
||||
{
|
||||
get
|
||||
{
|
||||
return summ;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.summ = value & 0xffff;
|
||||
}
|
||||
|
||||
}
|
||||
public const int size = 4;
|
||||
|
||||
// ushort Summ;
|
||||
private int summ;
|
||||
|
||||
// byte Shift;
|
||||
private int shift;
|
||||
|
||||
// byte Count;
|
||||
private int count;
|
||||
|
||||
public void Initialize(int initVal)
|
||||
{
|
||||
shift = (ModelPPM.PERIOD_BITS - 4) & 0xff;
|
||||
summ = (initVal << shift) & 0xffff;
|
||||
count = 4;
|
||||
}
|
||||
|
||||
public virtual void update()
|
||||
{
|
||||
if (shift < ModelPPM.PERIOD_BITS && --count == 0)
|
||||
{
|
||||
summ += summ;
|
||||
count = (3 << shift++);
|
||||
}
|
||||
summ &= 0xffff;
|
||||
count &= 0xff;
|
||||
shift &= 0xff;
|
||||
}
|
||||
|
||||
public virtual void incSumm(int dSumm)
|
||||
{
|
||||
Summ = Summ + dSumm;
|
||||
}
|
||||
|
||||
public override System.String ToString()
|
||||
{
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buffer.Append("SEE2Context[");
|
||||
buffer.Append("\n size=");
|
||||
buffer.Append(size);
|
||||
buffer.Append("\n summ=");
|
||||
buffer.Append(summ);
|
||||
buffer.Append("\n shift=");
|
||||
buffer.Append(shift);
|
||||
buffer.Append("\n count=");
|
||||
buffer.Append(count);
|
||||
buffer.Append("\n]");
|
||||
return buffer.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
120
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/H/State.cs
vendored
Normal file
120
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/H/State.cs
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace Compress.SevenZip.Compress.PPmd.H
|
||||
{
|
||||
internal class State : Pointer
|
||||
{
|
||||
internal const int Size = 6;
|
||||
|
||||
internal State(byte[] Memory)
|
||||
: base(Memory)
|
||||
{
|
||||
}
|
||||
|
||||
internal int Symbol
|
||||
{
|
||||
get
|
||||
{
|
||||
return Memory[Address] & 0xff;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
Memory[Address] = (byte)value;
|
||||
}
|
||||
|
||||
}
|
||||
internal int Freq
|
||||
{
|
||||
get
|
||||
{
|
||||
return Memory[Address + 1] & 0xff;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
Memory[Address + 1] = (byte)value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal State Initialize(byte[] mem)
|
||||
{
|
||||
return base.Initialize<State>(mem);
|
||||
}
|
||||
|
||||
internal void IncrementFreq(int dFreq)
|
||||
{
|
||||
Memory[Address + 1] = (byte)(Memory[Address + 1] + dFreq);
|
||||
}
|
||||
|
||||
internal int GetSuccessor()
|
||||
{
|
||||
return Utility.readIntLittleEndian(Memory, Address + 2);
|
||||
}
|
||||
|
||||
internal void SetSuccessor(PPMContext successor)
|
||||
{
|
||||
SetSuccessor(successor.Address);
|
||||
}
|
||||
|
||||
internal void SetSuccessor(int successor)
|
||||
{
|
||||
Utility.WriteLittleEndian(Memory, Address + 2, successor);
|
||||
}
|
||||
|
||||
internal void SetValues(StateRef state)
|
||||
{
|
||||
Symbol = state.Symbol;
|
||||
Freq = state.Freq;
|
||||
SetSuccessor(state.GetSuccessor());
|
||||
}
|
||||
|
||||
internal void SetValues(State ptr)
|
||||
{
|
||||
Array.Copy(ptr.Memory, ptr.Address, Memory, Address, Size);
|
||||
}
|
||||
|
||||
internal State DecrementAddress()
|
||||
{
|
||||
Address = Address - Size;
|
||||
return this;
|
||||
}
|
||||
|
||||
internal State IncrementAddress()
|
||||
{
|
||||
Address = Address + Size;
|
||||
return this;
|
||||
}
|
||||
|
||||
internal static void PPMDSwap(State ptr1, State ptr2)
|
||||
{
|
||||
byte[] mem1 = ptr1.Memory, mem2 = ptr2.Memory;
|
||||
for (int i = 0, pos1 = ptr1.Address, pos2 = ptr2.Address; i < Size; i++, pos1++, pos2++)
|
||||
{
|
||||
byte temp = mem1[pos1];
|
||||
mem1[pos1] = mem2[pos2];
|
||||
mem2[pos2] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
public override System.String ToString()
|
||||
{
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buffer.Append("State[");
|
||||
buffer.Append("\n Address=");
|
||||
buffer.Append(Address);
|
||||
buffer.Append("\n size=");
|
||||
buffer.Append(Size);
|
||||
buffer.Append("\n symbol=");
|
||||
buffer.Append(Symbol);
|
||||
buffer.Append("\n freq=");
|
||||
buffer.Append(Freq);
|
||||
buffer.Append("\n successor=");
|
||||
buffer.Append(GetSuccessor());
|
||||
buffer.Append("\n]");
|
||||
return buffer.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
90
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/H/StateRef.cs
vendored
Normal file
90
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/H/StateRef.cs
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
using System.Text;
|
||||
|
||||
namespace Compress.SevenZip.Compress.PPmd.H
|
||||
{
|
||||
internal class StateRef
|
||||
{
|
||||
private int symbol;
|
||||
|
||||
private int freq;
|
||||
|
||||
private int successor; // pointer ppmcontext
|
||||
|
||||
internal int Symbol
|
||||
{
|
||||
get
|
||||
{
|
||||
return symbol;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.symbol = value & 0xff;
|
||||
}
|
||||
|
||||
}
|
||||
internal int Freq
|
||||
{
|
||||
get
|
||||
{
|
||||
return freq;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.freq = value & 0xff;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal State Values
|
||||
{
|
||||
set
|
||||
{
|
||||
Freq = value.Freq;
|
||||
SetSuccessor(value.GetSuccessor());
|
||||
Symbol = value.Symbol;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public virtual void IncrementFreq(int dFreq)
|
||||
{
|
||||
freq = (freq + dFreq) & 0xff;
|
||||
}
|
||||
|
||||
public virtual void DecrementFreq(int dFreq)
|
||||
{
|
||||
freq = (freq - dFreq) & 0xff;
|
||||
}
|
||||
|
||||
public virtual int GetSuccessor()
|
||||
{
|
||||
return successor;
|
||||
}
|
||||
|
||||
public virtual void SetSuccessor(PPMContext successor)
|
||||
{
|
||||
SetSuccessor(successor.Address);
|
||||
}
|
||||
|
||||
public virtual void SetSuccessor(int successor)
|
||||
{
|
||||
this.successor = successor;
|
||||
}
|
||||
|
||||
public override System.String ToString()
|
||||
{
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buffer.Append("State[");
|
||||
buffer.Append("\n symbol=");
|
||||
buffer.Append(Symbol);
|
||||
buffer.Append("\n freq=");
|
||||
buffer.Append(Freq);
|
||||
buffer.Append("\n successor=");
|
||||
buffer.Append(GetSuccessor());
|
||||
buffer.Append("\n]");
|
||||
return buffer.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
489
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/H/SubAllocator.cs
vendored
Normal file
489
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/H/SubAllocator.cs
vendored
Normal file
@@ -0,0 +1,489 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace Compress.SevenZip.Compress.PPmd.H
|
||||
{
|
||||
internal class SubAllocator
|
||||
{
|
||||
virtual public int FakeUnitsStart
|
||||
{
|
||||
get
|
||||
{
|
||||
return fakeUnitsStart;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.fakeUnitsStart = value;
|
||||
}
|
||||
|
||||
}
|
||||
virtual public int HeapEnd
|
||||
{
|
||||
get
|
||||
{
|
||||
return heapEnd;
|
||||
}
|
||||
|
||||
}
|
||||
virtual public int PText
|
||||
{
|
||||
get
|
||||
{
|
||||
return pText;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
pText = value;
|
||||
}
|
||||
|
||||
}
|
||||
virtual public int UnitsStart
|
||||
{
|
||||
get
|
||||
{
|
||||
return unitsStart;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.unitsStart = value;
|
||||
}
|
||||
|
||||
}
|
||||
virtual public byte[] Heap
|
||||
{
|
||||
get
|
||||
{
|
||||
return heap;
|
||||
}
|
||||
|
||||
}
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'N4 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public const int N1 = 4;
|
||||
public const int N2 = 4;
|
||||
public const int N3 = 4;
|
||||
public static readonly int N4 = (128 + 3 - 1 * N1 - 2 * N2 - 3 * N3) / 4;
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'N_INDEXES '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly int N_INDEXES = N1 + N2 + N3 + N4;
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'UNIT_SIZE '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
//UPGRADE_NOTE: The initialization of 'UNIT_SIZE' was moved to static method 'SharpCompress.Unpack.PPM.SubAllocator'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
|
||||
public static readonly int UNIT_SIZE;
|
||||
|
||||
public const int FIXED_UNIT_SIZE = 12;
|
||||
|
||||
private int subAllocatorSize;
|
||||
|
||||
// byte Indx2Units[N_INDEXES], Units2Indx[128], GlueCount;
|
||||
private int[] indx2Units = new int[N_INDEXES];
|
||||
private int[] units2Indx = new int[128];
|
||||
private int glueCount;
|
||||
|
||||
// byte *HeapStart,*LoUnit, *HiUnit;
|
||||
private int heapStart, loUnit, hiUnit;
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'freeList '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private RarNode[] freeList = new RarNode[N_INDEXES];
|
||||
|
||||
// byte *pText, *UnitsStart,*HeapEnd,*FakeUnitsStart;
|
||||
private int pText, unitsStart, heapEnd, fakeUnitsStart;
|
||||
|
||||
private byte[] heap;
|
||||
|
||||
private int freeListPos;
|
||||
|
||||
private int tempMemBlockPos;
|
||||
|
||||
// Temp fields
|
||||
private RarNode tempRarNode = null;
|
||||
private RarMemBlock tempRarMemBlock1 = null;
|
||||
private RarMemBlock tempRarMemBlock2 = null;
|
||||
private RarMemBlock tempRarMemBlock3 = null;
|
||||
|
||||
public SubAllocator()
|
||||
{
|
||||
clean();
|
||||
}
|
||||
|
||||
public virtual void clean()
|
||||
{
|
||||
subAllocatorSize = 0;
|
||||
}
|
||||
|
||||
private void insertNode(int p, int indx)
|
||||
{
|
||||
RarNode temp = tempRarNode;
|
||||
temp.Address = p;
|
||||
temp.SetNext(freeList[indx].GetNext());
|
||||
freeList[indx].SetNext(temp);
|
||||
}
|
||||
|
||||
public virtual void incPText()
|
||||
{
|
||||
pText++;
|
||||
}
|
||||
|
||||
private int removeNode(int indx)
|
||||
{
|
||||
int retVal = freeList[indx].GetNext();
|
||||
RarNode temp = tempRarNode;
|
||||
temp.Address = retVal;
|
||||
freeList[indx].SetNext(temp.GetNext());
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private int U2B(int NU)
|
||||
{
|
||||
return UNIT_SIZE * NU;
|
||||
}
|
||||
|
||||
/* memblockptr */
|
||||
private int MBPtr(int BasePtr, int Items)
|
||||
{
|
||||
return (BasePtr + U2B(Items));
|
||||
}
|
||||
|
||||
private void splitBlock(int pv, int oldIndx, int newIndx)
|
||||
{
|
||||
int i, uDiff = indx2Units[oldIndx] - indx2Units[newIndx];
|
||||
int p = pv + U2B(indx2Units[newIndx]);
|
||||
if (indx2Units[i = units2Indx[uDiff - 1]] != uDiff)
|
||||
{
|
||||
insertNode(p, --i);
|
||||
p += U2B(i = indx2Units[i]);
|
||||
uDiff -= i;
|
||||
}
|
||||
insertNode(p, units2Indx[uDiff - 1]);
|
||||
}
|
||||
|
||||
public virtual void stopSubAllocator()
|
||||
{
|
||||
if (subAllocatorSize != 0)
|
||||
{
|
||||
subAllocatorSize = 0;
|
||||
//ArrayFactory.BYTES_FACTORY.recycle(heap);
|
||||
heap = null;
|
||||
heapStart = 1;
|
||||
// rarfree(HeapStart);
|
||||
// Free temp fields
|
||||
tempRarNode = null;
|
||||
tempRarMemBlock1 = null;
|
||||
tempRarMemBlock2 = null;
|
||||
tempRarMemBlock3 = null;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual int GetAllocatedMemory()
|
||||
{
|
||||
return subAllocatorSize;
|
||||
}
|
||||
|
||||
|
||||
public virtual bool startSubAllocator(int SASize)
|
||||
{
|
||||
int t = SASize;
|
||||
if (subAllocatorSize == t)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
stopSubAllocator();
|
||||
int allocSize = t / FIXED_UNIT_SIZE * UNIT_SIZE + UNIT_SIZE;
|
||||
|
||||
// adding space for freelist (needed for poiters)
|
||||
// 1+ for null pointer
|
||||
int realAllocSize = 1 + allocSize + 4 * N_INDEXES;
|
||||
// adding space for an additional memblock
|
||||
tempMemBlockPos = realAllocSize;
|
||||
realAllocSize += RarMemBlock.size;
|
||||
|
||||
heap = new byte[realAllocSize];
|
||||
heapStart = 1;
|
||||
heapEnd = heapStart + allocSize - UNIT_SIZE;
|
||||
subAllocatorSize = t;
|
||||
// Bug fixed
|
||||
freeListPos = heapStart + allocSize;
|
||||
//UPGRADE_ISSUE: The following fragment of code could not be parsed and was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1156'"
|
||||
//assert(realAllocSize - tempMemBlockPos == RarMemBlock.size): realAllocSize
|
||||
//+ + tempMemBlockPos + + RarMemBlock.size;
|
||||
|
||||
// Init freeList
|
||||
for (int i = 0, pos = freeListPos; i < freeList.Length; i++, pos += RarNode.size)
|
||||
{
|
||||
freeList[i] = new RarNode(heap);
|
||||
freeList[i].Address = pos;
|
||||
}
|
||||
|
||||
// Init temp fields
|
||||
tempRarNode = new RarNode(heap);
|
||||
tempRarMemBlock1 = new RarMemBlock(heap);
|
||||
tempRarMemBlock2 = new RarMemBlock(heap);
|
||||
tempRarMemBlock3 = new RarMemBlock(heap);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void glueFreeBlocks()
|
||||
{
|
||||
RarMemBlock s0 = tempRarMemBlock1;
|
||||
s0.Address = tempMemBlockPos;
|
||||
RarMemBlock p = tempRarMemBlock2;
|
||||
RarMemBlock p1 = tempRarMemBlock3;
|
||||
int i, k, sz;
|
||||
if (loUnit != hiUnit)
|
||||
{
|
||||
heap[loUnit] = 0;
|
||||
}
|
||||
for (i = 0, s0.SetPrev(s0), s0.SetNext(s0); i < N_INDEXES; i++)
|
||||
{
|
||||
while (freeList[i].GetNext() != 0)
|
||||
{
|
||||
p.Address = removeNode(i); // =(RAR_MEM_BLK*)RemoveNode(i);
|
||||
p.InsertAt(s0); // p->insertAt(&s0);
|
||||
p.Stamp = 0xFFFF; // p->Stamp=0xFFFF;
|
||||
p.SetNU(indx2Units[i]); // p->NU=Indx2Units[i];
|
||||
}
|
||||
}
|
||||
for (p.Address = s0.GetNext(); p.Address != s0.Address; p.Address = p.GetNext())
|
||||
{
|
||||
// while ((p1=MBPtr(p,p->NU))->Stamp == 0xFFFF && int(p->NU)+p1->NU
|
||||
// < 0x10000)
|
||||
// Bug fixed
|
||||
p1.Address = MBPtr(p.Address, p.GetNU());
|
||||
while (p1.Stamp == 0xFFFF && p.GetNU() + p1.GetNU() < 0x10000)
|
||||
{
|
||||
p1.Remove();
|
||||
p.SetNU(p.GetNU() + p1.GetNU()); // ->NU += p1->NU;
|
||||
p1.Address = MBPtr(p.Address, p.GetNU());
|
||||
}
|
||||
}
|
||||
// while ((p=s0.next) != &s0)
|
||||
// Bug fixed
|
||||
p.Address = s0.GetNext();
|
||||
while (p.Address != s0.Address)
|
||||
{
|
||||
for (p.Remove(), sz = p.GetNU(); sz > 128; sz -= 128, p.Address = MBPtr(p.Address, 128))
|
||||
{
|
||||
insertNode(p.Address, N_INDEXES - 1);
|
||||
}
|
||||
if (indx2Units[i = units2Indx[sz - 1]] != sz)
|
||||
{
|
||||
k = sz - indx2Units[--i];
|
||||
insertNode(MBPtr(p.Address, sz - k), k - 1);
|
||||
}
|
||||
insertNode(p.Address, i);
|
||||
p.Address = s0.GetNext();
|
||||
}
|
||||
}
|
||||
|
||||
private int allocUnitsRare(int indx)
|
||||
{
|
||||
if (glueCount == 0)
|
||||
{
|
||||
glueCount = 255;
|
||||
glueFreeBlocks();
|
||||
if (freeList[indx].GetNext() != 0)
|
||||
{
|
||||
return removeNode(indx);
|
||||
}
|
||||
}
|
||||
int i = indx;
|
||||
do
|
||||
{
|
||||
if (++i == N_INDEXES)
|
||||
{
|
||||
glueCount--;
|
||||
i = U2B(indx2Units[indx]);
|
||||
int j = FIXED_UNIT_SIZE * indx2Units[indx];
|
||||
if (fakeUnitsStart - pText > j)
|
||||
{
|
||||
fakeUnitsStart -= j;
|
||||
unitsStart -= i;
|
||||
return unitsStart;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
while (freeList[i].GetNext() == 0);
|
||||
int retVal = removeNode(i);
|
||||
splitBlock(retVal, i, indx);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public virtual int allocUnits(int NU)
|
||||
{
|
||||
int indx = units2Indx[NU - 1];
|
||||
if (freeList[indx].GetNext() != 0)
|
||||
{
|
||||
return removeNode(indx);
|
||||
}
|
||||
int retVal = loUnit;
|
||||
loUnit += U2B(indx2Units[indx]);
|
||||
if (loUnit <= hiUnit)
|
||||
{
|
||||
return retVal;
|
||||
}
|
||||
loUnit -= U2B(indx2Units[indx]);
|
||||
return allocUnitsRare(indx);
|
||||
}
|
||||
|
||||
public virtual int allocContext()
|
||||
{
|
||||
if (hiUnit != loUnit)
|
||||
return (hiUnit -= UNIT_SIZE);
|
||||
if (freeList[0].GetNext() != 0)
|
||||
{
|
||||
return removeNode(0);
|
||||
}
|
||||
return allocUnitsRare(0);
|
||||
}
|
||||
|
||||
public virtual int expandUnits(int oldPtr, int OldNU)
|
||||
{
|
||||
int i0 = units2Indx[OldNU - 1];
|
||||
int i1 = units2Indx[OldNU - 1 + 1];
|
||||
if (i0 == i1)
|
||||
{
|
||||
return oldPtr;
|
||||
}
|
||||
int ptr = allocUnits(OldNU + 1);
|
||||
if (ptr != 0)
|
||||
{
|
||||
// memcpy(ptr,OldPtr,U2B(OldNU));
|
||||
Array.Copy(heap, oldPtr, heap, ptr, U2B(OldNU));
|
||||
insertNode(oldPtr, i0);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
public virtual int shrinkUnits(int oldPtr, int oldNU, int newNU)
|
||||
{
|
||||
// System.out.println("SubAllocator.shrinkUnits(" + OldPtr + ", " +
|
||||
// OldNU + ", " + NewNU + ")");
|
||||
int i0 = units2Indx[oldNU - 1];
|
||||
int i1 = units2Indx[newNU - 1];
|
||||
if (i0 == i1)
|
||||
{
|
||||
return oldPtr;
|
||||
}
|
||||
if (freeList[i1].GetNext() != 0)
|
||||
{
|
||||
int ptr = removeNode(i1);
|
||||
// memcpy(ptr,OldPtr,U2B(NewNU));
|
||||
// for (int i = 0; i < U2B(NewNU); i++) {
|
||||
// heap[ptr + i] = heap[OldPtr + i];
|
||||
// }
|
||||
Array.Copy(heap, oldPtr, heap, ptr, U2B(newNU));
|
||||
insertNode(oldPtr, i0);
|
||||
return ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
splitBlock(oldPtr, i0, i1);
|
||||
return oldPtr;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void freeUnits(int ptr, int OldNU)
|
||||
{
|
||||
insertNode(ptr, units2Indx[OldNU - 1]);
|
||||
}
|
||||
|
||||
public virtual void decPText(int dPText)
|
||||
{
|
||||
PText = PText - dPText;
|
||||
}
|
||||
|
||||
public virtual void initSubAllocator()
|
||||
{
|
||||
int i, k;
|
||||
Utility.Fill(heap, freeListPos, freeListPos + sizeOfFreeList(), (byte)0);
|
||||
|
||||
pText = heapStart;
|
||||
|
||||
int size2 = FIXED_UNIT_SIZE * (subAllocatorSize / 8 / FIXED_UNIT_SIZE * 7);
|
||||
int realSize2 = size2 / FIXED_UNIT_SIZE * UNIT_SIZE;
|
||||
int size1 = subAllocatorSize - size2;
|
||||
int realSize1 = size1 / FIXED_UNIT_SIZE * UNIT_SIZE + size1 % FIXED_UNIT_SIZE;
|
||||
hiUnit = heapStart + subAllocatorSize;
|
||||
loUnit = unitsStart = heapStart + realSize1;
|
||||
fakeUnitsStart = heapStart + size1;
|
||||
hiUnit = loUnit + realSize2;
|
||||
|
||||
for (i = 0, k = 1; i < N1; i++, k += 1)
|
||||
{
|
||||
indx2Units[i] = k & 0xff;
|
||||
}
|
||||
for (k++; i < N1 + N2; i++, k += 2)
|
||||
{
|
||||
indx2Units[i] = k & 0xff;
|
||||
}
|
||||
for (k++; i < N1 + N2 + N3; i++, k += 3)
|
||||
{
|
||||
indx2Units[i] = k & 0xff;
|
||||
}
|
||||
for (k++; i < (N1 + N2 + N3 + N4); i++, k += 4)
|
||||
{
|
||||
indx2Units[i] = k & 0xff;
|
||||
}
|
||||
|
||||
for (glueCount = 0, k = 0, i = 0; k < 128; k++)
|
||||
{
|
||||
i += ((indx2Units[i] < (k + 1)) ? 1 : 0);
|
||||
units2Indx[k] = i & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
private int sizeOfFreeList()
|
||||
{
|
||||
return freeList.Length * RarNode.size;
|
||||
}
|
||||
|
||||
// Debug
|
||||
// public void dumpHeap() {
|
||||
// File file = new File("P:\\test\\heapdumpj");
|
||||
// OutputStream out = null;
|
||||
// try {
|
||||
// out = new FileOutputStream(file);
|
||||
// out.write(heap, heapStart, heapEnd - heapStart);
|
||||
// out.flush();
|
||||
// System.out.println("Heap dumped to " + file.getAbsolutePath());
|
||||
// }
|
||||
// catch (IOException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// finally {
|
||||
// FileUtil.close(out);
|
||||
// }
|
||||
// }
|
||||
|
||||
// Debug
|
||||
public override System.String ToString()
|
||||
{
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buffer.Append("SubAllocator[");
|
||||
buffer.Append("\n subAllocatorSize=");
|
||||
buffer.Append(subAllocatorSize);
|
||||
buffer.Append("\n glueCount=");
|
||||
buffer.Append(glueCount);
|
||||
buffer.Append("\n heapStart=");
|
||||
buffer.Append(heapStart);
|
||||
buffer.Append("\n loUnit=");
|
||||
buffer.Append(loUnit);
|
||||
buffer.Append("\n hiUnit=");
|
||||
buffer.Append(hiUnit);
|
||||
buffer.Append("\n pText=");
|
||||
buffer.Append(pText);
|
||||
buffer.Append("\n unitsStart=");
|
||||
buffer.Append(unitsStart);
|
||||
buffer.Append("\n]");
|
||||
return buffer.ToString();
|
||||
}
|
||||
static SubAllocator()
|
||||
{
|
||||
UNIT_SIZE = System.Math.Max(PPMContext.size, RarMemBlock.size);
|
||||
}
|
||||
}
|
||||
}
|
||||
457
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/I1/Allocator.cs
vendored
Normal file
457
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/I1/Allocator.cs
vendored
Normal file
@@ -0,0 +1,457 @@
|
||||
#region Using
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Compress.SevenZip.Compress.PPmd.I1
|
||||
{
|
||||
|
||||
/// Allocate a single, large array and then provide sections of this array to callers. Callers are provided with
|
||||
/// instances of <see cref="Pointer"/> (which simply contain a single address value, representing a location
|
||||
/// in the large array). Callers can then cast <see cref="Pointer"/> to one of the following structures (all
|
||||
/// of which also simply contain a single address value):
|
||||
internal class Allocator
|
||||
{
|
||||
private const uint UnitSize = 12;
|
||||
private const uint LocalOffset = 4; // reserve the first four bytes for Pointer.Zero
|
||||
private const uint NodeOffset = LocalOffset + MemoryNode.Size; // reserve space for a single memory node
|
||||
private const uint HeapOffset = NodeOffset + IndexCount * MemoryNode.Size; // reserve space for the array of memory nodes
|
||||
private const uint N1 = 4;
|
||||
private const uint N2 = 4;
|
||||
private const uint N3 = 4;
|
||||
private const uint N4 = (128 + 3 - 1 * N1 - 2 * N2 - 3 * N3) / 4;
|
||||
private const uint IndexCount = N1 + N2 + N3 + N4;
|
||||
|
||||
private static readonly byte[] indexToUnits;
|
||||
private static readonly byte[] unitsToIndex;
|
||||
|
||||
public uint AllocatorSize;
|
||||
public uint GlueCount;
|
||||
public Pointer BaseUnit;
|
||||
public Pointer LowUnit;
|
||||
public Pointer HighUnit;
|
||||
public Pointer Text;
|
||||
public Pointer Heap;
|
||||
public MemoryNode[] MemoryNodes;
|
||||
|
||||
public byte[] Memory;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes static read-only arrays used by the <see cref="Allocator"/>.
|
||||
/// </summary>
|
||||
static Allocator()
|
||||
{
|
||||
// Construct the static index to units lookup array. It will contain the following values.
|
||||
//
|
||||
// 1 2 3 4 6 8 10 12 15 18 21 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80 84 88 92 96 100 104 108
|
||||
// 112 116 120 124 128
|
||||
|
||||
uint index;
|
||||
uint unitCount;
|
||||
|
||||
indexToUnits = new byte[IndexCount];
|
||||
|
||||
for (index = 0, unitCount = 1; index < N1; index++, unitCount += 1)
|
||||
indexToUnits[index] = (byte)unitCount;
|
||||
|
||||
for (unitCount++; index < N1 + N2; index++, unitCount += 2)
|
||||
indexToUnits[index] = (byte)unitCount;
|
||||
|
||||
for (unitCount++; index < N1 + N2 + N3; index++, unitCount += 3)
|
||||
indexToUnits[index] = (byte)unitCount;
|
||||
|
||||
for (unitCount++; index < N1 + N2 + N3 + N4; index++, unitCount += 4)
|
||||
indexToUnits[index] = (byte)unitCount;
|
||||
|
||||
// Construct the static units to index lookup array. It will contain the following values.
|
||||
//
|
||||
// 00 01 02 03 04 04 05 05 06 06 07 07 08 08 08 09 09 09 10 10 10 11 11 11 12 12 12 12 13 13 13 13
|
||||
// 14 14 14 14 15 15 15 15 16 16 16 16 17 17 17 17 18 18 18 18 19 19 19 19 20 20 20 20 21 21 21 21
|
||||
// 22 22 22 22 23 23 23 23 24 24 24 24 25 25 25 25 26 26 26 26 27 27 27 27 28 28 28 28 29 29 29 29
|
||||
// 30 30 30 30 31 31 31 31 32 32 32 32 33 33 33 33 34 34 34 34 35 35 35 35 36 36 36 36 37 37 37 37
|
||||
|
||||
unitsToIndex = new byte[128];
|
||||
|
||||
for (unitCount = index = 0; unitCount < 128; unitCount++)
|
||||
{
|
||||
index += (uint)((indexToUnits[index] < unitCount + 1) ? 1 : 0);
|
||||
unitsToIndex[unitCount] = (byte)index;
|
||||
}
|
||||
}
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public Allocator()
|
||||
{
|
||||
MemoryNodes = new MemoryNode[IndexCount];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize or reset the memory allocator (so that the single, large array can be re-used without destroying
|
||||
/// and re-creating it).
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
for (int index = 0; index < IndexCount; index++)
|
||||
{
|
||||
MemoryNodes[index] = new MemoryNode((uint)(NodeOffset + index * MemoryNode.Size), Memory);
|
||||
MemoryNodes[index].Stamp = 0;
|
||||
MemoryNodes[index].Next = MemoryNode.Zero;
|
||||
MemoryNodes[index].UnitCount = 0;
|
||||
}
|
||||
|
||||
Text = Heap;
|
||||
|
||||
uint difference = UnitSize * (AllocatorSize / 8 / UnitSize * 7);
|
||||
|
||||
HighUnit = Heap + AllocatorSize;
|
||||
LowUnit = HighUnit - difference;
|
||||
BaseUnit = HighUnit - difference;
|
||||
|
||||
GlueCount = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start the allocator (create a single, large array of bytes).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note that .NET will create that array on the large object heap (because it is so large).
|
||||
/// </remarks>
|
||||
/// <param name="allocatorSize"></param>
|
||||
public void Start(int allocatorSize)
|
||||
{
|
||||
uint size = (uint)allocatorSize;
|
||||
if (AllocatorSize != size)
|
||||
{
|
||||
Stop();
|
||||
Memory = new byte[HeapOffset + size]; // the single, large array of bytes
|
||||
Heap = new Pointer(HeapOffset, Memory); // reserve bytes in the range 0 .. HeapOffset - 1
|
||||
AllocatorSize = size;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop the allocator (free the single, large array of bytes). This can safely be called multiple times (without
|
||||
/// intervening calls to <see cref="Start"/>).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Because the array is on the large object heap it may not be freed immediately.
|
||||
/// </remarks>
|
||||
public void Stop()
|
||||
{
|
||||
if (AllocatorSize != 0)
|
||||
{
|
||||
AllocatorSize = 0;
|
||||
Memory = null;
|
||||
Heap = Pointer.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine how much memory (from the single, large array) is currenly in use.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public uint GetMemoryUsed()
|
||||
{
|
||||
uint memoryUsed = AllocatorSize - (HighUnit - LowUnit) - (BaseUnit - Text);
|
||||
for (uint index = 0; index < IndexCount; index++)
|
||||
memoryUsed -= UnitSize * indexToUnits[index] * MemoryNodes[index].Stamp;
|
||||
return memoryUsed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allocate a given number of units from the single, large array. Each unit is <see cref="UnitSize"/> bytes
|
||||
/// in size.
|
||||
/// </summary>
|
||||
/// <param name="unitCount"></param>
|
||||
/// <returns></returns>
|
||||
public Pointer AllocateUnits(uint unitCount)
|
||||
{
|
||||
uint index = unitsToIndex[unitCount - 1];
|
||||
if (MemoryNodes[index].Available)
|
||||
return MemoryNodes[index].Remove();
|
||||
|
||||
Pointer allocatedBlock = LowUnit;
|
||||
LowUnit += indexToUnits[index] * UnitSize;
|
||||
if (LowUnit <= HighUnit)
|
||||
return allocatedBlock;
|
||||
|
||||
LowUnit -= indexToUnits[index] * UnitSize;
|
||||
return AllocateUnitsRare(index);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allocate enough space for a PpmContext instance in the single, large array.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Pointer AllocateContext()
|
||||
{
|
||||
if (HighUnit != LowUnit)
|
||||
return (HighUnit -= UnitSize);
|
||||
else if (MemoryNodes[0].Available)
|
||||
return MemoryNodes[0].Remove();
|
||||
else
|
||||
return AllocateUnitsRare(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Increase the size of an existing allocation (represented by a <see cref="Pointer"/>).
|
||||
/// </summary>
|
||||
/// <param name="oldPointer"></param>
|
||||
/// <param name="oldUnitCount"></param>
|
||||
/// <returns></returns>
|
||||
public Pointer ExpandUnits(Pointer oldPointer, uint oldUnitCount)
|
||||
{
|
||||
uint oldIndex = unitsToIndex[oldUnitCount - 1];
|
||||
uint newIndex = unitsToIndex[oldUnitCount];
|
||||
|
||||
if (oldIndex == newIndex)
|
||||
return oldPointer;
|
||||
|
||||
Pointer pointer = AllocateUnits(oldUnitCount + 1);
|
||||
|
||||
if (pointer != Pointer.Zero)
|
||||
{
|
||||
CopyUnits(pointer, oldPointer, oldUnitCount);
|
||||
MemoryNodes[oldIndex].Insert(oldPointer, oldUnitCount);
|
||||
}
|
||||
|
||||
return pointer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrease the size of an existing allocation (represented by a <see cref="Pointer"/>).
|
||||
/// </summary>
|
||||
/// <param name="oldPointer"></param>
|
||||
/// <param name="oldUnitCount"></param>
|
||||
/// <param name="newUnitCount"></param>
|
||||
/// <returns></returns>
|
||||
public Pointer ShrinkUnits(Pointer oldPointer, uint oldUnitCount, uint newUnitCount)
|
||||
{
|
||||
uint oldIndex = unitsToIndex[oldUnitCount - 1];
|
||||
uint newIndex = unitsToIndex[newUnitCount - 1];
|
||||
|
||||
if (oldIndex == newIndex)
|
||||
return oldPointer;
|
||||
|
||||
if (MemoryNodes[newIndex].Available)
|
||||
{
|
||||
Pointer pointer = MemoryNodes[newIndex].Remove();
|
||||
CopyUnits(pointer, oldPointer, newUnitCount);
|
||||
MemoryNodes[oldIndex].Insert(oldPointer, indexToUnits[oldIndex]);
|
||||
return pointer;
|
||||
}
|
||||
else
|
||||
{
|
||||
SplitBlock(oldPointer, oldIndex, newIndex);
|
||||
return oldPointer;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Free previously allocated space (the location and amount of space to free must be specified by using
|
||||
/// a <see cref="Pointer"/> to indicate the location and a number of units to indicate the amount).
|
||||
/// </summary>
|
||||
/// <param name="pointer"></param>
|
||||
/// <param name="unitCount"></param>
|
||||
public void FreeUnits(Pointer pointer, uint unitCount)
|
||||
{
|
||||
uint index = unitsToIndex[unitCount - 1];
|
||||
MemoryNodes[index].Insert(pointer, indexToUnits[index]);
|
||||
}
|
||||
|
||||
public void SpecialFreeUnits(Pointer pointer)
|
||||
{
|
||||
if (pointer != BaseUnit)
|
||||
{
|
||||
MemoryNodes[0].Insert(pointer, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
MemoryNode memoryNode = pointer;
|
||||
memoryNode.Stamp = uint.MaxValue;
|
||||
BaseUnit += UnitSize;
|
||||
}
|
||||
}
|
||||
|
||||
public Pointer MoveUnitsUp(Pointer oldPointer, uint unitCount)
|
||||
{
|
||||
uint index = unitsToIndex[unitCount - 1];
|
||||
|
||||
if (oldPointer > BaseUnit + 16 * 1024 || oldPointer > MemoryNodes[index].Next)
|
||||
return oldPointer;
|
||||
|
||||
Pointer pointer = MemoryNodes[index].Remove();
|
||||
CopyUnits(pointer, oldPointer, unitCount);
|
||||
unitCount = indexToUnits[index];
|
||||
|
||||
if (oldPointer != BaseUnit)
|
||||
MemoryNodes[index].Insert(oldPointer, unitCount);
|
||||
else
|
||||
BaseUnit += unitCount * UnitSize;
|
||||
|
||||
return pointer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Expand the space allocated (in the single, large array) for the bytes of the data (ie. the "text") that is
|
||||
/// being encoded or decoded.
|
||||
/// </summary>
|
||||
public void ExpandText()
|
||||
{
|
||||
MemoryNode memoryNode;
|
||||
uint[] counts = new uint[IndexCount];
|
||||
|
||||
while ((memoryNode = BaseUnit).Stamp == uint.MaxValue)
|
||||
{
|
||||
BaseUnit = memoryNode + memoryNode.UnitCount;
|
||||
counts[unitsToIndex[memoryNode.UnitCount - 1]]++;
|
||||
memoryNode.Stamp = 0;
|
||||
}
|
||||
|
||||
for (uint index = 0; index < IndexCount; index++)
|
||||
{
|
||||
for (memoryNode = MemoryNodes[index]; counts[index] != 0; memoryNode = memoryNode.Next)
|
||||
{
|
||||
while (memoryNode.Next.Stamp == 0)
|
||||
{
|
||||
memoryNode.Unlink();
|
||||
MemoryNodes[index].Stamp--;
|
||||
if (--counts[index] == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private Pointer AllocateUnitsRare(uint index)
|
||||
{
|
||||
if (GlueCount == 0)
|
||||
{
|
||||
GlueFreeBlocks();
|
||||
if (MemoryNodes[index].Available)
|
||||
return MemoryNodes[index].Remove();
|
||||
}
|
||||
|
||||
uint oldIndex = index;
|
||||
do
|
||||
{
|
||||
if (++oldIndex == IndexCount)
|
||||
{
|
||||
GlueCount--;
|
||||
oldIndex = indexToUnits[index] * UnitSize;
|
||||
return (BaseUnit - Text > oldIndex) ? (BaseUnit -= oldIndex) : Pointer.Zero;
|
||||
}
|
||||
} while (!MemoryNodes[oldIndex].Available);
|
||||
|
||||
Pointer allocatedBlock = MemoryNodes[oldIndex].Remove();
|
||||
SplitBlock(allocatedBlock, oldIndex, index);
|
||||
return allocatedBlock;
|
||||
}
|
||||
|
||||
private void SplitBlock(Pointer pointer, uint oldIndex, uint newIndex)
|
||||
{
|
||||
uint unitCountDifference = (uint)(indexToUnits[oldIndex] - indexToUnits[newIndex]);
|
||||
Pointer newPointer = pointer + indexToUnits[newIndex] * UnitSize;
|
||||
|
||||
uint index = unitsToIndex[unitCountDifference - 1];
|
||||
if (indexToUnits[index] != unitCountDifference)
|
||||
{
|
||||
uint unitCount = indexToUnits[--index];
|
||||
MemoryNodes[index].Insert(newPointer, unitCount);
|
||||
newPointer += unitCount * UnitSize;
|
||||
unitCountDifference -= unitCount;
|
||||
}
|
||||
|
||||
MemoryNodes[unitsToIndex[unitCountDifference - 1]].Insert(newPointer, unitCountDifference);
|
||||
}
|
||||
|
||||
private void GlueFreeBlocks()
|
||||
{
|
||||
MemoryNode memoryNode = new MemoryNode(LocalOffset, Memory);
|
||||
memoryNode.Stamp = 0;
|
||||
memoryNode.Next = MemoryNode.Zero;
|
||||
memoryNode.UnitCount = 0;
|
||||
|
||||
MemoryNode memoryNode0;
|
||||
MemoryNode memoryNode1;
|
||||
MemoryNode memoryNode2;
|
||||
|
||||
if (LowUnit != HighUnit)
|
||||
LowUnit[0] = 0;
|
||||
|
||||
// Find all unused memory nodes.
|
||||
|
||||
memoryNode1 = memoryNode;
|
||||
for (uint index = 0; index < IndexCount; index++)
|
||||
{
|
||||
while (MemoryNodes[index].Available)
|
||||
{
|
||||
memoryNode0 = MemoryNodes[index].Remove();
|
||||
if (memoryNode0.UnitCount != 0)
|
||||
{
|
||||
while ((memoryNode2 = memoryNode0 + memoryNode0.UnitCount).Stamp == uint.MaxValue)
|
||||
{
|
||||
memoryNode0.UnitCount = memoryNode0.UnitCount + memoryNode2.UnitCount;
|
||||
memoryNode2.UnitCount = 0;
|
||||
}
|
||||
memoryNode1.Link(memoryNode0);
|
||||
memoryNode1 = memoryNode0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Coalesce the memory represented by the unused memory nodes.
|
||||
|
||||
while (memoryNode.Available)
|
||||
{
|
||||
memoryNode0 = memoryNode.Remove();
|
||||
uint unitCount = memoryNode0.UnitCount;
|
||||
if (unitCount != 0)
|
||||
{
|
||||
for (; unitCount > 128; unitCount -= 128, memoryNode0 += 128)
|
||||
MemoryNodes[IndexCount - 1].Insert(memoryNode0, 128);
|
||||
|
||||
uint index = unitsToIndex[unitCount - 1];
|
||||
if (indexToUnits[index] != unitCount)
|
||||
{
|
||||
uint unitCountDifference = unitCount - indexToUnits[--index];
|
||||
MemoryNodes[unitCountDifference - 1].Insert(memoryNode0 + (unitCount - unitCountDifference), unitCountDifference);
|
||||
}
|
||||
|
||||
MemoryNodes[index].Insert(memoryNode0, indexToUnits[index]);
|
||||
}
|
||||
}
|
||||
|
||||
GlueCount = 1 << 13;
|
||||
}
|
||||
|
||||
private void CopyUnits(Pointer target, Pointer source, uint unitCount)
|
||||
{
|
||||
do
|
||||
{
|
||||
target[0] = source[0];
|
||||
target[1] = source[1];
|
||||
target[2] = source[2];
|
||||
target[3] = source[3];
|
||||
target[4] = source[4];
|
||||
target[5] = source[5];
|
||||
target[6] = source[6];
|
||||
target[7] = source[7];
|
||||
target[8] = source[8];
|
||||
target[9] = source[9];
|
||||
target[10] = source[10];
|
||||
target[11] = source[11];
|
||||
target += UnitSize;
|
||||
source += UnitSize;
|
||||
} while (--unitCount != 0);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
100
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/I1/Coder.cs
vendored
Normal file
100
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/I1/Coder.cs
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
#region Using
|
||||
|
||||
using System.IO;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Compress.SevenZip.Compress.PPmd.I1
|
||||
{
|
||||
/// <summary>
|
||||
/// A simple range coder.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note that in most cases fields are used rather than properties for performance reasons (for example,
|
||||
/// <see cref="Scale"/> is a field rather than a property).
|
||||
/// </remarks>
|
||||
internal class Coder
|
||||
{
|
||||
private const uint RangeTop = 1 << 24;
|
||||
private const uint RangeBottom = 1 << 15;
|
||||
private uint low;
|
||||
private uint code;
|
||||
private uint range;
|
||||
|
||||
public uint LowCount;
|
||||
public uint HighCount;
|
||||
public uint Scale;
|
||||
|
||||
public void RangeEncoderInitialize()
|
||||
{
|
||||
low = 0;
|
||||
range = uint.MaxValue;
|
||||
}
|
||||
|
||||
public void RangeEncoderNormalize(Stream stream)
|
||||
{
|
||||
while ((low ^ (low + range)) < RangeTop || range < RangeBottom && ((range = (uint) -low & (RangeBottom - 1)) != 0 || true))
|
||||
{
|
||||
stream.WriteByte((byte) (low >> 24));
|
||||
range <<= 8;
|
||||
low <<= 8;
|
||||
}
|
||||
}
|
||||
|
||||
public void RangeEncodeSymbol()
|
||||
{
|
||||
low += LowCount * (range /= Scale);
|
||||
range *= HighCount - LowCount;
|
||||
}
|
||||
|
||||
public void RangeShiftEncodeSymbol(int rangeShift)
|
||||
{
|
||||
low += LowCount * (range >>= rangeShift);
|
||||
range *= HighCount - LowCount;
|
||||
}
|
||||
|
||||
public void RangeEncoderFlush(Stream stream)
|
||||
{
|
||||
for (uint index = 0; index < 4; index++)
|
||||
{
|
||||
stream.WriteByte((byte) (low >> 24));
|
||||
low <<= 8;
|
||||
}
|
||||
}
|
||||
|
||||
public void RangeDecoderInitialize(Stream stream)
|
||||
{
|
||||
low = 0;
|
||||
code = 0;
|
||||
range = uint.MaxValue;
|
||||
for (uint index = 0; index < 4; index++)
|
||||
code = (code << 8) | (byte) stream.ReadByte();
|
||||
}
|
||||
|
||||
public void RangeDecoderNormalize(Stream stream)
|
||||
{
|
||||
while ((low ^ (low + range)) < RangeTop || range < RangeBottom && ((range = (uint) -low & (RangeBottom - 1)) != 0 || true))
|
||||
{
|
||||
code = (code << 8) | (byte) stream.ReadByte();
|
||||
range <<= 8;
|
||||
low <<= 8;
|
||||
}
|
||||
}
|
||||
|
||||
public uint RangeGetCurrentCount()
|
||||
{
|
||||
return (code - low) / (range /= Scale);
|
||||
}
|
||||
|
||||
public uint RangeGetCurrentShiftCount(int rangeShift)
|
||||
{
|
||||
return (code - low) / (range >>= rangeShift);
|
||||
}
|
||||
|
||||
public void RangeRemoveSubrange()
|
||||
{
|
||||
low += range * LowCount;
|
||||
range *= HighCount - LowCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
246
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/I1/MemoryNode.cs
vendored
Normal file
246
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/I1/MemoryNode.cs
vendored
Normal file
@@ -0,0 +1,246 @@
|
||||
#region Using
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Compress.SevenZip.Compress.PPmd.I1
|
||||
{
|
||||
/// <summary>
|
||||
/// A structure containing a single address. The address represents a location in the <see cref="Memory"/>
|
||||
/// array. That location in the <see cref="Memory"/> array contains information itself describing a section
|
||||
/// of the <see cref="Memory"/> array (ie. a block of memory).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This must be a structure rather than a class because several places in the associated code assume that
|
||||
/// <see cref="MemoryNode"/> is a value type (meaning that assignment creates a completely new copy of
|
||||
/// the instance rather than just copying a reference to the same instance).
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// MemoryNode
|
||||
/// 4 Stamp
|
||||
/// 4 Next
|
||||
/// 4 UnitCount
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Note that <see cref="Address"/> is a field rather than a property for performance reasons.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
internal struct MemoryNode
|
||||
{
|
||||
public uint Address;
|
||||
public byte[] Memory;
|
||||
public static readonly MemoryNode Zero = new MemoryNode(0, null);
|
||||
public const int Size = 12;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MemoryNode"/> structure.
|
||||
/// </summary>
|
||||
public MemoryNode(uint address, byte[] memory)
|
||||
{
|
||||
Address = address;
|
||||
Memory = memory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the stamp.
|
||||
/// </summary>
|
||||
public uint Stamp
|
||||
{
|
||||
get { return ((uint) Memory[Address]) | ((uint) Memory[Address + 1]) << 8 | ((uint) Memory[Address + 2]) << 16 | ((uint) Memory[Address + 3]) << 24; }
|
||||
set
|
||||
{
|
||||
Memory[Address] = (byte) value;
|
||||
Memory[Address + 1] = (byte) (value >> 8);
|
||||
Memory[Address + 2] = (byte) (value >> 16);
|
||||
Memory[Address + 3] = (byte) (value >> 24);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the next memory node.
|
||||
/// </summary>
|
||||
public MemoryNode Next
|
||||
{
|
||||
get { return new MemoryNode(((uint) Memory[Address + 4]) | ((uint) Memory[Address + 5]) << 8 | ((uint) Memory[Address + 6]) << 16 | ((uint) Memory[Address + 7]) << 24, Memory); }
|
||||
set
|
||||
{
|
||||
Memory[Address + 4] = (byte) value.Address;
|
||||
Memory[Address + 5] = (byte) (value.Address >> 8);
|
||||
Memory[Address + 6] = (byte) (value.Address >> 16);
|
||||
Memory[Address + 7] = (byte) (value.Address >> 24);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the unit count.
|
||||
/// </summary>
|
||||
public uint UnitCount
|
||||
{
|
||||
get { return ((uint) Memory[Address + 8]) | ((uint) Memory[Address + 9]) << 8 | ((uint) Memory[Address + 10]) << 16 | ((uint) Memory[Address + 11]) << 24; }
|
||||
set
|
||||
{
|
||||
Memory[Address + 8] = (byte) value;
|
||||
Memory[Address + 9] = (byte) (value >> 8);
|
||||
Memory[Address + 10] = (byte) (value >> 16);
|
||||
Memory[Address + 11] = (byte) (value >> 24);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether there is a next memory node available.
|
||||
/// </summary>
|
||||
public bool Available
|
||||
{
|
||||
get { return Next.Address != 0; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Link in the provided memory node.
|
||||
/// </summary>
|
||||
/// <param name="memoryNode"></param>
|
||||
public void Link(MemoryNode memoryNode)
|
||||
{
|
||||
memoryNode.Next = Next;
|
||||
Next = memoryNode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unlink this memory node.
|
||||
/// </summary>
|
||||
public void Unlink()
|
||||
{
|
||||
Next = Next.Next;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Insert the memory node into the linked list.
|
||||
/// </summary>
|
||||
/// <param name="memoryNode"></param>
|
||||
/// <param name="unitCount"></param>
|
||||
public void Insert(MemoryNode memoryNode, uint unitCount)
|
||||
{
|
||||
Link(memoryNode);
|
||||
memoryNode.Stamp = uint.MaxValue;
|
||||
memoryNode.UnitCount = unitCount;
|
||||
Stamp++;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove this memory node from the linked list.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public MemoryNode Remove()
|
||||
{
|
||||
MemoryNode next = Next;
|
||||
Unlink();
|
||||
Stamp--;
|
||||
return next;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allow a pointer to be implicitly converted to a memory node.
|
||||
/// </summary>
|
||||
/// <param name="pointer"></param>
|
||||
/// <returns></returns>
|
||||
public static implicit operator MemoryNode(Pointer pointer)
|
||||
{
|
||||
return new MemoryNode(pointer.Address, pointer.Memory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allow pointer-like addition on a memory node.
|
||||
/// </summary>
|
||||
/// <param name="memoryNode"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns></returns>
|
||||
public static MemoryNode operator +(MemoryNode memoryNode, int offset)
|
||||
{
|
||||
memoryNode.Address = (uint) (memoryNode.Address + offset * Size);
|
||||
return memoryNode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allow pointer-like addition on a memory node.
|
||||
/// </summary>
|
||||
/// <param name="memoryNode"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns></returns>
|
||||
public static MemoryNode operator +(MemoryNode memoryNode, uint offset)
|
||||
{
|
||||
memoryNode.Address += offset * Size;
|
||||
return memoryNode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allow pointer-like subtraction on a memory node.
|
||||
/// </summary>
|
||||
/// <param name="memoryNode"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns></returns>
|
||||
public static MemoryNode operator -(MemoryNode memoryNode, int offset)
|
||||
{
|
||||
memoryNode.Address = (uint) (memoryNode.Address - offset * Size);
|
||||
return memoryNode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allow pointer-like subtraction on a memory node.
|
||||
/// </summary>
|
||||
/// <param name="memoryNode"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns></returns>
|
||||
public static MemoryNode operator -(MemoryNode memoryNode, uint offset)
|
||||
{
|
||||
memoryNode.Address -= offset * Size;
|
||||
return memoryNode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compare two memory nodes.
|
||||
/// </summary>
|
||||
/// <param name="memoryNode1"></param>
|
||||
/// <param name="memoryNode2"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator ==(MemoryNode memoryNode1, MemoryNode memoryNode2)
|
||||
{
|
||||
return memoryNode1.Address == memoryNode2.Address;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compare two memory nodes.
|
||||
/// </summary>
|
||||
/// <param name="memoryNode1"></param>
|
||||
/// <param name="memoryNode2"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator !=(MemoryNode memoryNode1, MemoryNode memoryNode2)
|
||||
{
|
||||
return memoryNode1.Address != memoryNode2.Address;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether this instance and a specified object are equal.
|
||||
/// </summary>
|
||||
/// <returns>true if obj and this instance are the same type and represent the same value; otherwise, false.</returns>
|
||||
/// <param name="obj">Another object to compare to.</param>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is MemoryNode)
|
||||
{
|
||||
MemoryNode memoryNode = (MemoryNode) obj;
|
||||
return memoryNode.Address == Address;
|
||||
}
|
||||
return base.Equals(obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the hash code for this instance.
|
||||
/// </summary>
|
||||
/// <returns>A 32-bit signed integer that is the hash code for this instance.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Address.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
819
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/I1/Model.cs
vendored
Normal file
819
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/I1/Model.cs
vendored
Normal file
@@ -0,0 +1,819 @@
|
||||
#region Using
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
#endregion
|
||||
|
||||
// This is a port of Dmitry Shkarin's PPMd Variant I Revision 1.
|
||||
// Ported by Michael Bone (mjbone03@yahoo.com.au).
|
||||
namespace Compress.SevenZip.Compress.PPmd.I1
|
||||
{
|
||||
/// <summary>
|
||||
/// The model.
|
||||
/// </summary>
|
||||
internal partial class Model
|
||||
{
|
||||
public const uint Signature = 0x84acaf8fU;
|
||||
public const char Variant = 'I';
|
||||
public const int MaximumOrder = 16; // maximum allowed model order
|
||||
|
||||
private const byte UpperFrequency = 5;
|
||||
private const byte IntervalBitCount = 7;
|
||||
private const byte PeriodBitCount = 7;
|
||||
private const byte TotalBitCount = IntervalBitCount + PeriodBitCount;
|
||||
private const uint Interval = 1 << IntervalBitCount;
|
||||
private const uint BinaryScale = 1 << TotalBitCount;
|
||||
private const uint MaximumFrequency = 124;
|
||||
private const uint OrderBound = 9;
|
||||
|
||||
private See2Context[,] see2Contexts;
|
||||
private See2Context emptySee2Context;
|
||||
private PpmContext maximumContext;
|
||||
private ushort[,] binarySummary = new ushort[25, 64]; // binary SEE-contexts
|
||||
private byte[] numberStatisticsToBinarySummaryIndex = new byte[256];
|
||||
private byte[] probabilities = new byte[260];
|
||||
private byte[] characterMask = new byte[256];
|
||||
private byte escapeCount;
|
||||
private int modelOrder;
|
||||
private int orderFall;
|
||||
private int initialEscape;
|
||||
private int initialRunLength;
|
||||
private int runLength;
|
||||
private byte previousSuccess;
|
||||
private byte numberMasked;
|
||||
private ModelRestorationMethod method;
|
||||
private PpmState foundState; // found next state transition
|
||||
|
||||
private Allocator Allocator;
|
||||
private Coder Coder;
|
||||
private PpmContext minimumContext;
|
||||
private byte numberStatistics;
|
||||
private PpmState[] decodeStates = new PpmState[256];
|
||||
|
||||
private static readonly ushort[] InitialBinaryEscapes = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051 };
|
||||
private static readonly byte[] ExponentialEscapes = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public Model()
|
||||
{
|
||||
// Construct the conversion table for number statistics. Initially it will contain the following values.
|
||||
//
|
||||
// 0 2 4 4 4 4 4 4 4 4 4 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
|
||||
// 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
|
||||
// 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
|
||||
// 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
|
||||
// 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
|
||||
// 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
|
||||
// 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
|
||||
// 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
|
||||
|
||||
numberStatisticsToBinarySummaryIndex[0] = 2 * 0;
|
||||
numberStatisticsToBinarySummaryIndex[1] = 2 * 1;
|
||||
for (int index = 2; index < 11; index++)
|
||||
numberStatisticsToBinarySummaryIndex[index] = 2 * 2;
|
||||
for (int index = 11; index < 256; index++)
|
||||
numberStatisticsToBinarySummaryIndex[index] = 2 * 3;
|
||||
|
||||
// Construct the probability table. Initially it will contain the following values (depending on the value of
|
||||
// the upper frequency).
|
||||
//
|
||||
// 00 01 02 03 04 05 06 06 07 07 07 08 08 08 08 09 09 09 09 09 10 10 10 10 10 10 11 11 11 11 11 11
|
||||
// 11 12 12 12 12 12 12 12 12 13 13 13 13 13 13 13 13 13 14 14 14 14 14 14 14 14 14 14 15 15 15 15
|
||||
// 15 15 15 15 15 15 15 16 16 16 16 16 16 16 16 16 16 16 16 17 17 17 17 17 17 17 17 17 17 17 17 17
|
||||
// 18 18 18 18 18 18 18 18 18 18 18 18 18 18 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 20 20 20
|
||||
// 20 20 20 20 20 20 20 20 20 20 20 20 20 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 22 22
|
||||
// 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23
|
||||
// 23 23 23 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 25 25 25 25 25 25 25 25 25
|
||||
// 25 25 25 25 25 25 25 25 25 25 25 25 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26
|
||||
// 26 26 27 27
|
||||
|
||||
uint count = 1;
|
||||
uint step = 1;
|
||||
uint probability = UpperFrequency;
|
||||
|
||||
for (int index = 0; index < UpperFrequency; index++)
|
||||
probabilities[index] = (byte)index;
|
||||
|
||||
for (int index = UpperFrequency; index < 260; index++)
|
||||
{
|
||||
probabilities[index] = (byte)probability;
|
||||
count--;
|
||||
if (count == 0)
|
||||
{
|
||||
step++;
|
||||
count = step;
|
||||
probability++;
|
||||
}
|
||||
}
|
||||
|
||||
// Create the context array.
|
||||
|
||||
see2Contexts = new See2Context[24, 32];
|
||||
for (int index1 = 0; index1 < 24; index1++)
|
||||
for (int index2 = 0; index2 < 32; index2++)
|
||||
see2Contexts[index1, index2] = new See2Context();
|
||||
|
||||
// Set the signature (identifying the algorithm).
|
||||
|
||||
emptySee2Context = new See2Context();
|
||||
emptySee2Context.Summary = (ushort)(Signature & 0x0000ffff);
|
||||
emptySee2Context.Shift = (byte)((Signature >> 16) & 0x000000ff);
|
||||
emptySee2Context.Count = (byte)(Signature >> 24);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encode (ie. compress) a given source stream, writing the encoded result to the target stream.
|
||||
/// </summary>
|
||||
public void Encode(Stream target, Stream source, PpmdProperties properties)
|
||||
{
|
||||
if (target == null)
|
||||
throw new ArgumentNullException("target");
|
||||
|
||||
if (source == null)
|
||||
throw new ArgumentNullException("source");
|
||||
|
||||
EncodeStart(properties);
|
||||
EncodeBlock(target, source, true);
|
||||
}
|
||||
|
||||
internal Coder EncodeStart(PpmdProperties properties)
|
||||
{
|
||||
Allocator = properties.Allocator;
|
||||
Coder = new Coder();
|
||||
Coder.RangeEncoderInitialize();
|
||||
StartModel(properties.ModelOrder, properties.ModelRestorationMethod);
|
||||
return Coder;
|
||||
}
|
||||
|
||||
internal void EncodeBlock(Stream target, Stream source, bool final)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
minimumContext = maximumContext;
|
||||
numberStatistics = minimumContext.NumberStatistics;
|
||||
|
||||
int c = source.ReadByte();
|
||||
if (c < 0 && !final)
|
||||
return;
|
||||
|
||||
if (numberStatistics != 0)
|
||||
{
|
||||
EncodeSymbol1(c, minimumContext);
|
||||
Coder.RangeEncodeSymbol();
|
||||
}
|
||||
else
|
||||
{
|
||||
EncodeBinarySymbol(c, minimumContext);
|
||||
Coder.RangeShiftEncodeSymbol(TotalBitCount);
|
||||
}
|
||||
|
||||
while (foundState == PpmState.Zero)
|
||||
{
|
||||
Coder.RangeEncoderNormalize(target);
|
||||
do
|
||||
{
|
||||
orderFall++;
|
||||
minimumContext = minimumContext.Suffix;
|
||||
if (minimumContext == PpmContext.Zero)
|
||||
goto StopEncoding;
|
||||
} while (minimumContext.NumberStatistics == numberMasked);
|
||||
EncodeSymbol2(c, minimumContext);
|
||||
Coder.RangeEncodeSymbol();
|
||||
}
|
||||
|
||||
if (orderFall == 0 && (Pointer)foundState.Successor >= Allocator.BaseUnit)
|
||||
{
|
||||
maximumContext = foundState.Successor;
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateModel(minimumContext);
|
||||
if (escapeCount == 0)
|
||||
ClearMask();
|
||||
}
|
||||
|
||||
Coder.RangeEncoderNormalize(target);
|
||||
}
|
||||
|
||||
StopEncoding:
|
||||
Coder.RangeEncoderFlush(target);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Dencode (ie. decompress) a given source stream, writing the decoded result to the target stream.
|
||||
/// </summary>
|
||||
public void Decode(Stream target, Stream source, PpmdProperties properties)
|
||||
{
|
||||
if (target == null)
|
||||
throw new ArgumentNullException("target");
|
||||
|
||||
if (source == null)
|
||||
throw new ArgumentNullException("source");
|
||||
|
||||
DecodeStart(source, properties);
|
||||
byte[] buffer = new byte[65536];
|
||||
int read;
|
||||
while ((read = DecodeBlock(source, buffer, 0, buffer.Length)) != 0)
|
||||
target.Write(buffer, 0, read);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
internal Coder DecodeStart(Stream source, PpmdProperties properties)
|
||||
{
|
||||
Allocator = properties.Allocator;
|
||||
Coder = new Coder();
|
||||
Coder.RangeDecoderInitialize(source);
|
||||
StartModel(properties.ModelOrder, properties.ModelRestorationMethod);
|
||||
minimumContext = maximumContext;
|
||||
numberStatistics = minimumContext.NumberStatistics;
|
||||
return Coder;
|
||||
}
|
||||
|
||||
internal int DecodeBlock(Stream source, byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (minimumContext == PpmContext.Zero)
|
||||
return 0;
|
||||
|
||||
int total = 0;
|
||||
while (total < count)
|
||||
{
|
||||
if (numberStatistics != 0)
|
||||
DecodeSymbol1(minimumContext);
|
||||
else
|
||||
DecodeBinarySymbol(minimumContext);
|
||||
|
||||
Coder.RangeRemoveSubrange();
|
||||
|
||||
while (foundState == PpmState.Zero)
|
||||
{
|
||||
Coder.RangeDecoderNormalize(source);
|
||||
do
|
||||
{
|
||||
orderFall++;
|
||||
minimumContext = minimumContext.Suffix;
|
||||
if (minimumContext == PpmContext.Zero)
|
||||
goto StopDecoding;
|
||||
} while (minimumContext.NumberStatistics == numberMasked);
|
||||
DecodeSymbol2(minimumContext);
|
||||
Coder.RangeRemoveSubrange();
|
||||
}
|
||||
|
||||
buffer[offset] = foundState.Symbol;
|
||||
offset++;
|
||||
total++;
|
||||
|
||||
if (orderFall == 0 && (Pointer)foundState.Successor >= Allocator.BaseUnit)
|
||||
{
|
||||
maximumContext = foundState.Successor;
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateModel(minimumContext);
|
||||
if (escapeCount == 0)
|
||||
ClearMask();
|
||||
}
|
||||
|
||||
minimumContext = maximumContext;
|
||||
numberStatistics = minimumContext.NumberStatistics;
|
||||
Coder.RangeDecoderNormalize(source);
|
||||
}
|
||||
|
||||
StopDecoding:
|
||||
return total;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
/// Initialise the model (unless the model order is set to 1 in which case the model should be cleared so that
|
||||
/// the statistics are carried over, allowing "solid" mode compression).
|
||||
/// </summary>
|
||||
private void StartModel(int modelOrder, ModelRestorationMethod modelRestorationMethod)
|
||||
{
|
||||
Array.Clear(characterMask, 0, characterMask.Length);
|
||||
escapeCount = 1;
|
||||
|
||||
// Compress in "solid" mode if the model order value is set to 1 (this will examine the current PPM context
|
||||
// structures to determine the value of orderFall).
|
||||
|
||||
if (modelOrder < 2)
|
||||
{
|
||||
orderFall = this.modelOrder;
|
||||
for (PpmContext context = maximumContext; context.Suffix != PpmContext.Zero; context = context.Suffix)
|
||||
orderFall--;
|
||||
return;
|
||||
}
|
||||
|
||||
this.modelOrder = modelOrder;
|
||||
orderFall = modelOrder;
|
||||
method = modelRestorationMethod;
|
||||
Allocator.Initialize();
|
||||
initialRunLength = -((modelOrder < 12) ? modelOrder : 12) - 1;
|
||||
runLength = initialRunLength;
|
||||
|
||||
// Allocate the context structure.
|
||||
|
||||
maximumContext = Allocator.AllocateContext();
|
||||
maximumContext.Suffix = PpmContext.Zero;
|
||||
maximumContext.NumberStatistics = 255;
|
||||
maximumContext.SummaryFrequency = (ushort)(maximumContext.NumberStatistics + 2);
|
||||
maximumContext.Statistics = Allocator.AllocateUnits(256 / 2); // allocates enough space for 256 PPM states (each is 6 bytes)
|
||||
|
||||
previousSuccess = 0;
|
||||
for (int index = 0; index < 256; index++)
|
||||
{
|
||||
PpmState state = maximumContext.Statistics[index];
|
||||
state.Symbol = (byte)index;
|
||||
state.Frequency = 1;
|
||||
state.Successor = PpmContext.Zero;
|
||||
}
|
||||
|
||||
uint probability = 0;
|
||||
for (int index1 = 0; probability < 25; probability++)
|
||||
{
|
||||
while (probabilities[index1] == probability)
|
||||
index1++;
|
||||
for (int index2 = 0; index2 < 8; index2++)
|
||||
binarySummary[probability, index2] = (ushort)(BinaryScale - InitialBinaryEscapes[index2] / (index1 + 1));
|
||||
for (int index2 = 8; index2 < 64; index2 += 8)
|
||||
for (int index3 = 0; index3 < 8; index3++)
|
||||
binarySummary[probability, index2 + index3] = binarySummary[probability, index3];
|
||||
}
|
||||
|
||||
probability = 0;
|
||||
for (uint index1 = 0; probability < 24; probability++)
|
||||
{
|
||||
while (probabilities[index1 + 3] == probability + 3)
|
||||
index1++;
|
||||
for (int index2 = 0; index2 < 32; index2++)
|
||||
see2Contexts[probability, index2].Initialize(2 * index1 + 5);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateModel(PpmContext minimumContext)
|
||||
{
|
||||
PpmState state = PpmState.Zero;
|
||||
PpmContext Successor;
|
||||
PpmContext currentContext = maximumContext;
|
||||
uint numberStatistics;
|
||||
uint ns1;
|
||||
uint cf;
|
||||
uint sf;
|
||||
uint s0;
|
||||
uint foundStateFrequency = foundState.Frequency;
|
||||
byte foundStateSymbol = foundState.Symbol;
|
||||
byte symbol;
|
||||
byte flag;
|
||||
|
||||
PpmContext foundStateSuccessor = foundState.Successor;
|
||||
PpmContext context = minimumContext.Suffix;
|
||||
|
||||
if ((foundStateFrequency < MaximumFrequency / 4) && (context != PpmContext.Zero))
|
||||
{
|
||||
if (context.NumberStatistics != 0)
|
||||
{
|
||||
state = context.Statistics;
|
||||
if (state.Symbol != foundStateSymbol)
|
||||
{
|
||||
do
|
||||
{
|
||||
symbol = state[1].Symbol;
|
||||
state++;
|
||||
} while (symbol != foundStateSymbol);
|
||||
if (state[0].Frequency >= state[-1].Frequency)
|
||||
{
|
||||
Swap(state[0], state[-1]);
|
||||
state--;
|
||||
}
|
||||
}
|
||||
cf = (uint)((state.Frequency < MaximumFrequency - 9) ? 2 : 0);
|
||||
state.Frequency += (byte)cf;
|
||||
context.SummaryFrequency += (byte)cf;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = context.FirstState;
|
||||
state.Frequency += (byte)((state.Frequency < 32) ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (orderFall == 0 && foundStateSuccessor != PpmContext.Zero)
|
||||
{
|
||||
foundState.Successor = CreateSuccessors(true, state, minimumContext);
|
||||
if (foundState.Successor == PpmContext.Zero)
|
||||
goto RestartModel;
|
||||
maximumContext = foundState.Successor;
|
||||
return;
|
||||
}
|
||||
|
||||
Allocator.Text[0] = foundStateSymbol;
|
||||
Allocator.Text++;
|
||||
Successor = Allocator.Text;
|
||||
|
||||
if (Allocator.Text >= Allocator.BaseUnit)
|
||||
goto RestartModel;
|
||||
|
||||
if (foundStateSuccessor != PpmContext.Zero)
|
||||
{
|
||||
if (foundStateSuccessor < Allocator.BaseUnit)
|
||||
foundStateSuccessor = CreateSuccessors(false, state, minimumContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
foundStateSuccessor = ReduceOrder(state, minimumContext);
|
||||
}
|
||||
|
||||
if (foundStateSuccessor == PpmContext.Zero)
|
||||
goto RestartModel;
|
||||
|
||||
if (--orderFall == 0)
|
||||
{
|
||||
Successor = foundStateSuccessor;
|
||||
Allocator.Text -= (maximumContext != minimumContext) ? 1 : 0;
|
||||
}
|
||||
else if (method > ModelRestorationMethod.Freeze)
|
||||
{
|
||||
Successor = foundStateSuccessor;
|
||||
Allocator.Text = Allocator.Heap;
|
||||
orderFall = 0;
|
||||
}
|
||||
|
||||
numberStatistics = minimumContext.NumberStatistics;
|
||||
s0 = minimumContext.SummaryFrequency - numberStatistics - foundStateFrequency;
|
||||
flag = (byte)((foundStateSymbol >= 0x40) ? 0x08 : 0x00);
|
||||
for (; currentContext != minimumContext; currentContext = currentContext.Suffix)
|
||||
{
|
||||
ns1 = currentContext.NumberStatistics;
|
||||
if (ns1 != 0)
|
||||
{
|
||||
if ((ns1 & 1) != 0)
|
||||
{
|
||||
state = Allocator.ExpandUnits(currentContext.Statistics, (ns1 + 1) >> 1);
|
||||
if (state == PpmState.Zero)
|
||||
goto RestartModel;
|
||||
currentContext.Statistics = state;
|
||||
}
|
||||
currentContext.SummaryFrequency += (ushort)((3 * ns1 + 1 < numberStatistics) ? 1 : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
state = Allocator.AllocateUnits(1);
|
||||
if (state == PpmState.Zero)
|
||||
goto RestartModel;
|
||||
Copy(state, currentContext.FirstState);
|
||||
currentContext.Statistics = state;
|
||||
if (state.Frequency < MaximumFrequency / 4 - 1)
|
||||
state.Frequency += state.Frequency;
|
||||
else
|
||||
state.Frequency = (byte)(MaximumFrequency - 4);
|
||||
currentContext.SummaryFrequency = (ushort)(state.Frequency + initialEscape + ((numberStatistics > 2) ? 1 : 0));
|
||||
}
|
||||
|
||||
cf = (uint)(2 * foundStateFrequency * (currentContext.SummaryFrequency + 6));
|
||||
sf = s0 + currentContext.SummaryFrequency;
|
||||
|
||||
if (cf < 6 * sf)
|
||||
{
|
||||
cf = (uint)(1 + ((cf > sf) ? 1 : 0) + ((cf >= 4 * sf) ? 1 : 0));
|
||||
currentContext.SummaryFrequency += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
cf = (uint)(4 + ((cf > 9 * sf) ? 1 : 0) + ((cf > 12 * sf) ? 1 : 0) + ((cf > 15 * sf) ? 1 : 0));
|
||||
currentContext.SummaryFrequency += (ushort)cf;
|
||||
}
|
||||
|
||||
state = currentContext.Statistics + (++currentContext.NumberStatistics);
|
||||
state.Successor = Successor;
|
||||
state.Symbol = foundStateSymbol;
|
||||
state.Frequency = (byte)cf;
|
||||
currentContext.Flags |= flag;
|
||||
}
|
||||
|
||||
maximumContext = foundStateSuccessor;
|
||||
return;
|
||||
|
||||
RestartModel:
|
||||
RestoreModel(currentContext, minimumContext, foundStateSuccessor);
|
||||
}
|
||||
|
||||
private PpmContext CreateSuccessors(bool skip, PpmState state, PpmContext context)
|
||||
{
|
||||
PpmContext upBranch = foundState.Successor;
|
||||
PpmState[] states = new PpmState[MaximumOrder];
|
||||
uint stateIndex = 0;
|
||||
byte symbol = foundState.Symbol;
|
||||
|
||||
if (!skip)
|
||||
{
|
||||
states[stateIndex++] = foundState;
|
||||
if (context.Suffix == PpmContext.Zero)
|
||||
goto NoLoop;
|
||||
}
|
||||
|
||||
bool gotoLoopEntry = false;
|
||||
if (state != PpmState.Zero)
|
||||
{
|
||||
context = context.Suffix;
|
||||
gotoLoopEntry = true;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if (gotoLoopEntry)
|
||||
{
|
||||
gotoLoopEntry = false;
|
||||
goto LoopEntry;
|
||||
}
|
||||
|
||||
context = context.Suffix;
|
||||
if (context.NumberStatistics != 0)
|
||||
{
|
||||
byte temporary;
|
||||
state = context.Statistics;
|
||||
if (state.Symbol != symbol)
|
||||
{
|
||||
do
|
||||
{
|
||||
temporary = state[1].Symbol;
|
||||
state++;
|
||||
} while (temporary != symbol);
|
||||
}
|
||||
temporary = (byte)((state.Frequency < MaximumFrequency - 9) ? 1 : 0);
|
||||
state.Frequency += temporary;
|
||||
context.SummaryFrequency += temporary;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = context.FirstState;
|
||||
state.Frequency += (byte)(((context.Suffix.NumberStatistics == 0) ? 1 : 0) & ((state.Frequency < 24) ? 1 : 0));
|
||||
}
|
||||
|
||||
LoopEntry:
|
||||
if (state.Successor != upBranch)
|
||||
{
|
||||
context = state.Successor;
|
||||
break;
|
||||
}
|
||||
states[stateIndex++] = state;
|
||||
} while (context.Suffix != PpmContext.Zero);
|
||||
|
||||
NoLoop:
|
||||
if (stateIndex == 0)
|
||||
return context;
|
||||
|
||||
byte localNumberStatistics = 0;
|
||||
byte localFlags = (byte)((symbol >= 0x40) ? 0x10 : 0x00);
|
||||
symbol = upBranch.NumberStatistics;
|
||||
byte localSymbol = symbol;
|
||||
byte localFrequency;
|
||||
PpmContext localSuccessor = ((Pointer)upBranch) + 1;
|
||||
localFlags |= (byte)((symbol >= 0x40) ? 0x08 : 0x00);
|
||||
|
||||
if (context.NumberStatistics != 0)
|
||||
{
|
||||
state = context.Statistics;
|
||||
if (state.Symbol != symbol)
|
||||
{
|
||||
byte temporary;
|
||||
do
|
||||
{
|
||||
temporary = state[1].Symbol;
|
||||
state++;
|
||||
} while (temporary != symbol);
|
||||
}
|
||||
uint cf = (uint)(state.Frequency - 1);
|
||||
uint s0 = (uint)(context.SummaryFrequency - context.NumberStatistics - cf);
|
||||
localFrequency = (byte)(1 + ((2 * cf <= s0) ? (uint)((5 * cf > s0) ? 1 : 0) : ((cf + 2 * s0 - 3) / s0)));
|
||||
}
|
||||
else
|
||||
{
|
||||
localFrequency = context.FirstStateFrequency;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
PpmContext currentContext = Allocator.AllocateContext();
|
||||
if (currentContext == PpmContext.Zero)
|
||||
return PpmContext.Zero;
|
||||
currentContext.NumberStatistics = localNumberStatistics;
|
||||
currentContext.Flags = localFlags;
|
||||
currentContext.FirstStateSymbol = localSymbol;
|
||||
currentContext.FirstStateFrequency = localFrequency;
|
||||
currentContext.FirstStateSuccessor = localSuccessor;
|
||||
currentContext.Suffix = context;
|
||||
context = currentContext;
|
||||
states[--stateIndex].Successor = context;
|
||||
} while (stateIndex != 0);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
private PpmContext ReduceOrder(PpmState state, PpmContext context)
|
||||
{
|
||||
PpmState currentState;
|
||||
PpmState[] states = new PpmState[MaximumOrder];
|
||||
uint stateIndex = 0;
|
||||
PpmContext currentContext = context;
|
||||
PpmContext UpBranch = Allocator.Text;
|
||||
byte temporary;
|
||||
byte symbol = foundState.Symbol;
|
||||
|
||||
states[stateIndex++] = foundState;
|
||||
foundState.Successor = UpBranch;
|
||||
orderFall++;
|
||||
|
||||
bool gotoLoopEntry = false;
|
||||
if (state != PpmState.Zero)
|
||||
{
|
||||
context = context.Suffix;
|
||||
gotoLoopEntry = true;
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (gotoLoopEntry)
|
||||
{
|
||||
gotoLoopEntry = false;
|
||||
goto LoopEntry;
|
||||
}
|
||||
|
||||
if (context.Suffix == PpmContext.Zero)
|
||||
{
|
||||
if (method > ModelRestorationMethod.Freeze)
|
||||
{
|
||||
do
|
||||
{
|
||||
states[--stateIndex].Successor = context;
|
||||
} while (stateIndex != 0);
|
||||
Allocator.Text = Allocator.Heap + 1;
|
||||
orderFall = 1;
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
context = context.Suffix;
|
||||
if (context.NumberStatistics != 0)
|
||||
{
|
||||
state = context.Statistics;
|
||||
if (state.Symbol != symbol)
|
||||
{
|
||||
do
|
||||
{
|
||||
temporary = state[1].Symbol;
|
||||
state++;
|
||||
} while (temporary != symbol);
|
||||
}
|
||||
temporary = (byte)((state.Frequency < MaximumFrequency - 9) ? 2 : 0);
|
||||
state.Frequency += temporary;
|
||||
context.SummaryFrequency += temporary;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = context.FirstState;
|
||||
state.Frequency += (byte)((state.Frequency < 32) ? 1 : 0);
|
||||
}
|
||||
|
||||
LoopEntry:
|
||||
if (state.Successor != PpmContext.Zero)
|
||||
break;
|
||||
states[stateIndex++] = state;
|
||||
state.Successor = UpBranch;
|
||||
orderFall++;
|
||||
}
|
||||
|
||||
if (method > ModelRestorationMethod.Freeze)
|
||||
{
|
||||
context = state.Successor;
|
||||
do
|
||||
{
|
||||
states[--stateIndex].Successor = context;
|
||||
} while (stateIndex != 0);
|
||||
Allocator.Text = Allocator.Heap + 1;
|
||||
orderFall = 1;
|
||||
return context;
|
||||
}
|
||||
else if (state.Successor <= UpBranch)
|
||||
{
|
||||
currentState = foundState;
|
||||
foundState = state;
|
||||
state.Successor = CreateSuccessors(false, PpmState.Zero, context);
|
||||
foundState = currentState;
|
||||
}
|
||||
|
||||
if (orderFall == 1 && currentContext == maximumContext)
|
||||
{
|
||||
foundState.Successor = state.Successor;
|
||||
Allocator.Text--;
|
||||
}
|
||||
|
||||
return state.Successor;
|
||||
}
|
||||
|
||||
private void RestoreModel(PpmContext context, PpmContext minimumContext, PpmContext foundStateSuccessor)
|
||||
{
|
||||
PpmContext currentContext;
|
||||
|
||||
Allocator.Text = Allocator.Heap;
|
||||
for (currentContext = maximumContext; currentContext != context; currentContext = currentContext.Suffix)
|
||||
{
|
||||
if (--currentContext.NumberStatistics == 0)
|
||||
{
|
||||
currentContext.Flags = (byte)((currentContext.Flags & 0x10) + ((currentContext.Statistics.Symbol >= 0x40) ? 0x08 : 0x00));
|
||||
PpmState state = currentContext.Statistics;
|
||||
Copy(currentContext.FirstState, state);
|
||||
Allocator.SpecialFreeUnits(state);
|
||||
currentContext.FirstStateFrequency = (byte)((currentContext.FirstStateFrequency + 11) >> 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
Refresh((uint)((currentContext.NumberStatistics + 3) >> 1), false, currentContext);
|
||||
}
|
||||
}
|
||||
|
||||
for (; currentContext != minimumContext; currentContext = currentContext.Suffix)
|
||||
{
|
||||
if (currentContext.NumberStatistics == 0)
|
||||
currentContext.FirstStateFrequency -= (byte)(currentContext.FirstStateFrequency >> 1);
|
||||
else if ((currentContext.SummaryFrequency += 4) > 128 + 4 * currentContext.NumberStatistics)
|
||||
Refresh((uint)((currentContext.NumberStatistics + 2) >> 1), true, currentContext);
|
||||
}
|
||||
|
||||
if (method > ModelRestorationMethod.Freeze)
|
||||
{
|
||||
maximumContext = foundStateSuccessor;
|
||||
Allocator.GlueCount += (uint)(((Allocator.MemoryNodes[1].Stamp & 1) == 0) ? 1 : 0);
|
||||
}
|
||||
else if (method == ModelRestorationMethod.Freeze)
|
||||
{
|
||||
while (maximumContext.Suffix != PpmContext.Zero)
|
||||
maximumContext = maximumContext.Suffix;
|
||||
|
||||
RemoveBinaryContexts(0, maximumContext);
|
||||
method = (ModelRestorationMethod)(method + 1);
|
||||
Allocator.GlueCount = 0;
|
||||
orderFall = modelOrder;
|
||||
}
|
||||
else if (method == ModelRestorationMethod.Restart || Allocator.GetMemoryUsed() < (Allocator.AllocatorSize >> 1))
|
||||
{
|
||||
StartModel(modelOrder, method);
|
||||
escapeCount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (maximumContext.Suffix != PpmContext.Zero)
|
||||
maximumContext = maximumContext.Suffix;
|
||||
|
||||
do
|
||||
{
|
||||
CutOff(0, maximumContext);
|
||||
Allocator.ExpandText();
|
||||
} while (Allocator.GetMemoryUsed() > 3 * (Allocator.AllocatorSize >> 2));
|
||||
|
||||
Allocator.GlueCount = 0;
|
||||
orderFall = modelOrder;
|
||||
}
|
||||
}
|
||||
|
||||
private static void Swap(PpmState state1, PpmState state2)
|
||||
{
|
||||
byte swapSymbol = state1.Symbol;
|
||||
byte swapFrequency = state1.Frequency;
|
||||
PpmContext swapSuccessor = state1.Successor;
|
||||
|
||||
state1.Symbol = state2.Symbol;
|
||||
state1.Frequency = state2.Frequency;
|
||||
state1.Successor = state2.Successor;
|
||||
|
||||
state2.Symbol = swapSymbol;
|
||||
state2.Frequency = swapFrequency;
|
||||
state2.Successor = swapSuccessor;
|
||||
}
|
||||
|
||||
private static void Copy(PpmState state1, PpmState state2)
|
||||
{
|
||||
state1.Symbol = state2.Symbol;
|
||||
state1.Frequency = state2.Frequency;
|
||||
state1.Successor = state2.Successor;
|
||||
}
|
||||
|
||||
private static int Mean(int sum, int shift, int round)
|
||||
{
|
||||
return (sum + (1 << (shift - round))) >> shift;
|
||||
}
|
||||
|
||||
private void ClearMask()
|
||||
{
|
||||
escapeCount = 1;
|
||||
Array.Clear(characterMask, 0, characterMask.Length);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
29
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/I1/ModelRestorationMethod.cs
vendored
Normal file
29
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/I1/ModelRestorationMethod.cs
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
#region Using
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Compress.SevenZip.Compress.PPmd.I1
|
||||
{
|
||||
/// <summary>
|
||||
/// The method used to adjust the model when the memory limit is reached.
|
||||
/// </summary>
|
||||
internal enum ModelRestorationMethod
|
||||
{
|
||||
/// <summary>
|
||||
/// Restart the model from scratch (this is the default).
|
||||
/// </summary>
|
||||
Restart = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Cut off the model (nearly twice as slow).
|
||||
/// </summary>
|
||||
CutOff = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Freeze the context tree (in some cases may result in poor compression).
|
||||
/// </summary>
|
||||
Freeze = 2
|
||||
}
|
||||
}
|
||||
319
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/I1/Pointer.cs
vendored
Normal file
319
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/I1/Pointer.cs
vendored
Normal file
@@ -0,0 +1,319 @@
|
||||
#region Using
|
||||
|
||||
using System;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Compress.SevenZip.Compress.PPmd.I1
|
||||
{
|
||||
/// <summary>
|
||||
/// A structure containing a single address representing a position in the <see cref="Memory"/> array. This
|
||||
/// is intended to mimic the behaviour of a pointer in C/C++.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This must be a structure rather than a class because several places in the associated code assume that
|
||||
/// <see cref="Pointer"/> is a value type (meaning that assignment creates a completely new copy of the
|
||||
/// instance rather than just copying a reference to the same instance).
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Note that <see cref="Address"/> is a field rather than a property for performance reasons.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
internal struct Pointer
|
||||
{
|
||||
public uint Address;
|
||||
public byte[] Memory;
|
||||
public static readonly Pointer Zero = new Pointer(0, null);
|
||||
public const int Size = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Pointer"/> structure.
|
||||
/// </summary>
|
||||
public Pointer(uint address, byte[] memory)
|
||||
{
|
||||
Address = address;
|
||||
Memory = memory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the byte at the given <paramref name="offset"/>.
|
||||
/// </summary>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns></returns>
|
||||
public byte this[int offset]
|
||||
{
|
||||
get
|
||||
{
|
||||
#if DEBUG
|
||||
if (Address == 0)
|
||||
throw new InvalidOperationException("The pointer being indexed is a null pointer.");
|
||||
#endif
|
||||
return Memory[Address + offset];
|
||||
}
|
||||
set
|
||||
{
|
||||
#if DEBUG
|
||||
if (Address == 0)
|
||||
throw new InvalidOperationException("The pointer being indexed is a null pointer.");
|
||||
#endif
|
||||
Memory[Address + offset] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allow a <see cref="MemoryNode"/> to be implicitly converted to a <see cref="Pointer"/>.
|
||||
/// </summary>
|
||||
/// <param name="memoryNode"></param>
|
||||
/// <returns></returns>
|
||||
public static implicit operator Pointer(MemoryNode memoryNode)
|
||||
{
|
||||
return new Pointer(memoryNode.Address, memoryNode.Memory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allow a <see cref="Model.PpmContext"/> to be implicitly converted to a <see cref="Pointer"/>.
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
public static implicit operator Pointer(Model.PpmContext context)
|
||||
{
|
||||
return new Pointer(context.Address, context.Memory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allow a <see cref="PpmState"/> to be implicitly converted to a <see cref="Pointer"/>.
|
||||
/// </summary>
|
||||
/// <param name="state"></param>
|
||||
/// <returns></returns>
|
||||
public static implicit operator Pointer(PpmState state)
|
||||
{
|
||||
return new Pointer(state.Address, state.Memory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Increase the address of a pointer by the given number of bytes.
|
||||
/// </summary>
|
||||
/// <param name="pointer"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns></returns>
|
||||
public static Pointer operator +(Pointer pointer, int offset)
|
||||
{
|
||||
#if DEBUG
|
||||
if (pointer.Address == 0)
|
||||
throw new InvalidOperationException("The pointer is a null pointer.");
|
||||
#endif
|
||||
pointer.Address = (uint) (pointer.Address + offset);
|
||||
return pointer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Increase the address of a pointer by the given number of bytes.
|
||||
/// </summary>
|
||||
/// <param name="pointer"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns></returns>
|
||||
public static Pointer operator +(Pointer pointer, uint offset)
|
||||
{
|
||||
#if DEBUG
|
||||
if (pointer.Address == 0)
|
||||
throw new InvalidOperationException("The pointer is a null pointer.");
|
||||
#endif
|
||||
pointer.Address += offset;
|
||||
return pointer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Increment the address of a pointer.
|
||||
/// </summary>
|
||||
/// <param name="pointer"></param>
|
||||
/// <returns></returns>
|
||||
public static Pointer operator ++(Pointer pointer)
|
||||
{
|
||||
#if DEBUG
|
||||
if (pointer.Address == 0)
|
||||
throw new InvalidOperationException("The pointer being incremented is a null pointer.");
|
||||
#endif
|
||||
pointer.Address++;
|
||||
return pointer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrease the address of a pointer by the given number of bytes.
|
||||
/// </summary>
|
||||
/// <param name="pointer"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns></returns>
|
||||
public static Pointer operator -(Pointer pointer, int offset)
|
||||
{
|
||||
#if DEBUG
|
||||
if (pointer.Address == 0)
|
||||
throw new InvalidOperationException("The pointer is a null pointer.");
|
||||
#endif
|
||||
pointer.Address = (uint) (pointer.Address - offset);
|
||||
return pointer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrease the address of a pointer by the given number of bytes.
|
||||
/// </summary>
|
||||
/// <param name="pointer"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns></returns>
|
||||
public static Pointer operator -(Pointer pointer, uint offset)
|
||||
{
|
||||
#if DEBUG
|
||||
if (pointer.Address == 0)
|
||||
throw new InvalidOperationException("The pointer is a null pointer.");
|
||||
#endif
|
||||
pointer.Address -= offset;
|
||||
return pointer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrement the address of a pointer.
|
||||
/// </summary>
|
||||
/// <param name="pointer"></param>
|
||||
/// <returns></returns>
|
||||
public static Pointer operator --(Pointer pointer)
|
||||
{
|
||||
#if DEBUG
|
||||
if (pointer.Address == 0)
|
||||
throw new InvalidOperationException("The pointer being decremented is a null pointer.");
|
||||
#endif
|
||||
pointer.Address--;
|
||||
return pointer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtract two pointers.
|
||||
/// </summary>
|
||||
/// <param name="pointer1"></param>
|
||||
/// <param name="pointer2"></param>
|
||||
/// <returns>The number of bytes between the two pointers.</returns>
|
||||
public static uint operator -(Pointer pointer1, Pointer pointer2)
|
||||
{
|
||||
#if DEBUG
|
||||
if (pointer1.Address == 0)
|
||||
throw new InvalidOperationException("The pointer to the left of the subtraction operator is a null pointer.");
|
||||
if (pointer2.Address == 0)
|
||||
throw new InvalidOperationException("The pointer to the right of the subtraction operator is a null pointer.");
|
||||
#endif
|
||||
return pointer1.Address - pointer2.Address;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compare pointers.
|
||||
/// </summary>
|
||||
/// <param name="pointer1"></param>
|
||||
/// <param name="pointer2"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator <(Pointer pointer1, Pointer pointer2)
|
||||
{
|
||||
#if DEBUG
|
||||
if (pointer1.Address == 0)
|
||||
throw new InvalidOperationException("The pointer to the left of the less than operator is a null pointer.");
|
||||
if (pointer2.Address == 0)
|
||||
throw new InvalidOperationException("The pointer to the right of the less than operator is a null pointer.");
|
||||
#endif
|
||||
return pointer1.Address < pointer2.Address;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compare two pointers.
|
||||
/// </summary>
|
||||
/// <param name="pointer1"></param>
|
||||
/// <param name="pointer2"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator <=(Pointer pointer1, Pointer pointer2)
|
||||
{
|
||||
#if DEBUG
|
||||
if (pointer1.Address == 0)
|
||||
throw new InvalidOperationException("The pointer to the left of the less than or equal to operator is a null pointer.");
|
||||
if (pointer2.Address == 0)
|
||||
throw new InvalidOperationException("The pointer to the right of the less than or equal to operator is a null pointer.");
|
||||
#endif
|
||||
return pointer1.Address <= pointer2.Address;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compare two pointers.
|
||||
/// </summary>
|
||||
/// <param name="pointer1"></param>
|
||||
/// <param name="pointer2"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator >(Pointer pointer1, Pointer pointer2)
|
||||
{
|
||||
#if DEBUG
|
||||
if (pointer1.Address == 0)
|
||||
throw new InvalidOperationException("The pointer to the left of the greater than operator is a null pointer.");
|
||||
if (pointer2.Address == 0)
|
||||
throw new InvalidOperationException("The pointer to the right of the greater than operator is a null pointer.");
|
||||
#endif
|
||||
return pointer1.Address > pointer2.Address;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compare two pointers.
|
||||
/// </summary>
|
||||
/// <param name="pointer1"></param>
|
||||
/// <param name="pointer2"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator >=(Pointer pointer1, Pointer pointer2)
|
||||
{
|
||||
#if DEBUG
|
||||
if (pointer1.Address == 0)
|
||||
throw new InvalidOperationException("The pointer to the left of the greater than or equal to operator is a null pointer.");
|
||||
if (pointer2.Address == 0)
|
||||
throw new InvalidOperationException("The pointer to the right of the greater than or equal to operator is a null pointer.");
|
||||
#endif
|
||||
return pointer1.Address >= pointer2.Address;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compare two pointers.
|
||||
/// </summary>
|
||||
/// <param name="pointer1"></param>
|
||||
/// <param name="pointer2"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator ==(Pointer pointer1, Pointer pointer2)
|
||||
{
|
||||
return pointer1.Address == pointer2.Address;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compare two pointers.
|
||||
/// </summary>
|
||||
/// <param name="pointer1"></param>
|
||||
/// <param name="pointer2"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator !=(Pointer pointer1, Pointer pointer2)
|
||||
{
|
||||
return pointer1.Address != pointer2.Address;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether this instance and a specified object are equal.
|
||||
/// </summary>
|
||||
/// <returns>true if obj and this instance are the same type and represent the same value; otherwise, false.</returns>
|
||||
/// <param name="obj">Another object to compare to.</param>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is Pointer)
|
||||
{
|
||||
Pointer pointer = (Pointer) obj;
|
||||
return pointer.Address == Address;
|
||||
}
|
||||
return base.Equals(obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the hash code for this instance.
|
||||
/// </summary>
|
||||
/// <returns>A 32-bit signed integer that is the hash code for this instance.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Address.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
787
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/I1/PpmContext.cs
vendored
Normal file
787
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/I1/PpmContext.cs
vendored
Normal file
@@ -0,0 +1,787 @@
|
||||
#region Using
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Compress.SevenZip.Compress.PPmd.I1
|
||||
{
|
||||
/// <summary>
|
||||
/// The PPM context structure. This is tightly coupled with <see cref="Model"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This must be a structure rather than a class because several places in the associated code assume that
|
||||
/// <see cref="PpmContext"/> is a value type (meaning that assignment creates a completely new copy of
|
||||
/// the instance rather than just copying a reference to the same instance).
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
internal partial class Model
|
||||
{
|
||||
/// <summary>
|
||||
/// The structure which represents the current PPM context. This is 12 bytes in size.
|
||||
/// </summary>
|
||||
internal struct PpmContext
|
||||
{
|
||||
public uint Address;
|
||||
public byte[] Memory;
|
||||
public static readonly PpmContext Zero = new PpmContext(0, null);
|
||||
public const int Size = 12;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PpmContext"/> structure.
|
||||
/// </summary>
|
||||
public PpmContext(uint address, byte[] memory)
|
||||
{
|
||||
Address = address;
|
||||
Memory = memory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number statistics.
|
||||
/// </summary>
|
||||
public byte NumberStatistics
|
||||
{
|
||||
get { return Memory[Address]; }
|
||||
set { Memory[Address] = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the flags.
|
||||
/// </summary>
|
||||
public byte Flags
|
||||
{
|
||||
get { return Memory[Address + 1]; }
|
||||
set { Memory[Address + 1] = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the summary frequency.
|
||||
/// </summary>
|
||||
public ushort SummaryFrequency
|
||||
{
|
||||
get { return (ushort)(((ushort)Memory[Address + 2]) | ((ushort)Memory[Address + 3]) << 8); }
|
||||
set
|
||||
{
|
||||
Memory[Address + 2] = (byte)value;
|
||||
Memory[Address + 3] = (byte)(value >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the statistics.
|
||||
/// </summary>
|
||||
public PpmState Statistics
|
||||
{
|
||||
get { return new PpmState(((uint)Memory[Address + 4]) | ((uint)Memory[Address + 5]) << 8 | ((uint)Memory[Address + 6]) << 16 | ((uint)Memory[Address + 7]) << 24, Memory); }
|
||||
set
|
||||
{
|
||||
Memory[Address + 4] = (byte)value.Address;
|
||||
Memory[Address + 5] = (byte)(value.Address >> 8);
|
||||
Memory[Address + 6] = (byte)(value.Address >> 16);
|
||||
Memory[Address + 7] = (byte)(value.Address >> 24);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the suffix.
|
||||
/// </summary>
|
||||
public PpmContext Suffix
|
||||
{
|
||||
get { return new PpmContext(((uint)Memory[Address + 8]) | ((uint)Memory[Address + 9]) << 8 | ((uint)Memory[Address + 10]) << 16 | ((uint)Memory[Address + 11]) << 24, Memory); }
|
||||
set
|
||||
{
|
||||
Memory[Address + 8] = (byte)value.Address;
|
||||
Memory[Address + 9] = (byte)(value.Address >> 8);
|
||||
Memory[Address + 10] = (byte)(value.Address >> 16);
|
||||
Memory[Address + 11] = (byte)(value.Address >> 24);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The first PPM state associated with the PPM context.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// The first PPM state overlaps this PPM context instance (the context.SummaryFrequency and context.Statistics members
|
||||
/// of PpmContext use 6 bytes and so can therefore fit into the space used by the Symbol, Frequency and
|
||||
/// Successor members of PpmState, since they also add up to 6 bytes).
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// PpmContext (context.SummaryFrequency and context.Statistics use 6 bytes)
|
||||
/// 1 context.NumberStatistics
|
||||
/// 1 context.Flags
|
||||
/// 2 context.SummaryFrequency
|
||||
/// 4 context.Statistics (pointer to PpmState)
|
||||
/// 4 context.Suffix (pointer to PpmContext)
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// PpmState (total of 6 bytes)
|
||||
/// 1 Symbol
|
||||
/// 1 Frequency
|
||||
/// 4 Successor (pointer to PpmContext)
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <returns></returns>
|
||||
public PpmState FirstState
|
||||
{
|
||||
get { return new PpmState(Address + 2, Memory); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the symbol of the first PPM state. This is provided for convenience. The same
|
||||
/// information can be obtained using the Symbol property on the PPM state provided by the
|
||||
/// <see cref="FirstState"/> property.
|
||||
/// </summary>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "The property getter is provided for completeness.")]
|
||||
public byte FirstStateSymbol
|
||||
{
|
||||
get { return Memory[Address + 2]; }
|
||||
set { Memory[Address + 2] = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the frequency of the first PPM state. This is provided for convenience. The same
|
||||
/// information can be obtained using the Frequency property on the PPM state provided by the
|
||||
///context.FirstState property.
|
||||
/// </summary>
|
||||
public byte FirstStateFrequency
|
||||
{
|
||||
get { return Memory[Address + 3]; }
|
||||
set { Memory[Address + 3] = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the successor of the first PPM state. This is provided for convenience. The same
|
||||
/// information can be obtained using the Successor property on the PPM state provided by the
|
||||
/// </summary>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "The property getter is provided for completeness.")]
|
||||
public PpmContext FirstStateSuccessor
|
||||
{
|
||||
get { return new PpmContext(((uint)Memory[Address + 4]) | ((uint)Memory[Address + 5]) << 8 | ((uint)Memory[Address + 6]) << 16 | ((uint)Memory[Address + 7]) << 24, Memory); }
|
||||
set
|
||||
{
|
||||
Memory[Address + 4] = (byte)value.Address;
|
||||
Memory[Address + 5] = (byte)(value.Address >> 8);
|
||||
Memory[Address + 6] = (byte)(value.Address >> 16);
|
||||
Memory[Address + 7] = (byte)(value.Address >> 24);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allow a pointer to be implicitly converted to a PPM context.
|
||||
/// </summary>
|
||||
/// <param name="pointer"></param>
|
||||
/// <returns></returns>
|
||||
public static implicit operator PpmContext(Pointer pointer)
|
||||
{
|
||||
return new PpmContext(pointer.Address, pointer.Memory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allow pointer-like addition on a PPM context.
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns></returns>
|
||||
public static PpmContext operator +(PpmContext context, int offset)
|
||||
{
|
||||
context.Address = (uint)(context.Address + offset * Size);
|
||||
return context;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allow pointer-like subtraction on a PPM context.
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns></returns>
|
||||
public static PpmContext operator -(PpmContext context, int offset)
|
||||
{
|
||||
context.Address = (uint)(context.Address - offset * Size);
|
||||
return context;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compare two PPM contexts.
|
||||
/// </summary>
|
||||
/// <param name="context1"></param>
|
||||
/// <param name="context2"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator <=(PpmContext context1, PpmContext context2)
|
||||
{
|
||||
return context1.Address <= context2.Address;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compare two PPM contexts.
|
||||
/// </summary>
|
||||
/// <param name="context1"></param>
|
||||
/// <param name="context2"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator >=(PpmContext context1, PpmContext context2)
|
||||
{
|
||||
return context1.Address >= context2.Address;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compare two PPM contexts.
|
||||
/// </summary>
|
||||
/// <param name="context1"></param>
|
||||
/// <param name="context2"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator ==(PpmContext context1, PpmContext context2)
|
||||
{
|
||||
return context1.Address == context2.Address;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compare two PPM contexts.
|
||||
/// </summary>
|
||||
/// <param name="context1"></param>
|
||||
/// <param name="context2"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator !=(PpmContext context1, PpmContext context2)
|
||||
{
|
||||
return context1.Address != context2.Address;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether this instance and a specified object are equal.
|
||||
/// </summary>
|
||||
/// <returns>true if obj and this instance are the same type and represent the same value; otherwise, false.</returns>
|
||||
/// <param name="obj">Another object to compare to.</param>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is PpmContext)
|
||||
{
|
||||
PpmContext context = (PpmContext)obj;
|
||||
return context.Address == Address;
|
||||
}
|
||||
return base.Equals(obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the hash code for this instance.
|
||||
/// </summary>
|
||||
/// <returns>A 32-bit signed integer that is the hash code for this instance.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Address.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
private void EncodeBinarySymbol(int symbol, PpmContext context)
|
||||
{
|
||||
PpmState state = context.FirstState;
|
||||
int index1 = probabilities[state.Frequency - 1];
|
||||
int index2 = numberStatisticsToBinarySummaryIndex[context.Suffix.NumberStatistics] + previousSuccess + context.Flags + ((runLength >> 26) & 0x20);
|
||||
|
||||
if (state.Symbol == symbol)
|
||||
{
|
||||
foundState = state;
|
||||
state.Frequency += (byte)((state.Frequency < 196) ? 1 : 0);
|
||||
Coder.LowCount = 0;
|
||||
Coder.HighCount = binarySummary[index1, index2];
|
||||
binarySummary[index1, index2] += (ushort)(Interval - Mean(binarySummary[index1, index2], PeriodBitCount, 2));
|
||||
previousSuccess = 1;
|
||||
runLength++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Coder.LowCount = binarySummary[index1, index2];
|
||||
binarySummary[index1, index2] -= (ushort)Mean(binarySummary[index1, index2], PeriodBitCount, 2);
|
||||
Coder.HighCount = BinaryScale;
|
||||
initialEscape = ExponentialEscapes[binarySummary[index1, index2] >> 10];
|
||||
characterMask[state.Symbol] = escapeCount;
|
||||
previousSuccess = 0;
|
||||
numberMasked = 0;
|
||||
foundState = PpmState.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
private void EncodeSymbol1(int symbol, PpmContext context)
|
||||
{
|
||||
uint lowCount;
|
||||
uint index = context.Statistics.Symbol;
|
||||
PpmState state = context.Statistics;
|
||||
Coder.Scale = context.SummaryFrequency;
|
||||
if (index == symbol)
|
||||
{
|
||||
Coder.HighCount = state.Frequency;
|
||||
previousSuccess = (byte)((2 * Coder.HighCount >= Coder.Scale) ? 1 : 0);
|
||||
foundState = state;
|
||||
foundState.Frequency += 4;
|
||||
context.SummaryFrequency += 4;
|
||||
runLength += previousSuccess;
|
||||
if (state.Frequency > MaximumFrequency)
|
||||
Rescale(context);
|
||||
Coder.LowCount = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
lowCount = state.Frequency;
|
||||
index = context.NumberStatistics;
|
||||
previousSuccess = 0;
|
||||
while ((++state).Symbol != symbol)
|
||||
{
|
||||
lowCount += state.Frequency;
|
||||
if (--index == 0)
|
||||
{
|
||||
Coder.LowCount = lowCount;
|
||||
characterMask[state.Symbol] = escapeCount;
|
||||
numberMasked = context.NumberStatistics;
|
||||
index = context.NumberStatistics;
|
||||
foundState = PpmState.Zero;
|
||||
do
|
||||
{
|
||||
characterMask[(--state).Symbol] = escapeCount;
|
||||
} while (--index != 0);
|
||||
Coder.HighCount = Coder.Scale;
|
||||
return;
|
||||
}
|
||||
}
|
||||
Coder.HighCount = (Coder.LowCount = lowCount) + state.Frequency;
|
||||
Update1(state, context);
|
||||
}
|
||||
|
||||
private void EncodeSymbol2(int symbol, PpmContext context)
|
||||
{
|
||||
See2Context see2Context = MakeEscapeFrequency(context);
|
||||
uint currentSymbol;
|
||||
uint lowCount = 0;
|
||||
uint index = (uint)(context.NumberStatistics - numberMasked);
|
||||
PpmState state = context.Statistics - 1;
|
||||
|
||||
do
|
||||
{
|
||||
do
|
||||
{
|
||||
currentSymbol = state[1].Symbol;
|
||||
state++;
|
||||
} while (characterMask[currentSymbol] == escapeCount);
|
||||
characterMask[currentSymbol] = escapeCount;
|
||||
if (currentSymbol == symbol)
|
||||
goto SymbolFound;
|
||||
lowCount += state.Frequency;
|
||||
} while (--index != 0);
|
||||
|
||||
Coder.LowCount = lowCount;
|
||||
Coder.Scale += Coder.LowCount;
|
||||
Coder.HighCount = Coder.Scale;
|
||||
see2Context.Summary += (ushort)Coder.Scale;
|
||||
numberMasked = context.NumberStatistics;
|
||||
return;
|
||||
|
||||
SymbolFound:
|
||||
Coder.LowCount = lowCount;
|
||||
lowCount += state.Frequency;
|
||||
Coder.HighCount = lowCount;
|
||||
for (PpmState p1 = state; --index != 0; )
|
||||
{
|
||||
do
|
||||
{
|
||||
currentSymbol = p1[1].Symbol;
|
||||
p1++;
|
||||
} while (characterMask[currentSymbol] == escapeCount);
|
||||
lowCount += p1.Frequency;
|
||||
}
|
||||
Coder.Scale += lowCount;
|
||||
see2Context.Update();
|
||||
Update2(state, context);
|
||||
}
|
||||
|
||||
private void DecodeBinarySymbol(PpmContext context)
|
||||
{
|
||||
PpmState state = context.FirstState;
|
||||
int index1 = probabilities[state.Frequency - 1];
|
||||
int index2 = numberStatisticsToBinarySummaryIndex[context.Suffix.NumberStatistics] + previousSuccess + context.Flags + ((runLength >> 26) & 0x20);
|
||||
|
||||
if (Coder.RangeGetCurrentShiftCount(TotalBitCount) < binarySummary[index1, index2])
|
||||
{
|
||||
foundState = state;
|
||||
state.Frequency += (byte)((state.Frequency < 196) ? 1 : 0);
|
||||
Coder.LowCount = 0;
|
||||
Coder.HighCount = binarySummary[index1, index2];
|
||||
binarySummary[index1, index2] += (ushort)(Interval - Mean(binarySummary[index1, index2], PeriodBitCount, 2));
|
||||
previousSuccess = 1;
|
||||
runLength++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Coder.LowCount = binarySummary[index1, index2];
|
||||
binarySummary[index1, index2] -= (ushort)Mean(binarySummary[index1, index2], PeriodBitCount, 2);
|
||||
Coder.HighCount = BinaryScale;
|
||||
initialEscape = ExponentialEscapes[binarySummary[index1, index2] >> 10];
|
||||
characterMask[state.Symbol] = escapeCount;
|
||||
previousSuccess = 0;
|
||||
numberMasked = 0;
|
||||
foundState = PpmState.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
private void DecodeSymbol1(PpmContext context)
|
||||
{
|
||||
uint index;
|
||||
uint count;
|
||||
uint highCount = context.Statistics.Frequency;
|
||||
PpmState state = context.Statistics;
|
||||
Coder.Scale = context.SummaryFrequency;
|
||||
|
||||
count = Coder.RangeGetCurrentCount();
|
||||
if (count < highCount)
|
||||
{
|
||||
Coder.HighCount = highCount;
|
||||
previousSuccess = (byte)((2 * Coder.HighCount >= Coder.Scale) ? 1 : 0);
|
||||
foundState = state;
|
||||
highCount += 4;
|
||||
foundState.Frequency = (byte)highCount;
|
||||
context.SummaryFrequency += 4;
|
||||
runLength += previousSuccess;
|
||||
if (highCount > MaximumFrequency)
|
||||
Rescale(context);
|
||||
Coder.LowCount = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
index = context.NumberStatistics;
|
||||
previousSuccess = 0;
|
||||
while ((highCount += (++state).Frequency) <= count)
|
||||
{
|
||||
if (--index == 0)
|
||||
{
|
||||
Coder.LowCount = highCount;
|
||||
characterMask[state.Symbol] = escapeCount;
|
||||
numberMasked = context.NumberStatistics;
|
||||
index = context.NumberStatistics;
|
||||
foundState = PpmState.Zero;
|
||||
do
|
||||
{
|
||||
characterMask[(--state).Symbol] = escapeCount;
|
||||
} while (--index != 0);
|
||||
Coder.HighCount = Coder.Scale;
|
||||
return;
|
||||
}
|
||||
}
|
||||
Coder.HighCount = highCount;
|
||||
Coder.LowCount = Coder.HighCount - state.Frequency;
|
||||
Update1(state, context);
|
||||
}
|
||||
|
||||
private void DecodeSymbol2(PpmContext context)
|
||||
{
|
||||
See2Context see2Context = MakeEscapeFrequency(context);
|
||||
uint currentSymbol;
|
||||
uint count;
|
||||
uint highCount = 0;
|
||||
uint index = (uint)(context.NumberStatistics - numberMasked);
|
||||
uint stateIndex = 0;
|
||||
PpmState state = context.Statistics - 1;
|
||||
|
||||
do
|
||||
{
|
||||
do
|
||||
{
|
||||
currentSymbol = state[1].Symbol;
|
||||
state++;
|
||||
} while (characterMask[currentSymbol] == escapeCount);
|
||||
highCount += state.Frequency;
|
||||
decodeStates[stateIndex++] = state; // note that decodeStates is a static array that is re-used on each call to this method (for performance reasons)
|
||||
} while (--index != 0);
|
||||
|
||||
Coder.Scale += highCount;
|
||||
count = Coder.RangeGetCurrentCount();
|
||||
stateIndex = 0;
|
||||
state = decodeStates[stateIndex];
|
||||
if (count < highCount)
|
||||
{
|
||||
highCount = 0;
|
||||
while ((highCount += state.Frequency) <= count)
|
||||
state = decodeStates[++stateIndex];
|
||||
Coder.HighCount = highCount;
|
||||
Coder.LowCount = Coder.HighCount - state.Frequency;
|
||||
see2Context.Update();
|
||||
Update2(state, context);
|
||||
}
|
||||
else
|
||||
{
|
||||
Coder.LowCount = highCount;
|
||||
Coder.HighCount = Coder.Scale;
|
||||
index = (uint)(context.NumberStatistics - numberMasked);
|
||||
numberMasked = context.NumberStatistics;
|
||||
do
|
||||
{
|
||||
characterMask[decodeStates[stateIndex].Symbol] = escapeCount;
|
||||
stateIndex++;
|
||||
} while (--index != 0);
|
||||
see2Context.Summary += (ushort)Coder.Scale;
|
||||
}
|
||||
}
|
||||
|
||||
private void Update1(PpmState state, PpmContext context)
|
||||
{
|
||||
foundState = state;
|
||||
foundState.Frequency += 4;
|
||||
context.SummaryFrequency += 4;
|
||||
if (state[0].Frequency > state[-1].Frequency)
|
||||
{
|
||||
Swap(state[0], state[-1]);
|
||||
foundState = --state;
|
||||
if (state.Frequency > MaximumFrequency)
|
||||
Rescale(context);
|
||||
}
|
||||
}
|
||||
|
||||
private void Update2(PpmState state, PpmContext context)
|
||||
{
|
||||
foundState = state;
|
||||
foundState.Frequency += 4;
|
||||
context.SummaryFrequency += 4;
|
||||
if (state.Frequency > MaximumFrequency)
|
||||
Rescale(context);
|
||||
escapeCount++;
|
||||
runLength = initialRunLength;
|
||||
}
|
||||
|
||||
private See2Context MakeEscapeFrequency(PpmContext context)
|
||||
{
|
||||
uint numberStatistics = (uint)2 * context.NumberStatistics;
|
||||
See2Context see2Context;
|
||||
|
||||
if (context.NumberStatistics != 0xff)
|
||||
{
|
||||
// Note that context.Flags is always in the range 0 .. 28 (this ensures that the index used for the second
|
||||
// dimension of the see2Contexts array is always in the range 0 .. 31).
|
||||
|
||||
numberStatistics = context.Suffix.NumberStatistics;
|
||||
int index1 = probabilities[context.NumberStatistics + 2] - 3;
|
||||
int index2 = ((context.SummaryFrequency > 11 * (context.NumberStatistics + 1)) ? 1 : 0) + ((2 * context.NumberStatistics < numberStatistics + numberMasked) ? 2 : 0) + context.Flags;
|
||||
see2Context = see2Contexts[index1, index2];
|
||||
Coder.Scale = see2Context.Mean();
|
||||
}
|
||||
else
|
||||
{
|
||||
see2Context = emptySee2Context;
|
||||
Coder.Scale = 1;
|
||||
}
|
||||
|
||||
return see2Context;
|
||||
}
|
||||
|
||||
private void Rescale(PpmContext context)
|
||||
{
|
||||
uint oldUnitCount;
|
||||
int adder;
|
||||
uint escapeFrequency;
|
||||
uint index = context.NumberStatistics;
|
||||
|
||||
byte localSymbol;
|
||||
byte localFrequency;
|
||||
PpmContext localSuccessor;
|
||||
PpmState p1;
|
||||
PpmState state;
|
||||
|
||||
for (state = foundState; state != context.Statistics; state--)
|
||||
Swap(state[0], state[-1]);
|
||||
|
||||
state.Frequency += 4;
|
||||
context.SummaryFrequency += 4;
|
||||
escapeFrequency = (uint)(context.SummaryFrequency - state.Frequency);
|
||||
adder = (orderFall != 0 || method > ModelRestorationMethod.Freeze) ? 1 : 0;
|
||||
state.Frequency = (byte)((state.Frequency + adder) >> 1);
|
||||
context.SummaryFrequency = state.Frequency;
|
||||
|
||||
do
|
||||
{
|
||||
escapeFrequency -= (++state).Frequency;
|
||||
state.Frequency = (byte)((state.Frequency + adder) >> 1);
|
||||
context.SummaryFrequency += state.Frequency;
|
||||
if (state[0].Frequency > state[-1].Frequency)
|
||||
{
|
||||
p1 = state;
|
||||
localSymbol = p1.Symbol;
|
||||
localFrequency = p1.Frequency;
|
||||
localSuccessor = p1.Successor;
|
||||
do
|
||||
{
|
||||
Copy(p1[0], p1[-1]);
|
||||
} while (localFrequency > (--p1)[-1].Frequency);
|
||||
p1.Symbol = localSymbol;
|
||||
p1.Frequency = localFrequency;
|
||||
p1.Successor = localSuccessor;
|
||||
}
|
||||
} while (--index != 0);
|
||||
|
||||
if (state.Frequency == 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
index++;
|
||||
} while ((--state).Frequency == 0);
|
||||
|
||||
escapeFrequency += index;
|
||||
oldUnitCount = (uint)((context.NumberStatistics + 2) >> 1);
|
||||
context.NumberStatistics -= (byte)index;
|
||||
if (context.NumberStatistics == 0)
|
||||
{
|
||||
localSymbol = context.Statistics.Symbol;
|
||||
localFrequency = context.Statistics.Frequency;
|
||||
localSuccessor = context.Statistics.Successor;
|
||||
localFrequency = (byte)((2 * localFrequency + escapeFrequency - 1) / escapeFrequency);
|
||||
if (localFrequency > MaximumFrequency / 3)
|
||||
localFrequency = (byte)(MaximumFrequency / 3);
|
||||
Allocator.FreeUnits(context.Statistics, oldUnitCount);
|
||||
context.FirstStateSymbol = localSymbol;
|
||||
context.FirstStateFrequency = localFrequency;
|
||||
context.FirstStateSuccessor = localSuccessor;
|
||||
context.Flags = (byte)((context.Flags & 0x10) + ((localSymbol >= 0x40) ? 0x08 : 0x00));
|
||||
foundState = context.FirstState;
|
||||
return;
|
||||
}
|
||||
|
||||
context.Statistics = Allocator.ShrinkUnits(context.Statistics, oldUnitCount, (uint)((context.NumberStatistics + 2) >> 1));
|
||||
context.Flags &= 0xf7;
|
||||
index = context.NumberStatistics;
|
||||
state = context.Statistics;
|
||||
context.Flags |= (byte)((state.Symbol >= 0x40) ? 0x08 : 0x00);
|
||||
do
|
||||
{
|
||||
context.Flags |= (byte)(((++state).Symbol >= 0x40) ? 0x08 : 0x00);
|
||||
} while (--index != 0);
|
||||
}
|
||||
|
||||
escapeFrequency -= (escapeFrequency >> 1);
|
||||
context.SummaryFrequency += (ushort)escapeFrequency;
|
||||
context.Flags |= 0x04;
|
||||
foundState = context.Statistics;
|
||||
}
|
||||
|
||||
private void Refresh(uint oldUnitCount, bool scale, PpmContext context)
|
||||
{
|
||||
int index = context.NumberStatistics;
|
||||
int escapeFrequency;
|
||||
int scaleValue = (scale ? 1 : 0);
|
||||
|
||||
context.Statistics = Allocator.ShrinkUnits(context.Statistics, oldUnitCount, (uint)((index + 2) >> 1));
|
||||
PpmState statistics = context.Statistics;
|
||||
context.Flags = (byte)((context.Flags & (0x10 + (scale ? 0x04 : 0x00))) + ((statistics.Symbol >= 0x40) ? 0x08 : 0x00));
|
||||
escapeFrequency = context.SummaryFrequency - statistics.Frequency;
|
||||
statistics.Frequency = (byte)((statistics.Frequency + scaleValue) >> scaleValue);
|
||||
context.SummaryFrequency = statistics.Frequency;
|
||||
|
||||
do
|
||||
{
|
||||
escapeFrequency -= (++statistics).Frequency;
|
||||
statistics.Frequency = (byte)((statistics.Frequency + scaleValue) >> scaleValue);
|
||||
context.SummaryFrequency += statistics.Frequency;
|
||||
context.Flags |= (byte)((statistics.Symbol >= 0x40) ? 0x08 : 0x00);
|
||||
} while (--index != 0);
|
||||
|
||||
escapeFrequency = (escapeFrequency + scaleValue) >> scaleValue;
|
||||
context.SummaryFrequency += (ushort)escapeFrequency;
|
||||
}
|
||||
|
||||
private PpmContext CutOff(int order, PpmContext context)
|
||||
{
|
||||
int index;
|
||||
PpmState state;
|
||||
|
||||
if (context.NumberStatistics == 0)
|
||||
{
|
||||
state = context.FirstState;
|
||||
if ((Pointer)state.Successor >= Allocator.BaseUnit)
|
||||
{
|
||||
if (order < modelOrder)
|
||||
state.Successor = CutOff(order + 1, state.Successor);
|
||||
else
|
||||
state.Successor = PpmContext.Zero;
|
||||
|
||||
if (state.Successor == PpmContext.Zero && order > OrderBound)
|
||||
{
|
||||
Allocator.SpecialFreeUnits(context);
|
||||
return PpmContext.Zero;
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
else
|
||||
{
|
||||
Allocator.SpecialFreeUnits(context);
|
||||
return PpmContext.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
uint unitCount = (uint)((context.NumberStatistics + 2) >> 1);
|
||||
context.Statistics = Allocator.MoveUnitsUp(context.Statistics, unitCount);
|
||||
index = context.NumberStatistics;
|
||||
for (state = context.Statistics + index; state >= context.Statistics; state--)
|
||||
{
|
||||
if (state.Successor < Allocator.BaseUnit)
|
||||
{
|
||||
state.Successor = PpmContext.Zero;
|
||||
Swap(state, context.Statistics[index--]);
|
||||
}
|
||||
else if (order < modelOrder)
|
||||
state.Successor = CutOff(order + 1, state.Successor);
|
||||
else
|
||||
state.Successor = PpmContext.Zero;
|
||||
}
|
||||
|
||||
if (index != context.NumberStatistics && order != 0)
|
||||
{
|
||||
context.NumberStatistics = (byte)index;
|
||||
state = context.Statistics;
|
||||
if (index < 0)
|
||||
{
|
||||
Allocator.FreeUnits(state, unitCount);
|
||||
Allocator.SpecialFreeUnits(context);
|
||||
return PpmContext.Zero;
|
||||
}
|
||||
else if (index == 0)
|
||||
{
|
||||
context.Flags = (byte)((context.Flags & 0x10) + ((state.Symbol >= 0x40) ? 0x08 : 0x00));
|
||||
Copy(context.FirstState, state);
|
||||
Allocator.FreeUnits(state, unitCount);
|
||||
context.FirstStateFrequency = (byte)((context.FirstStateFrequency + 11) >> 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
Refresh(unitCount, context.SummaryFrequency > 16 * index, context);
|
||||
}
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
private PpmContext RemoveBinaryContexts(int order, PpmContext context)
|
||||
{
|
||||
if (context.NumberStatistics == 0)
|
||||
{
|
||||
PpmState state = context.FirstState;
|
||||
if ((Pointer)state.Successor >= Allocator.BaseUnit && order < modelOrder)
|
||||
state.Successor = RemoveBinaryContexts(order + 1, state.Successor);
|
||||
else
|
||||
state.Successor = PpmContext.Zero;
|
||||
if ((state.Successor == PpmContext.Zero) && (context.Suffix.NumberStatistics == 0 || context.Suffix.Flags == 0xff))
|
||||
{
|
||||
Allocator.FreeUnits(context, 1);
|
||||
return PpmContext.Zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
||||
for (PpmState state = context.Statistics + context.NumberStatistics; state >= context.Statistics; state--)
|
||||
{
|
||||
if ((Pointer)state.Successor >= Allocator.BaseUnit && order < modelOrder)
|
||||
state.Successor = RemoveBinaryContexts(order + 1, state.Successor);
|
||||
else
|
||||
state.Successor = PpmContext.Zero;
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
}
|
||||
}
|
||||
206
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/I1/PpmState.cs
vendored
Normal file
206
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/I1/PpmState.cs
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
#region Using
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Compress.SevenZip.Compress.PPmd.I1
|
||||
{
|
||||
/// <summary>
|
||||
/// PPM state.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This must be a structure rather than a class because several places in the associated code assume that
|
||||
/// <see cref="PpmState"/> is a value type (meaning that assignment creates a completely new copy of the
|
||||
/// instance rather than just copying a reference to the same instance).
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Note that <see cref="Address"/> is a field rather than a property for performance reasons.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
internal struct PpmState
|
||||
{
|
||||
public uint Address;
|
||||
public byte[] Memory;
|
||||
public static readonly PpmState Zero = new PpmState(0, null);
|
||||
public const int Size = 6;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PpmState"/> structure.
|
||||
/// </summary>
|
||||
public PpmState(uint address, byte[] memory)
|
||||
{
|
||||
Address = address;
|
||||
Memory = memory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the symbol.
|
||||
/// </summary>
|
||||
public byte Symbol
|
||||
{
|
||||
get { return Memory[Address]; }
|
||||
set { Memory[Address] = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the frequency.
|
||||
/// </summary>
|
||||
public byte Frequency
|
||||
{
|
||||
get { return Memory[Address + 1]; }
|
||||
set { Memory[Address + 1] = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the successor.
|
||||
/// </summary>
|
||||
public Model.PpmContext Successor
|
||||
{
|
||||
get { return new Model.PpmContext(((uint) Memory[Address + 2]) | ((uint) Memory[Address + 3]) << 8 | ((uint) Memory[Address + 4]) << 16 | ((uint) Memory[Address + 5]) << 24, Memory); }
|
||||
set
|
||||
{
|
||||
Memory[Address + 2] = (byte) value.Address;
|
||||
Memory[Address + 3] = (byte) (value.Address >> 8);
|
||||
Memory[Address + 4] = (byte) (value.Address >> 16);
|
||||
Memory[Address + 5] = (byte) (value.Address >> 24);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="PpmState"/> at the <paramref name="offset"/> relative to this
|
||||
/// <see cref="PpmState"/>.
|
||||
/// </summary>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns></returns>
|
||||
public PpmState this[int offset]
|
||||
{
|
||||
get { return new PpmState((uint) (Address + offset * Size), Memory); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allow a pointer to be implicitly converted to a PPM state.
|
||||
/// </summary>
|
||||
/// <param name="pointer"></param>
|
||||
/// <returns></returns>
|
||||
public static implicit operator PpmState(Pointer pointer)
|
||||
{
|
||||
return new PpmState(pointer.Address, pointer.Memory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allow pointer-like addition on a PPM state.
|
||||
/// </summary>
|
||||
/// <param name="state"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns></returns>
|
||||
public static PpmState operator +(PpmState state, int offset)
|
||||
{
|
||||
state.Address = (uint) (state.Address + offset * Size);
|
||||
return state;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allow pointer-like incrementing on a PPM state.
|
||||
/// </summary>
|
||||
/// <param name="state"></param>
|
||||
/// <returns></returns>
|
||||
public static PpmState operator ++(PpmState state)
|
||||
{
|
||||
state.Address += Size;
|
||||
return state;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allow pointer-like subtraction on a PPM state.
|
||||
/// </summary>
|
||||
/// <param name="state"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns></returns>
|
||||
public static PpmState operator -(PpmState state, int offset)
|
||||
{
|
||||
state.Address = (uint) (state.Address - offset * Size);
|
||||
return state;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allow pointer-like decrementing on a PPM state.
|
||||
/// </summary>
|
||||
/// <param name="state"></param>
|
||||
/// <returns></returns>
|
||||
public static PpmState operator --(PpmState state)
|
||||
{
|
||||
state.Address -= Size;
|
||||
return state;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compare two PPM states.
|
||||
/// </summary>
|
||||
/// <param name="state1"></param>
|
||||
/// <param name="state2"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator <=(PpmState state1, PpmState state2)
|
||||
{
|
||||
return state1.Address <= state2.Address;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compare two PPM states.
|
||||
/// </summary>
|
||||
/// <param name="state1"></param>
|
||||
/// <param name="state2"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator >=(PpmState state1, PpmState state2)
|
||||
{
|
||||
return state1.Address >= state2.Address;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compare two PPM states.
|
||||
/// </summary>
|
||||
/// <param name="state1"></param>
|
||||
/// <param name="state2"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator ==(PpmState state1, PpmState state2)
|
||||
{
|
||||
return state1.Address == state2.Address;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compare two PPM states.
|
||||
/// </summary>
|
||||
/// <param name="state1"></param>
|
||||
/// <param name="state2"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator !=(PpmState state1, PpmState state2)
|
||||
{
|
||||
return state1.Address != state2.Address;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether this instance and a specified object are equal.
|
||||
/// </summary>
|
||||
/// <returns>true if obj and this instance are the same type and represent the same value; otherwise, false.</returns>
|
||||
/// <param name="obj">Another object to compare to.</param>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is PpmState)
|
||||
{
|
||||
PpmState state = (PpmState) obj;
|
||||
return state.Address == Address;
|
||||
}
|
||||
return base.Equals(obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the hash code for this instance.
|
||||
/// </summary>
|
||||
/// <returns>A 32-bit signed integer that is the hash code for this instance.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Address.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
55
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/I1/See2Context.cs
vendored
Normal file
55
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/I1/See2Context.cs
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
#region Using
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Compress.SevenZip.Compress.PPmd.I1
|
||||
{
|
||||
/// <summary>
|
||||
/// SEE2 (secondary escape estimation) contexts for PPM contexts with masked symbols.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This must be a class rather than a structure because MakeEscapeFrequency returns a See2Context
|
||||
/// instance from the see2Contexts array. The caller (for example, EncodeSymbol2) then updates the
|
||||
/// returned See2Context instance and expects the updates to be reflected in the see2Contexts array.
|
||||
/// This would not happen if this were a structure.
|
||||
/// </para>
|
||||
/// <remarks>
|
||||
/// Note that in most cases fields are used rather than properties for performance reasons (for example,
|
||||
/// <see cref="Shift"/> is a field rather than a property).
|
||||
/// </remarks>
|
||||
/// </remarks>
|
||||
internal class See2Context
|
||||
{
|
||||
private const byte PeriodBitCount = 7;
|
||||
|
||||
public ushort Summary;
|
||||
public byte Shift;
|
||||
public byte Count;
|
||||
|
||||
public void Initialize(uint initialValue)
|
||||
{
|
||||
Shift = PeriodBitCount - 4;
|
||||
Summary = (ushort) (initialValue << Shift);
|
||||
Count = 7;
|
||||
}
|
||||
|
||||
public uint Mean()
|
||||
{
|
||||
uint value = (uint) (Summary >> Shift);
|
||||
Summary = (ushort) (Summary - value);
|
||||
return (uint) (value + ((value == 0) ? 1 : 0));
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (Shift < PeriodBitCount && --Count == 0)
|
||||
{
|
||||
Summary += Summary;
|
||||
Count = (byte) (3 << Shift++);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
81
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/PpmdProperties.cs
vendored
Normal file
81
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/PpmdProperties.cs
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
using System;
|
||||
|
||||
namespace Compress.SevenZip.Compress.PPmd
|
||||
{
|
||||
public enum PpmdVersion
|
||||
{
|
||||
H,
|
||||
H7z,
|
||||
I1,
|
||||
}
|
||||
|
||||
public class PpmdProperties
|
||||
{
|
||||
public PpmdVersion Version = PpmdVersion.I1;
|
||||
public int ModelOrder;
|
||||
internal I1.ModelRestorationMethod ModelRestorationMethod;
|
||||
|
||||
private int allocatorSize;
|
||||
internal I1.Allocator Allocator;
|
||||
|
||||
public PpmdProperties()
|
||||
: this(16 << 20, 6)
|
||||
{
|
||||
}
|
||||
|
||||
public PpmdProperties(int allocatorSize, int modelOrder)
|
||||
: this(allocatorSize, modelOrder, I1.ModelRestorationMethod.Restart)
|
||||
{
|
||||
}
|
||||
|
||||
internal PpmdProperties(int allocatorSize, int modelOrder, I1.ModelRestorationMethod modelRestorationMethod)
|
||||
{
|
||||
AllocatorSize = allocatorSize;
|
||||
ModelOrder = modelOrder;
|
||||
ModelRestorationMethod = modelRestorationMethod;
|
||||
}
|
||||
|
||||
public PpmdProperties(byte[] properties)
|
||||
{
|
||||
if (properties.Length == 2)
|
||||
{
|
||||
ushort props = BitConverter.ToUInt16(properties, 0);
|
||||
AllocatorSize = (((props >> 4) & 0xff) + 1) << 20;
|
||||
ModelOrder = (props & 0x0f) + 1;
|
||||
ModelRestorationMethod = (I1.ModelRestorationMethod)(props >> 12);
|
||||
}
|
||||
else if (properties.Length == 5)
|
||||
{
|
||||
Version = PpmdVersion.H7z;
|
||||
AllocatorSize = BitConverter.ToInt32(properties, 1);
|
||||
ModelOrder = properties[0];
|
||||
}
|
||||
}
|
||||
|
||||
public int AllocatorSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return allocatorSize;
|
||||
}
|
||||
set
|
||||
{
|
||||
allocatorSize = value;
|
||||
if (Version == PpmdVersion.I1)
|
||||
{
|
||||
if (Allocator == null)
|
||||
Allocator = new I1.Allocator();
|
||||
Allocator.Start(allocatorSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] Properties
|
||||
{
|
||||
get
|
||||
{
|
||||
return BitConverter.GetBytes((ushort)((ModelOrder - 1) + (((AllocatorSize >> 20) - 1) << 4) + ((ushort)ModelRestorationMethod << 12)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
154
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/PpmdStream.cs
vendored
Normal file
154
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/PpmdStream.cs
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Compress.SevenZip.Compress.RangeCoder;
|
||||
|
||||
namespace Compress.SevenZip.Compress.PPmd
|
||||
{
|
||||
public class PpmdStream : Stream
|
||||
{
|
||||
private PpmdProperties properties;
|
||||
private Stream stream;
|
||||
private bool compress;
|
||||
private I1.Model model;
|
||||
private H.ModelPPM modelH;
|
||||
private Decoder decoder;
|
||||
private long position = 0;
|
||||
|
||||
public PpmdStream(PpmdProperties properties, Stream stream, bool compress)
|
||||
{
|
||||
this.properties = properties;
|
||||
this.stream = stream;
|
||||
this.compress = compress;
|
||||
|
||||
if (properties.Version == PpmdVersion.I1)
|
||||
{
|
||||
model = new I1.Model();
|
||||
if (compress)
|
||||
model.EncodeStart(properties);
|
||||
else
|
||||
model.DecodeStart(stream, properties);
|
||||
}
|
||||
if (properties.Version == PpmdVersion.H)
|
||||
{
|
||||
modelH = new H.ModelPPM();
|
||||
if (compress)
|
||||
throw new NotImplementedException();
|
||||
else
|
||||
modelH.decodeInit(stream, properties.ModelOrder, properties.AllocatorSize);
|
||||
}
|
||||
if (properties.Version == PpmdVersion.H7z)
|
||||
{
|
||||
modelH = new H.ModelPPM();
|
||||
if (compress)
|
||||
throw new NotImplementedException();
|
||||
else
|
||||
modelH.decodeInit(null, properties.ModelOrder, properties.AllocatorSize);
|
||||
decoder = new Decoder();
|
||||
decoder.Init(stream);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanRead
|
||||
{
|
||||
get { return !compress; }
|
||||
}
|
||||
|
||||
public override bool CanSeek
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public override bool CanWrite
|
||||
{
|
||||
get { return compress; }
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
if (isDisposing)
|
||||
{
|
||||
if (compress)
|
||||
model.EncodeBlock(stream, new MemoryStream(), true);
|
||||
}
|
||||
base.Dispose(isDisposing);
|
||||
}
|
||||
|
||||
public override long Length
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get
|
||||
{
|
||||
return position;
|
||||
}
|
||||
set
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (compress)
|
||||
return 0;
|
||||
int size = 0;
|
||||
if (properties.Version == PpmdVersion.I1)
|
||||
size = model.DecodeBlock(stream, buffer, offset, count);
|
||||
if (properties.Version == PpmdVersion.H)
|
||||
{
|
||||
int c;
|
||||
while (size < count && (c = modelH.decodeChar()) >= 0)
|
||||
{
|
||||
buffer[offset++] = (byte)c;
|
||||
size++;
|
||||
}
|
||||
}
|
||||
if (properties.Version == PpmdVersion.H7z)
|
||||
{
|
||||
int c;
|
||||
while (size < count && (c = modelH.decodeChar(decoder)) >= 0)
|
||||
{
|
||||
buffer[offset++] = (byte)c;
|
||||
size++;
|
||||
}
|
||||
}
|
||||
position += size;
|
||||
return size;
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
if (origin != SeekOrigin.Current)
|
||||
throw new NotImplementedException();
|
||||
|
||||
byte[] tmpBuff = new byte[1024];
|
||||
long sizeToGo = offset;
|
||||
while (sizeToGo > 0)
|
||||
{
|
||||
int sizenow = sizeToGo > 1024 ? 1024 : (int)sizeToGo;
|
||||
Read(tmpBuff, 0, sizenow);
|
||||
sizeToGo -= sizenow;
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (compress)
|
||||
model.EncodeBlock(stream, new MemoryStream(buffer, offset, count), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
467
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/Utility.cs
vendored
Normal file
467
SabreTools.Library/External/Compress/SevenZip/Compress/PPmd/Utility.cs
vendored
Normal file
@@ -0,0 +1,467 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Compress.SevenZip.Compress.PPmd
|
||||
{
|
||||
internal static class Utility
|
||||
{
|
||||
public static ReadOnlyCollection<T> ToReadOnly<T>(this IEnumerable<T> items)
|
||||
{
|
||||
return new ReadOnlyCollection<T>(items.ToList());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an unsigned bitwise right shift with the specified number
|
||||
/// </summary>
|
||||
/// <param name="number">Number to operate on</param>
|
||||
/// <param name="bits">Ammount of bits to shift</param>
|
||||
/// <returns>The resulting number from the shift operation</returns>
|
||||
public static int URShift(int number, int bits)
|
||||
{
|
||||
if (number >= 0)
|
||||
return number >> bits;
|
||||
else
|
||||
return (number >> bits) + (2 << ~bits);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an unsigned bitwise right shift with the specified number
|
||||
/// </summary>
|
||||
/// <param name="number">Number to operate on</param>
|
||||
/// <param name="bits">Ammount of bits to shift</param>
|
||||
/// <returns>The resulting number from the shift operation</returns>
|
||||
public static int URShift(int number, long bits)
|
||||
{
|
||||
return URShift(number, (int)bits);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an unsigned bitwise right shift with the specified number
|
||||
/// </summary>
|
||||
/// <param name="number">Number to operate on</param>
|
||||
/// <param name="bits">Ammount of bits to shift</param>
|
||||
/// <returns>The resulting number from the shift operation</returns>
|
||||
public static long URShift(long number, int bits)
|
||||
{
|
||||
if (number >= 0)
|
||||
return number >> bits;
|
||||
else
|
||||
return (number >> bits) + (2L << ~bits);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an unsigned bitwise right shift with the specified number
|
||||
/// </summary>
|
||||
/// <param name="number">Number to operate on</param>
|
||||
/// <param name="bits">Ammount of bits to shift</param>
|
||||
/// <returns>The resulting number from the shift operation</returns>
|
||||
public static long URShift(long number, long bits)
|
||||
{
|
||||
return URShift(number, (int)bits);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fills the array with an specific value from an specific index to an specific index.
|
||||
/// </summary>
|
||||
/// <param name="array">The array to be filled.</param>
|
||||
/// <param name="fromindex">The first index to be filled.</param>
|
||||
/// <param name="toindex">The last index to be filled.</param>
|
||||
/// <param name="val">The value to fill the array with.</param>
|
||||
public static void Fill<T>(T[] array, int fromindex, int toindex, T val) where T : struct
|
||||
{
|
||||
if (array.Length == 0)
|
||||
{
|
||||
throw new NullReferenceException();
|
||||
}
|
||||
if (fromindex > toindex)
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
if ((fromindex < 0) || ((System.Array)array).Length < toindex)
|
||||
{
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
for (int index = (fromindex > 0) ? fromindex-- : fromindex; index < toindex; index++)
|
||||
{
|
||||
array[index] = val;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fills the array with an specific value.
|
||||
/// </summary>
|
||||
/// <param name="array">The array to be filled.</param>
|
||||
/// <param name="val">The value to fill the array with.</param>
|
||||
public static void Fill<T>(T[] array, T val) where T : struct
|
||||
{
|
||||
Fill(array, 0, array.Length, val);
|
||||
}
|
||||
|
||||
public static void SetSize(this List<byte> list, int count)
|
||||
{
|
||||
if (count > list.Count)
|
||||
{
|
||||
for (int i = list.Count; i < count; i++)
|
||||
{
|
||||
list.Add(0x0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] temp = new byte[count];
|
||||
list.CopyTo(temp, 0);
|
||||
list.Clear();
|
||||
list.AddRange(temp);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Read a int value from the byte array at the given position (Big Endian)
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="array">the array to read from
|
||||
/// </param>
|
||||
/// <param name="pos">the offset
|
||||
/// </param>
|
||||
/// <returns> the value
|
||||
/// </returns>
|
||||
public static int readIntBigEndian(byte[] array, int pos)
|
||||
{
|
||||
int temp = 0;
|
||||
temp |= array[pos] & 0xff;
|
||||
temp <<= 8;
|
||||
temp |= array[pos + 1] & 0xff;
|
||||
temp <<= 8;
|
||||
temp |= array[pos + 2] & 0xff;
|
||||
temp <<= 8;
|
||||
temp |= array[pos + 3] & 0xff;
|
||||
return temp;
|
||||
}
|
||||
|
||||
/// <summary> Read a short value from the byte array at the given position (little
|
||||
/// Endian)
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="array">the array to read from
|
||||
/// </param>
|
||||
/// <param name="pos">the offset
|
||||
/// </param>
|
||||
/// <returns> the value
|
||||
/// </returns>
|
||||
public static short readShortLittleEndian(byte[] array, int pos)
|
||||
{
|
||||
return BitConverter.ToInt16(array, pos);
|
||||
}
|
||||
|
||||
/// <summary> Read an int value from the byte array at the given position (little
|
||||
/// Endian)
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="array">the array to read from
|
||||
/// </param>
|
||||
/// <param name="pos">the offset
|
||||
/// </param>
|
||||
/// <returns> the value
|
||||
/// </returns>
|
||||
public static int readIntLittleEndian(byte[] array, int pos)
|
||||
{
|
||||
return BitConverter.ToInt32(array, pos);
|
||||
}
|
||||
|
||||
/// <summary> Write an int value into the byte array at the given position (Big endian)
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="array">the array
|
||||
/// </param>
|
||||
/// <param name="pos">the offset
|
||||
/// </param>
|
||||
/// <param name="value">the value to write
|
||||
/// </param>
|
||||
public static void writeIntBigEndian(byte[] array, int pos, int value)
|
||||
{
|
||||
array[pos] = (byte)((Utility.URShift(value, 24)) & 0xff);
|
||||
array[pos + 1] = (byte)((Utility.URShift(value, 16)) & 0xff);
|
||||
array[pos + 2] = (byte)((Utility.URShift(value, 8)) & 0xff);
|
||||
array[pos + 3] = (byte)((value) & 0xff);
|
||||
}
|
||||
|
||||
/// <summary> Write a short value into the byte array at the given position (little
|
||||
/// endian)
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="array">the array
|
||||
/// </param>
|
||||
/// <param name="pos">the offset
|
||||
/// </param>
|
||||
/// <param name="value">the value to write
|
||||
/// </param>
|
||||
public static void WriteLittleEndian(byte[] array, int pos, short value)
|
||||
{
|
||||
byte[] newBytes = BitConverter.GetBytes(value);
|
||||
Array.Copy(newBytes, 0, array, pos, newBytes.Length);
|
||||
}
|
||||
|
||||
/// <summary> Increment a short value at the specified position by the specified amount
|
||||
/// (little endian).
|
||||
/// </summary>
|
||||
public static void incShortLittleEndian(byte[] array, int pos, short incrementValue)
|
||||
{
|
||||
short existingValue = BitConverter.ToInt16(array, pos);
|
||||
existingValue += incrementValue;
|
||||
WriteLittleEndian(array, pos, existingValue);
|
||||
//int c = Utility.URShift(((array[pos] & 0xff) + (dv & 0xff)), 8);
|
||||
//array[pos] = (byte)(array[pos] + (dv & 0xff));
|
||||
//if ((c > 0) || ((dv & 0xff00) != 0))
|
||||
//{
|
||||
// array[pos + 1] = (byte)(array[pos + 1] + ((Utility.URShift(dv, 8)) & 0xff) + c);
|
||||
//}
|
||||
}
|
||||
|
||||
/// <summary> Write an int value into the byte array at the given position (little
|
||||
/// endian)
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="array">the array
|
||||
/// </param>
|
||||
/// <param name="pos">the offset
|
||||
/// </param>
|
||||
/// <param name="value">the value to write
|
||||
/// </param>
|
||||
public static void WriteLittleEndian(byte[] array, int pos, int value)
|
||||
{
|
||||
byte[] newBytes = BitConverter.GetBytes(value);
|
||||
Array.Copy(newBytes, 0, array, pos, newBytes.Length);
|
||||
}
|
||||
|
||||
public static void Initialize<T>(this T[] array, Func<T> func)
|
||||
{
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
array[i] = func();
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddRange<T>(this ICollection<T> destination, IEnumerable<T> source)
|
||||
{
|
||||
foreach (T item in source)
|
||||
{
|
||||
destination.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ForEach<T>(this IEnumerable<T> items, Action<T> action)
|
||||
{
|
||||
foreach (T item in items)
|
||||
{
|
||||
action(item);
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<T> AsEnumerable<T>(this T item)
|
||||
{
|
||||
yield return item;
|
||||
}
|
||||
|
||||
public static void CheckNotNull(this object obj, string name)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
throw new ArgumentNullException(name);
|
||||
}
|
||||
}
|
||||
|
||||
public static void CheckNotNullOrEmpty(this string obj, string name)
|
||||
{
|
||||
obj.CheckNotNull(name);
|
||||
if (obj.Length == 0)
|
||||
{
|
||||
throw new ArgumentException("String is empty.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void Skip(this Stream source, long advanceAmount)
|
||||
{
|
||||
byte[] buffer = new byte[32 * 1024];
|
||||
int read = 0;
|
||||
int readCount = 0;
|
||||
do
|
||||
{
|
||||
readCount = buffer.Length;
|
||||
if (readCount > advanceAmount)
|
||||
{
|
||||
readCount = (int)advanceAmount;
|
||||
}
|
||||
read = source.Read(buffer, 0, readCount);
|
||||
if (read < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
advanceAmount -= read;
|
||||
if (advanceAmount == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
|
||||
public static void SkipAll(this Stream source)
|
||||
{
|
||||
byte[] buffer = new byte[32 * 1024];
|
||||
do
|
||||
{
|
||||
} while (source.Read(buffer, 0, buffer.Length) == buffer.Length);
|
||||
}
|
||||
|
||||
|
||||
public static byte[] UInt32ToBigEndianBytes(uint x)
|
||||
{
|
||||
return new byte[] {
|
||||
(byte)((x >> 24) & 0xff),
|
||||
(byte)((x >> 16) & 0xff),
|
||||
(byte)((x >> 8) & 0xff),
|
||||
(byte)(x & 0xff) };
|
||||
}
|
||||
|
||||
public static DateTime DosDateToDateTime(UInt16 iDate, UInt16 iTime)
|
||||
{
|
||||
int year = iDate / 512 + 1980;
|
||||
int month = iDate % 512 / 32;
|
||||
int day = iDate % 512 % 32;
|
||||
int hour = iTime / 2048;
|
||||
int minute = iTime % 2048 / 32;
|
||||
int second = iTime % 2048 % 32 * 2;
|
||||
|
||||
if (iDate == UInt16.MaxValue || month == 0 || day == 0)
|
||||
{
|
||||
year = 1980;
|
||||
month = 1;
|
||||
day = 1;
|
||||
}
|
||||
|
||||
if (iTime == UInt16.MaxValue)
|
||||
{
|
||||
hour = minute = second = 0;
|
||||
}
|
||||
|
||||
DateTime dt;
|
||||
try
|
||||
{
|
||||
dt = new DateTime(year, month, day, hour, minute, second);
|
||||
}
|
||||
catch
|
||||
{
|
||||
dt = new DateTime();
|
||||
}
|
||||
return dt;
|
||||
}
|
||||
|
||||
public static uint DateTimeToDosTime(this DateTime? dateTime)
|
||||
{
|
||||
if (dateTime == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return (uint)(
|
||||
(dateTime.Value.Second / 2) | (dateTime.Value.Minute << 5) | (dateTime.Value.Hour << 11) |
|
||||
(dateTime.Value.Day << 16) | (dateTime.Value.Month << 21) | ((dateTime.Value.Year - 1980) << 25));
|
||||
}
|
||||
|
||||
|
||||
public static DateTime DosDateToDateTime(UInt32 iTime)
|
||||
{
|
||||
return DosDateToDateTime((UInt16)(iTime / 65536),
|
||||
(UInt16)(iTime % 65536));
|
||||
}
|
||||
|
||||
public static DateTime DosDateToDateTime(Int32 iTime)
|
||||
{
|
||||
return DosDateToDateTime((UInt32)iTime);
|
||||
}
|
||||
|
||||
public static long TransferTo(this Stream source, Stream destination)
|
||||
{
|
||||
byte[] array = new byte[4096];
|
||||
int count;
|
||||
long total = 0;
|
||||
while ((count = source.Read(array, 0, array.Length)) != 0)
|
||||
{
|
||||
total += count;
|
||||
destination.Write(array, 0, count);
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
public static bool ReadFully(this Stream stream, byte[] buffer)
|
||||
{
|
||||
int total = 0;
|
||||
int read;
|
||||
while ((read = stream.Read(buffer, total, buffer.Length - total)) > 0)
|
||||
{
|
||||
total += read;
|
||||
if (total >= buffer.Length)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return (total >= buffer.Length);
|
||||
}
|
||||
|
||||
public static string TrimNulls(this string source)
|
||||
{
|
||||
return source.Replace('\0', ' ').Trim();
|
||||
}
|
||||
|
||||
public static bool BinaryEquals(this byte[] source, byte[] target)
|
||||
{
|
||||
if (source.Length != target.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < source.Length; ++i)
|
||||
{
|
||||
if (source[i] != target[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#if PORTABLE
|
||||
public static void CopyTo(this byte[] array, byte[] destination, int index)
|
||||
{
|
||||
Array.Copy(array, 0, destination, index, array.Length);
|
||||
}
|
||||
|
||||
public static long HostToNetworkOrder(long host)
|
||||
{
|
||||
return (int)((long)HostToNetworkOrder((int)host)
|
||||
& unchecked((long)(unchecked((ulong)-1))) << 32
|
||||
| ((long)HostToNetworkOrder((int)((int)host >> 32)) & unchecked((long)(unchecked((ulong)-1)))));
|
||||
}
|
||||
public static int HostToNetworkOrder(int host)
|
||||
{
|
||||
return (int)((int)(HostToNetworkOrder((short)host) & -1) << 16 | (HostToNetworkOrder((short)(host >> 16)) & -1));
|
||||
}
|
||||
public static short HostToNetworkOrder(short host)
|
||||
{
|
||||
return (short)((int)(host & 255) << 8 | ((int)host >> 8 & 255));
|
||||
}
|
||||
public static long NetworkToHostOrder(long network)
|
||||
{
|
||||
return HostToNetworkOrder(network);
|
||||
}
|
||||
public static int NetworkToHostOrder(int network)
|
||||
{
|
||||
return HostToNetworkOrder(network);
|
||||
}
|
||||
public static short NetworkToHostOrder(short network)
|
||||
{
|
||||
return HostToNetworkOrder(network);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user