Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '7zip/Compress/PPMD/PPMDSubAlloc.h')
-rwxr-xr-x7zip/Compress/PPMD/PPMDSubAlloc.h147
1 files changed, 90 insertions, 57 deletions
diff --git a/7zip/Compress/PPMD/PPMDSubAlloc.h b/7zip/Compress/PPMD/PPMDSubAlloc.h
index 5a333fe3..fd64d577 100755
--- a/7zip/Compress/PPMD/PPMDSubAlloc.h
+++ b/7zip/Compress/PPMD/PPMDSubAlloc.h
@@ -11,39 +11,47 @@
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)
+// Extra 1 * UNIT_SIZE for NULL support
+// Extra 2 * UNIT_SIZE for s0 in GlueFreeBlocks()
+const UInt32 kExtraSize = (UNIT_SIZE * 3);
+const UInt32 kMaxMemBlockSize = 0xFFFFFFFF - kExtraSize;
+
struct MEM_BLK
{
UInt16 Stamp, NU;
- MEM_BLK *Next, *Prev;
- void InsertAt(MEM_BLK* p)
+ UInt32 Next, Prev;
+ void InsertAt(Byte *Base, UInt32 p)
{
- Next = (Prev = p)->Next;
- p->Next = Next->Prev = this;
+ Prev = p;
+ MEM_BLK *pp = (MEM_BLK *)(Base + p);
+ Next = pp->Next;
+ pp->Next = ((MEM_BLK *)(Base + Next))->Prev = (Byte *)this - Base;
}
- void Remove()
+ void Remove(Byte *Base)
{
- Prev->Next=Next;
- Next->Prev=Prev;
+ ((MEM_BLK *)(Base + Prev))->Next = Next;
+ ((MEM_BLK *)(Base + Next))->Prev = Prev;
}
-} _PACK_ATTR;
-#pragma pack()
+};
class CSubAllocator
{
UInt32 SubAllocatorSize;
Byte Indx2Units[N_INDEXES], Units2Indx[128], GlueCount;
- struct NODE { NODE* Next; } FreeList[N_INDEXES];
+ UInt32 FreeList[N_INDEXES];
+
+ Byte *Base;
+ Byte *HeapStart, *LoUnit, *HiUnit;
public:
- Byte* HeapStart, *pText, *UnitsStart, *LoUnit, *HiUnit;
+ Byte *pText, *UnitsStart;
CSubAllocator():
SubAllocatorSize(0),
GlueCount(0),
- pText(0),
- UnitsStart(0),
LoUnit(0),
- HiUnit(0)
+ HiUnit(0),
+ pText(0),
+ UnitsStart(0)
{
memset(Indx2Units, 0, sizeof(Indx2Units));
memset(FreeList, 0, sizeof(FreeList));
@@ -53,21 +61,28 @@ public:
StopSubAllocator();
};
+ void *GetPtr(UInt32 offset) const { return (offset == 0) ? 0 : (void *)(Base + offset); }
+ void *GetPtrNoCheck(UInt32 offset) const { return (void *)(Base + offset); }
+ UInt32 GetOffset(void *ptr) const { return (ptr == 0) ? 0 : (UInt32)((Byte *)ptr - Base); }
+ UInt32 GetOffsetNoCheck(void *ptr) const { return (UInt32)((Byte *)ptr - Base); }
+ MEM_BLK *GetBlk(UInt32 offset) const { return (MEM_BLK *)(Base + offset); }
+ UInt32 *GetNode(UInt32 offset) const { return (UInt32 *)(Base + offset); }
void InsertNode(void* p, int indx)
{
- ((NODE*) p)->Next = FreeList[indx].Next;
- FreeList[indx].Next = (NODE*)p;
+ *(UInt32 *)p = FreeList[indx];
+ FreeList[indx] = GetOffsetNoCheck(p);
}
void* RemoveNode(int indx)
{
- NODE* RetVal = FreeList[indx].Next;
- FreeList[indx].Next = RetVal->Next;
- return RetVal;
+ UInt32 offset = FreeList[indx];
+ UInt32 *p = GetNode(offset);
+ FreeList[indx] = *p;
+ return (void *)p;
}
- UINT U2B(int NU) { return 8 * NU + 4 * NU; }
+ UINT U2B(int NU) const { return (UINT)(NU) * UNIT_SIZE; }
void SplitBlock(void* pv, int oldIndx, int newIndx)
{
@@ -82,25 +97,22 @@ public:
InsertNode(p, Units2Indx[UDiff - 1]);
}
- UInt32 GetUsedMemory()
+ UInt32 GetUsedMemory() const
{
- UInt32 i, k, RetVal = SubAllocatorSize - (UInt32)(HiUnit - LoUnit) - (UInt32)(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;
- }
+ UInt32 RetVal = SubAllocatorSize - (UInt32)(HiUnit - LoUnit) - (UInt32)(UnitsStart - pText);
+ for (UInt32 i = 0; i < N_INDEXES; i++)
+ for (UInt32 pn = FreeList[i]; pn != 0; RetVal -= (UInt32)Indx2Units[i] * UNIT_SIZE)
+ pn = *GetNode(pn);
return (RetVal >> 2);
}
void StopSubAllocator()
{
- if ( SubAllocatorSize )
+ if (SubAllocatorSize != 0)
{
- BigFree(HeapStart);
+ BigFree(Base);
SubAllocatorSize = 0;
- HeapStart = 0;
+ Base = 0;
}
}
@@ -110,10 +122,13 @@ public:
return true;
StopSubAllocator();
if (size == 0)
- HeapStart = 0;
+ Base = 0;
else
- if ((HeapStart = (Byte *)::BigAlloc(size)) == 0)
+ {
+ if ((Base = (Byte *)::BigAlloc(size + kExtraSize)) == 0)
return false;
+ HeapStart = Base + UNIT_SIZE; // we need such code to support NULL;
+ }
SubAllocatorSize = size;
return true;
}
@@ -138,34 +153,52 @@ public:
void GlueFreeBlocks()
{
- MEM_BLK s0, *p, *p1;
- int i, k, sz;
+ UInt32 s0 = (UInt32)(HeapStart + SubAllocatorSize - Base);
+
+ // We need add exta MEM_BLK with Stamp=0
+ GetBlk(s0)->Stamp = 0;
+ s0 += UNIT_SIZE;
+ MEM_BLK *ps0 = GetBlk(s0);
+
+ UInt32 p;
+ int i;
if (LoUnit != HiUnit)
*LoUnit=0;
- for (i = 0, s0.Next = s0.Prev = &s0; i < N_INDEXES; i++)
- while ( FreeList[i].Next )
+ ps0->Next = ps0->Prev = s0;
+
+ for (i = 0; i < N_INDEXES; i++)
+ while (FreeList[i] != 0)
{
- p = (MEM_BLK*) RemoveNode(i);
- p->InsertAt(&s0);
- p->Stamp = 0xFFFF;
- p->NU = Indx2Units[i];
+ MEM_BLK *pp = (MEM_BLK *)RemoveNode(i);
+ pp->InsertAt(Base, s0);
+ pp->Stamp = 0xFFFF;
+ pp->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)
+ for (p = ps0->Next; p != s0; p = GetBlk(p)->Next)
+ {
+ while (true)
{
- p1->Remove();
- p->NU += p1->NU;
+ MEM_BLK *pp = GetBlk(p);
+ MEM_BLK *pp1 = GetBlk(p + pp->NU * UNIT_SIZE);
+ if (pp1->Stamp != 0xFFFF || int(pp->NU) + pp1->NU >= 0x10000)
+ break;
+ pp1->Remove(Base);
+ pp->NU += pp1->NU;
}
- while ((p=s0.Next) != &s0)
+ }
+ while ((p = ps0->Next) != s0)
{
- for (p->Remove(), sz=p->NU; sz > 128; sz -= 128, p += 128)
- InsertNode(p, N_INDEXES - 1);
+ MEM_BLK *pp = GetBlk(p);
+ pp->Remove(Base);
+ int sz;
+ for (sz = pp->NU; sz > 128; sz -= 128, p += 128 * UNIT_SIZE)
+ InsertNode(Base + p, N_INDEXES - 1);
if (Indx2Units[i = Units2Indx[sz-1]] != sz)
{
- k = sz-Indx2Units[--i];
- InsertNode(p + (sz - k), k - 1);
+ int k = sz - Indx2Units[--i];
+ InsertNode(Base + p + (sz - k) * UNIT_SIZE, k - 1);
}
- InsertNode(p,i);
+ InsertNode(Base + p, i);
}
}
void* AllocUnitsRare(int indx)
@@ -174,7 +207,7 @@ public:
{
GlueCount = 255;
GlueFreeBlocks();
- if (FreeList[indx].Next)
+ if (FreeList[indx] != 0)
return RemoveNode(indx);
}
int i = indx;
@@ -186,7 +219,7 @@ public:
i = U2B(Indx2Units[indx]);
return (UnitsStart - pText > i) ? (UnitsStart -= i) : (NULL);
}
- } while (!FreeList[i].Next);
+ } while (FreeList[i] == 0);
void* RetVal = RemoveNode(i);
SplitBlock(RetVal, i, indx);
return RetVal;
@@ -195,7 +228,7 @@ public:
void* AllocUnits(int NU)
{
int indx = Units2Indx[NU - 1];
- if (FreeList[indx].Next)
+ if (FreeList[indx] != 0)
return RemoveNode(indx);
void* RetVal = LoUnit;
LoUnit += U2B(Indx2Units[indx]);
@@ -209,7 +242,7 @@ public:
{
if (HiUnit != LoUnit)
return (HiUnit -= UNIT_SIZE);
- if (FreeList->Next)
+ if (FreeList[0] != 0)
return RemoveNode(0);
return AllocUnitsRare(0);
}
@@ -233,7 +266,7 @@ public:
int i0 = Units2Indx[oldNU - 1], i1 = Units2Indx[newNU - 1];
if (i0 == i1)
return oldPtr;
- if ( FreeList[i1].Next )
+ if (FreeList[i1] != 0)
{
void* ptr = RemoveNode(i1);
memcpy(ptr, oldPtr, U2B(newNU));