📄 suballocator.java.svn-base
字号:
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 31.05.2007
*
* Source: $HeadURL$
* Last changed: $LastChangedDate$
*
* the unrar licence applies to all junrar source and binary distributions
* you are not allowed to use this source to re-create the RAR compression algorithm
*
* Here some html entities which can be used for escaping javadoc tags:
* "&": "&" or "&"
* "<": "<" or "<"
* ">": ">" or ">"
* "@": "@"
*/
package de.innosystec.unrar.unpack.ppm;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Arrays;
import java.util.List;
import de.innosystec.unrar.Archive;
import de.innosystec.unrar.io.ReadOnlyAccessFile;
import de.innosystec.unrar.rarfile.BaseBlock;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class SubAllocator
{
public static final int N1 = 4, N2 = 4, N3 = 4, N4 = (128 + 3 - 1 * N1 - 2
* N2 - 3 * N3) / 4;
public static final int N_INDEXES = N1 + N2 + N3 + N4;
public static final int UNIT_SIZE = Math.max(PPMContext.size,
RarMemBlock.size);
public static final int FIXED_UNIT_SIZE = 12;
private int subAllocatorSize;
private short[] indx2Units = new short[N_INDEXES];
private short[] units2Indx = new short[128];
private short glueCount;
private int heapStart, loUnit, hiUnit;
private RarNode[] FreeList = new RarNode[N_INDEXES];
//
private int pText, unitsStart, heapEnd, fakeUnitsStart;
private byte[] heap;
private int freeListPos;
private int tempMemBlockPos;
public SubAllocator()
{
clean();
}
public void clean()
{
subAllocatorSize = 0;
}
private void insertNode(int p/* rarnode ptr */, int indx)
{
RarNode temp = new RarNode(heap);
temp.setAddress(p);
temp.setNext(FreeList[indx].getNext());
FreeList[indx].setNext(temp);
}
public void incPText(){
pText++;
}
private int removeNode(int indx)
{
int retVal = FreeList[indx].getNext();
RarNode temp = new RarNode(heap);
temp.setAddress(retVal);
FreeList[indx].setNext(temp.getNext());
return retVal;
}
private int U2B(int NU)
{
return /* 8*NU+4*NU */UNIT_SIZE * NU;
}
/* memblockptr */
private int MBPtr(int BasePtr, int Items)
{
return (BasePtr + U2B(Items));
}
private void splitBlock(int pv/* ptr */, 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 void stopSubAllocator()
{
if (subAllocatorSize != 0) {
subAllocatorSize = 0;
heap = null;
heapStart = 1;
// rarfree(HeapStart);
}
}
public int GetAllocatedMemory()
{
return subAllocatorSize;
};
public boolean startSubAllocator(int SASize)
{
int t = SASize << 20;
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;
freeListPos = allocSize;
heap = new byte[(int) realAllocSize];
heapStart = 1;
heapEnd = heapStart + allocSize - UNIT_SIZE;
subAllocatorSize = t;
return true;
}
private void glueFreeBlocks()
{
RarMemBlock s0 = new RarMemBlock(heap);
s0.setAddress((int) tempMemBlockPos);
RarMemBlock p = new RarMemBlock(heap);
RarMemBlock p1 = new RarMemBlock(heap);
int i, k, sz;
if (loUnit != hiUnit) {
heap[(int) loUnit] = 0;
}
for (i = 0, s0.setPrev(s0), s0.setNext(s0); i < N_INDEXES; i++) {
while (FreeList[i].getNext() == 0) {
p.setAddress(removeNode(i));// =(RAR_MEM_BLK*)RemoveNode(i);
p.insertAt(s0);// p->insertAt(&s0);
p.setStamp((short) 0xFFFF);// p->Stamp=0xFFFF;
p.setNU(indx2Units[i]);// p->NU=Indx2Units[i];
}
}
for (p.setAddress(s0.getNext()); p.getAddress() != s0.getAddress(); p
.setAddress(p.getNext())) {
// while ((p1=MBPtr(p,p->NU))->Stamp == 0xFFFF && int(p->NU)+p1->NU
// < 0x10000)
for (p1.setAddress(MBPtr(p.getAddress(), p.getNU())); p1.getStamp() == (short) 0xFFFF
&& (int) (p.getNU() + p1.getNU()) < 0x10000;) {
p1.remove();
p.setNU((short) (p.getNU() + p1.getNU()));// ->NU += p1->NU;
}
}
// while ((p=s0.next) != &s0)
for (p.setAddress(s0.getNext()); p.getAddress() != s0.getAddress();) {
for (p.remove(), sz = p.getNU(); sz > 128; sz -= 128, p
.setAddress(MBPtr(p.getAddress(), 128))) {
insertNode(p.getAddress(), N_INDEXES - 1);
}
if (indx2Units[i = units2Indx[sz - 1]] != sz) {
k = sz - indx2Units[--i];
insertNode(MBPtr(p.getAddress(), sz - k), k - 1);
}
insertNode(p.getAddress(), i);
}
}
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 ((int) unitsStart);
}
return (0);
}
} while (FreeList[i].getNext() == 0);
int retVal = removeNode(i);
splitBlock(retVal, i, indx);
return retVal;
}
public 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 int allocContext()
{
if (hiUnit != loUnit)
return (hiUnit -= UNIT_SIZE);
if (FreeList[0].getNext() != 0) {
return removeNode(0);
}
return allocUnitsRare(0);
}
public 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));
for (int i = 0; i < U2B(OldNU); i++) {
heap[ptr + i] = heap[OldPtr + i];
}
insertNode(OldPtr, i0);
}
return ptr;
}
public int shrinkUnits(int OldPtr, int OldNU, int NewNU)
{
int i0 = units2Indx[OldNU - 1], 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];
}
insertNode(OldPtr, i0);
return ptr;
} else {
splitBlock(OldPtr, i0, i1);
return OldPtr;
}
}
public void freeUnits(int ptr, int OldNU)
{
insertNode(ptr, units2Indx[OldNU - 1]);
}
public int getFakeUnitsStart()
{
return fakeUnitsStart;
}
public void setFakeUnitsStart(int fakeUnitsStart)
{
this.fakeUnitsStart = fakeUnitsStart;
}
public int getHeapEnd()
{
return heapEnd;
}
public void setHeapEnd(int heapEnd)
{
this.heapEnd = heapEnd;
}
public int getPText()
{
return pText;
}
public void setPText(int text)
{
pText = text;
}
public int getUnitsStart()
{
return unitsStart;
}
public void setUnitsStart(int unitsStart)
{
this.unitsStart = unitsStart;
}
public void initSubAllocator()
{
int i, k;
for (int j = 0; j < FreeList.length; j++) {
FreeList[j] = new RarNode(heap);
}
for (int j = (int) freeListPos; j < heap.length; j++) {
heap[j] = 0;
}
for (int j = (int) freeListPos, l = 0; j < tempMemBlockPos-1; j += 4, l++) {
FreeList[l].setAddress(j);
}
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] = (short) k;
}
for (k++; i < N1 + N2; i++, k += 2) {
indx2Units[i] = (short) k;
}
for (k++; i < N1 + N2 + N3; i++, k += 3) {
indx2Units[i] = (short) k;
}
for (k++; i < (N1 + N2 + N3 + N4); i++, k += 4) {
indx2Units[i] = (short) k;
}
for (glueCount = (short) 0, k = 0, i = 0; k < 128; k++) {
i += ((indx2Units[i] < (k + 1)) ? 1 : 0);
units2Indx[k] = (short) i;
}
}
public byte[] getHeap()
{
return heap;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -