mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-13 20:11:35 -06:00
4.20
This commit is contained in:
committed by
Kornel Lesiński
parent
8c1b5c7b7e
commit
3c510ba80b
@@ -1,35 +1,42 @@
|
||||
// SubAlloc.h
|
||||
// PPMDSubAlloc.h
|
||||
// This code is based on Dmitry Shkarin's PPMdH code
|
||||
|
||||
#pragma once
|
||||
#ifndef __PPMD_SUBALLOC_H
|
||||
#define __PPMD_SUBALLOC_H
|
||||
|
||||
#ifndef __SubAlloc_H
|
||||
#define __SubAlloc_H
|
||||
#include "PPMDType.h"
|
||||
|
||||
#include "PPMdType.h"
|
||||
#include "../../../Common/Alloc.h"
|
||||
|
||||
const UINT N1=4, N2=4, N3=4, N4=(128+3-1*N1-2*N2-3*N3)/4;
|
||||
const UINT UNIT_SIZE=12, N_INDEXES=N1+N2+N3+N4;
|
||||
|
||||
#pragma pack(1)
|
||||
struct MEM_BLK {
|
||||
WORD Stamp, NU;
|
||||
MEM_BLK* next, * prev;
|
||||
void insertAt(MEM_BLK* p) {
|
||||
next=(prev=p)->next; p->next=next->prev=this;
|
||||
}
|
||||
void remove() { prev->next=next; next->prev=prev; }
|
||||
struct MEM_BLK
|
||||
{
|
||||
UInt16 Stamp, NU;
|
||||
MEM_BLK *Next, *Prev;
|
||||
void InsertAt(MEM_BLK* p)
|
||||
{
|
||||
Next = (Prev = p)->Next;
|
||||
p->Next = Next->Prev = this;
|
||||
}
|
||||
void Remove()
|
||||
{
|
||||
Prev->Next=Next;
|
||||
Next->Prev=Prev;
|
||||
}
|
||||
} _PACK_ATTR;
|
||||
#pragma pack()
|
||||
|
||||
|
||||
class CSubAllocator
|
||||
{
|
||||
DWORD SubAllocatorSize;
|
||||
BYTE Indx2Units[N_INDEXES], Units2Indx[128], GlueCount;
|
||||
struct NODE { NODE* next; } FreeList[N_INDEXES];
|
||||
UInt32 SubAllocatorSize;
|
||||
Byte Indx2Units[N_INDEXES], Units2Indx[128], GlueCount;
|
||||
struct NODE { NODE* Next; } FreeList[N_INDEXES];
|
||||
public:
|
||||
BYTE* HeapStart, * pText, * UnitsStart, * LoUnit, * HiUnit;
|
||||
Byte* HeapStart, *pText, *UnitsStart, *LoUnit, *HiUnit;
|
||||
CSubAllocator():
|
||||
SubAllocatorSize(0),
|
||||
GlueCount(0),
|
||||
@@ -47,159 +54,200 @@ public:
|
||||
};
|
||||
|
||||
|
||||
inline void InsertNode(void* p,int indx) {
|
||||
((NODE*) p)->next=FreeList[indx].next; FreeList[indx].next=(NODE*) p;
|
||||
}
|
||||
inline void* RemoveNode(int indx) {
|
||||
NODE* RetVal=FreeList[indx].next; FreeList[indx].next=RetVal->next;
|
||||
return RetVal;
|
||||
}
|
||||
inline UINT U2B(int NU) { return 8*NU+4*NU; }
|
||||
inline void SplitBlock(void* pv,int OldIndx,int NewIndx)
|
||||
{
|
||||
int i, UDiff=Indx2Units[OldIndx]-Indx2Units[NewIndx];
|
||||
BYTE* p=((BYTE*) 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]);
|
||||
}
|
||||
void InsertNode(void* p, int indx)
|
||||
{
|
||||
((NODE*) p)->Next = FreeList[indx].Next;
|
||||
FreeList[indx].Next = (NODE*)p;
|
||||
}
|
||||
|
||||
DWORD _STDCALL GetUsedMemory()
|
||||
{
|
||||
DWORD i, k, RetVal=SubAllocatorSize-(HiUnit-LoUnit)-(UnitsStart-pText);
|
||||
for (k=i=0;i < N_INDEXES;i++, k=0) {
|
||||
for (NODE* pn=FreeList+i;(pn=pn->next) != NULL;k++)
|
||||
;
|
||||
RetVal -= UNIT_SIZE*Indx2Units[i]*k;
|
||||
void* RemoveNode(int indx)
|
||||
{
|
||||
NODE* RetVal = FreeList[indx].Next;
|
||||
FreeList[indx].Next = RetVal->Next;
|
||||
return RetVal;
|
||||
}
|
||||
|
||||
UINT U2B(int NU) { return 8 * NU + 4 * NU; }
|
||||
|
||||
void SplitBlock(void* pv, int oldIndx, int newIndx)
|
||||
{
|
||||
int i, UDiff = Indx2Units[oldIndx] - Indx2Units[newIndx];
|
||||
Byte* p = ((Byte*)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]);
|
||||
}
|
||||
|
||||
UInt32 GetUsedMemory()
|
||||
{
|
||||
UInt32 i, k, RetVal = SubAllocatorSize - (HiUnit - LoUnit) - (UnitsStart-pText);
|
||||
for (k = i = 0; i < N_INDEXES; i++, k = 0)
|
||||
{
|
||||
for (NODE* pn = FreeList + i;(pn = pn->Next) != NULL; k++)
|
||||
;
|
||||
RetVal -= UNIT_SIZE*Indx2Units[i] * k;
|
||||
}
|
||||
return (RetVal >> 2);
|
||||
}
|
||||
|
||||
void _STDCALL StopSubAllocator()
|
||||
}
|
||||
|
||||
void StopSubAllocator()
|
||||
{
|
||||
if ( SubAllocatorSize )
|
||||
{
|
||||
#ifdef WIN32
|
||||
VirtualFree(HeapStart, 0, MEM_RELEASE);
|
||||
#else
|
||||
delete[] HeapStart;
|
||||
#endif
|
||||
BigFree(HeapStart);
|
||||
SubAllocatorSize = 0;
|
||||
HeapStart = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool _STDCALL StartSubAllocator(UINT32 aSize)
|
||||
bool StartSubAllocator(UInt32 size)
|
||||
{
|
||||
if (SubAllocatorSize == aSize)
|
||||
if (SubAllocatorSize == size)
|
||||
return true;
|
||||
StopSubAllocator();
|
||||
#ifdef WIN32
|
||||
if ((HeapStart = (BYTE *)::VirtualAlloc(0, aSize, MEM_COMMIT, PAGE_READWRITE)) == 0)
|
||||
if ((HeapStart = (Byte *)::BigAlloc(size)) == 0)
|
||||
return false;
|
||||
#else
|
||||
if ((HeapStart = new BYTE[aSize]) == NULL)
|
||||
return false;
|
||||
#endif
|
||||
SubAllocatorSize = aSize;
|
||||
SubAllocatorSize = size;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void InitSubAllocator()
|
||||
{
|
||||
void InitSubAllocator()
|
||||
{
|
||||
int i, k;
|
||||
memset(FreeList,0,sizeof(FreeList));
|
||||
HiUnit=(pText=HeapStart)+SubAllocatorSize;
|
||||
UINT Diff=UNIT_SIZE*(SubAllocatorSize/8/UNIT_SIZE*7);
|
||||
LoUnit=UnitsStart=HiUnit-Diff;
|
||||
for (i=0,k=1;i < N1 ;i++,k += 1) Indx2Units[i]=k;
|
||||
for (k++;i < N1+N2 ;i++,k += 2) Indx2Units[i]=k;
|
||||
for (k++;i < N1+N2+N3 ;i++,k += 3) Indx2Units[i]=k;
|
||||
for (k++;i < N1+N2+N3+N4;i++,k += 4) Indx2Units[i]=k;
|
||||
for (GlueCount=k=i=0;k < 128;k++) {
|
||||
i += (Indx2Units[i] < k+1); Units2Indx[k]=i;
|
||||
memset(FreeList, 0, sizeof(FreeList));
|
||||
HiUnit = (pText = HeapStart) + SubAllocatorSize;
|
||||
UINT Diff = UNIT_SIZE * (SubAllocatorSize / 8 / UNIT_SIZE * 7);
|
||||
LoUnit = UnitsStart = HiUnit - Diff;
|
||||
for (i = 0, k=1; i < N1 ; i++, k += 1) Indx2Units[i]=k;
|
||||
for (k++; i < N1 + N2 ;i++, k += 2) Indx2Units[i]=k;
|
||||
for (k++; i < N1 + N2 + N3 ;i++,k += 3) Indx2Units[i]=k;
|
||||
for (k++; i < N1 + N2 + N3 + N4; i++, k += 4) Indx2Units[i]=k;
|
||||
for (GlueCount = k = i = 0; k < 128; k++)
|
||||
{
|
||||
i += (Indx2Units[i] < k+1);
|
||||
Units2Indx[k]=i;
|
||||
}
|
||||
}
|
||||
inline void GlueFreeBlocks()
|
||||
{
|
||||
MEM_BLK s0, * p, * p1;
|
||||
}
|
||||
|
||||
void GlueFreeBlocks()
|
||||
{
|
||||
MEM_BLK s0, *p, *p1;
|
||||
int i, k, sz;
|
||||
if (LoUnit != HiUnit) *LoUnit=0;
|
||||
for (i=0, s0.next=s0.prev=&s0;i < N_INDEXES;i++)
|
||||
while ( FreeList[i].next ) {
|
||||
p=(MEM_BLK*) RemoveNode(i); p->insertAt(&s0);
|
||||
p->Stamp=0xFFFF; p->NU=Indx2Units[i];
|
||||
}
|
||||
for (p=s0.next;p != &s0;p=p->next)
|
||||
while ((p1=p+p->NU)->Stamp == 0xFFFF && int(p->NU)+p1->NU < 0x10000) {
|
||||
p1->remove(); p->NU += p1->NU;
|
||||
}
|
||||
while ((p=s0.next) != &s0) {
|
||||
for (p->remove(), sz=p->NU;sz > 128;sz -= 128, p += 128)
|
||||
InsertNode(p,N_INDEXES-1);
|
||||
if (Indx2Units[i=Units2Indx[sz-1]] != sz) {
|
||||
k=sz-Indx2Units[--i]; InsertNode(p+(sz-k),k-1);
|
||||
}
|
||||
InsertNode(p,i);
|
||||
if (LoUnit != HiUnit)
|
||||
*LoUnit=0;
|
||||
for (i = 0, s0.Next = s0.Prev = &s0; i < N_INDEXES; i++)
|
||||
while ( FreeList[i].Next )
|
||||
{
|
||||
p = (MEM_BLK*) RemoveNode(i);
|
||||
p->InsertAt(&s0);
|
||||
p->Stamp = 0xFFFF;
|
||||
p->NU = Indx2Units[i];
|
||||
}
|
||||
for (p=s0.Next; p != &s0; p =p->Next)
|
||||
while ((p1 = p + p->NU)->Stamp == 0xFFFF && int(p->NU) + p1->NU < 0x10000)
|
||||
{
|
||||
p1->Remove();
|
||||
p->NU += p1->NU;
|
||||
}
|
||||
while ((p=s0.Next) != &s0)
|
||||
{
|
||||
for (p->Remove(), sz=p->NU; sz > 128; sz -= 128, p += 128)
|
||||
InsertNode(p, N_INDEXES - 1);
|
||||
if (Indx2Units[i = Units2Indx[sz-1]] != sz)
|
||||
{
|
||||
k = sz-Indx2Units[--i];
|
||||
InsertNode(p + (sz - k), k - 1);
|
||||
}
|
||||
InsertNode(p,i);
|
||||
}
|
||||
}
|
||||
void* AllocUnitsRare(int indx)
|
||||
{
|
||||
if ( !GlueCount ) {
|
||||
GlueCount = 255; GlueFreeBlocks();
|
||||
if ( FreeList[indx].next ) return RemoveNode(indx);
|
||||
}
|
||||
void* AllocUnitsRare(int indx)
|
||||
{
|
||||
if ( !GlueCount )
|
||||
{
|
||||
GlueCount = 255;
|
||||
GlueFreeBlocks();
|
||||
if (FreeList[indx].Next)
|
||||
return RemoveNode(indx);
|
||||
}
|
||||
int i=indx;
|
||||
do {
|
||||
if (++i == N_INDEXES) {
|
||||
GlueCount--; i=U2B(Indx2Units[indx]);
|
||||
return (UnitsStart-pText > i)?(UnitsStart -= i):(NULL);
|
||||
}
|
||||
} while ( !FreeList[i].next );
|
||||
void* RetVal=RemoveNode(i); SplitBlock(RetVal,i,indx);
|
||||
int i = indx;
|
||||
do
|
||||
{
|
||||
if (++i == N_INDEXES)
|
||||
{
|
||||
GlueCount--;
|
||||
i = U2B(Indx2Units[indx]);
|
||||
return (UnitsStart - pText > i) ? (UnitsStart -= i) : (NULL);
|
||||
}
|
||||
} while (!FreeList[i].Next);
|
||||
void* RetVal = RemoveNode(i);
|
||||
SplitBlock(RetVal, i, indx);
|
||||
return RetVal;
|
||||
}
|
||||
inline void* AllocUnits(int NU)
|
||||
{
|
||||
int indx=Units2Indx[NU-1];
|
||||
if ( FreeList[indx].next ) return RemoveNode(indx);
|
||||
void* RetVal=LoUnit; LoUnit += U2B(Indx2Units[indx]);
|
||||
if (LoUnit <= HiUnit) return RetVal;
|
||||
LoUnit -= U2B(Indx2Units[indx]); return AllocUnitsRare(indx);
|
||||
}
|
||||
inline void* AllocContext()
|
||||
{
|
||||
if (HiUnit != LoUnit) return (HiUnit -= UNIT_SIZE);
|
||||
if ( FreeList->next ) return RemoveNode(0);
|
||||
}
|
||||
|
||||
void* AllocUnits(int NU)
|
||||
{
|
||||
int indx = Units2Indx[NU - 1];
|
||||
if (FreeList[indx].Next)
|
||||
return RemoveNode(indx);
|
||||
void* RetVal = LoUnit;
|
||||
LoUnit += U2B(Indx2Units[indx]);
|
||||
if (LoUnit <= HiUnit)
|
||||
return RetVal;
|
||||
LoUnit -= U2B(Indx2Units[indx]);
|
||||
return AllocUnitsRare(indx);
|
||||
}
|
||||
|
||||
void* AllocContext()
|
||||
{
|
||||
if (HiUnit != LoUnit)
|
||||
return (HiUnit -= UNIT_SIZE);
|
||||
if (FreeList->Next)
|
||||
return RemoveNode(0);
|
||||
return AllocUnitsRare(0);
|
||||
}
|
||||
inline void* ExpandUnits(void* OldPtr,int OldNU)
|
||||
{
|
||||
int i0=Units2Indx[OldNU-1], i1=Units2Indx[OldNU-1+1];
|
||||
if (i0 == i1) return OldPtr;
|
||||
void* ptr=AllocUnits(OldNU+1);
|
||||
if ( ptr ) {
|
||||
memcpy(ptr,OldPtr,U2B(OldNU)); InsertNode(OldPtr,i0);
|
||||
}
|
||||
|
||||
void* ExpandUnits(void* oldPtr, int oldNU)
|
||||
{
|
||||
int i0=Units2Indx[oldNU - 1], i1=Units2Indx[oldNU - 1 + 1];
|
||||
if (i0 == i1)
|
||||
return oldPtr;
|
||||
void* ptr = AllocUnits(oldNU + 1);
|
||||
if (ptr)
|
||||
{
|
||||
memcpy(ptr, oldPtr, U2B(oldNU));
|
||||
InsertNode(oldPtr, i0);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
inline void* ShrinkUnits(void* OldPtr,int OldNU,int NewNU)
|
||||
{
|
||||
int i0=Units2Indx[OldNU-1], i1=Units2Indx[NewNU-1];
|
||||
if (i0 == i1) return OldPtr;
|
||||
if ( FreeList[i1].next ) {
|
||||
void* ptr=RemoveNode(i1); memcpy(ptr,OldPtr,U2B(NewNU));
|
||||
InsertNode(OldPtr,i0); return ptr;
|
||||
} else {
|
||||
SplitBlock(OldPtr,i0,i1); return OldPtr;
|
||||
}
|
||||
|
||||
void* ShrinkUnits(void* oldPtr, int oldNU, int newNU)
|
||||
{
|
||||
int i0 = Units2Indx[oldNU - 1], i1 = Units2Indx[newNU - 1];
|
||||
if (i0 == i1)
|
||||
return oldPtr;
|
||||
if ( FreeList[i1].Next )
|
||||
{
|
||||
void* ptr = RemoveNode(i1);
|
||||
memcpy(ptr, oldPtr, U2B(newNU));
|
||||
InsertNode(oldPtr,i0);
|
||||
return ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
SplitBlock(oldPtr, i0, i1);
|
||||
return oldPtr;
|
||||
}
|
||||
}
|
||||
inline void FreeUnits(void* ptr,int OldNU)
|
||||
{
|
||||
InsertNode(ptr,Units2Indx[OldNU-1]);
|
||||
}
|
||||
}
|
||||
|
||||
void FreeUnits(void* ptr, int oldNU)
|
||||
{
|
||||
InsertNode(ptr, Units2Indx[oldNU - 1]);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user