Mercurial > vba-linux
diff src/win32/7zip/7z/CPP/7zip/Compress/PpmdSubAlloc.h @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/win32/7zip/7z/CPP/7zip/Compress/PpmdSubAlloc.h Sat Mar 03 10:31:27 2012 -0600 1.3 @@ -0,0 +1,295 @@ 1.4 +// PpmdSubAlloc.h 1.5 +// This code is based on Dmitry Shkarin's PPMdH code 1.6 + 1.7 +#ifndef __COMPRESS_PPMD_SUB_ALLOC_H 1.8 +#define __COMPRESS_PPMD_SUB_ALLOC_H 1.9 + 1.10 +extern "C" 1.11 +{ 1.12 +#include "../../../C/Alloc.h" 1.13 +} 1.14 + 1.15 +#include "PpmdType.h" 1.16 + 1.17 +const UINT N1=4, N2=4, N3=4, N4=(128+3-1*N1-2*N2-3*N3)/4; 1.18 +const UINT UNIT_SIZE=12, N_INDEXES=N1+N2+N3+N4; 1.19 + 1.20 +// Extra 1 * UNIT_SIZE for NULL support 1.21 +// Extra 2 * UNIT_SIZE for s0 in GlueFreeBlocks() 1.22 +const UInt32 kExtraSize = (UNIT_SIZE * 3); 1.23 +const UInt32 kMaxMemBlockSize = 0xFFFFFFFF - kExtraSize; 1.24 + 1.25 +struct MEM_BLK 1.26 +{ 1.27 + UInt16 Stamp, NU; 1.28 + UInt32 Next, Prev; 1.29 + void InsertAt(Byte *Base, UInt32 p) 1.30 + { 1.31 + Prev = p; 1.32 + MEM_BLK *pp = (MEM_BLK *)(Base + p); 1.33 + Next = pp->Next; 1.34 + pp->Next = ((MEM_BLK *)(Base + Next))->Prev = (UInt32)((Byte *)this - Base); 1.35 + } 1.36 + void Remove(Byte *Base) 1.37 + { 1.38 + ((MEM_BLK *)(Base + Prev))->Next = Next; 1.39 + ((MEM_BLK *)(Base + Next))->Prev = Prev; 1.40 + } 1.41 +}; 1.42 + 1.43 + 1.44 +class CSubAllocator 1.45 +{ 1.46 + UInt32 SubAllocatorSize; 1.47 + Byte Indx2Units[N_INDEXES], Units2Indx[128], GlueCount; 1.48 + UInt32 FreeList[N_INDEXES]; 1.49 + 1.50 + Byte *Base; 1.51 + Byte *HeapStart, *LoUnit, *HiUnit; 1.52 +public: 1.53 + Byte *pText, *UnitsStart; 1.54 + CSubAllocator(): 1.55 + SubAllocatorSize(0), 1.56 + GlueCount(0), 1.57 + LoUnit(0), 1.58 + HiUnit(0), 1.59 + pText(0), 1.60 + UnitsStart(0) 1.61 + { 1.62 + memset(Indx2Units, 0, sizeof(Indx2Units)); 1.63 + memset(FreeList, 0, sizeof(FreeList)); 1.64 + } 1.65 + ~CSubAllocator() 1.66 + { 1.67 + StopSubAllocator(); 1.68 + }; 1.69 + 1.70 + void *GetPtr(UInt32 offset) const { return (offset == 0) ? 0 : (void *)(Base + offset); } 1.71 + void *GetPtrNoCheck(UInt32 offset) const { return (void *)(Base + offset); } 1.72 + UInt32 GetOffset(void *ptr) const { return (ptr == 0) ? 0 : (UInt32)((Byte *)ptr - Base); } 1.73 + UInt32 GetOffsetNoCheck(void *ptr) const { return (UInt32)((Byte *)ptr - Base); } 1.74 + MEM_BLK *GetBlk(UInt32 offset) const { return (MEM_BLK *)(Base + offset); } 1.75 + UInt32 *GetNode(UInt32 offset) const { return (UInt32 *)(Base + offset); } 1.76 + 1.77 + void InsertNode(void* p, int indx) 1.78 + { 1.79 + *(UInt32 *)p = FreeList[indx]; 1.80 + FreeList[indx] = GetOffsetNoCheck(p); 1.81 + } 1.82 + 1.83 + void* RemoveNode(int indx) 1.84 + { 1.85 + UInt32 offset = FreeList[indx]; 1.86 + UInt32 *p = GetNode(offset); 1.87 + FreeList[indx] = *p; 1.88 + return (void *)p; 1.89 + } 1.90 + 1.91 + UINT U2B(int NU) const { return (UINT)(NU) * UNIT_SIZE; } 1.92 + 1.93 + void SplitBlock(void* pv, int oldIndx, int newIndx) 1.94 + { 1.95 + int i, UDiff = Indx2Units[oldIndx] - Indx2Units[newIndx]; 1.96 + Byte* p = ((Byte*)pv) + U2B(Indx2Units[newIndx]); 1.97 + if (Indx2Units[i = Units2Indx[UDiff-1]] != UDiff) 1.98 + { 1.99 + InsertNode(p, --i); 1.100 + p += U2B(i = Indx2Units[i]); 1.101 + UDiff -= i; 1.102 + } 1.103 + InsertNode(p, Units2Indx[UDiff - 1]); 1.104 + } 1.105 + 1.106 + UInt32 GetUsedMemory() const 1.107 + { 1.108 + UInt32 RetVal = SubAllocatorSize - (UInt32)(HiUnit - LoUnit) - (UInt32)(UnitsStart - pText); 1.109 + for (UInt32 i = 0; i < N_INDEXES; i++) 1.110 + for (UInt32 pn = FreeList[i]; pn != 0; RetVal -= (UInt32)Indx2Units[i] * UNIT_SIZE) 1.111 + pn = *GetNode(pn); 1.112 + return (RetVal >> 2); 1.113 + } 1.114 + 1.115 + UInt32 GetSubAllocatorSize() const { return SubAllocatorSize; } 1.116 + 1.117 + void StopSubAllocator() 1.118 + { 1.119 + if (SubAllocatorSize != 0) 1.120 + { 1.121 + BigFree(Base); 1.122 + SubAllocatorSize = 0; 1.123 + Base = 0; 1.124 + } 1.125 + } 1.126 + 1.127 + bool StartSubAllocator(UInt32 size) 1.128 + { 1.129 + if (SubAllocatorSize == size) 1.130 + return true; 1.131 + StopSubAllocator(); 1.132 + if (size == 0) 1.133 + Base = 0; 1.134 + else 1.135 + { 1.136 + if ((Base = (Byte *)::BigAlloc(size + kExtraSize)) == 0) 1.137 + return false; 1.138 + HeapStart = Base + UNIT_SIZE; // we need such code to support NULL; 1.139 + } 1.140 + SubAllocatorSize = size; 1.141 + return true; 1.142 + } 1.143 + 1.144 + void InitSubAllocator() 1.145 + { 1.146 + int i, k; 1.147 + memset(FreeList, 0, sizeof(FreeList)); 1.148 + HiUnit = (pText = HeapStart) + SubAllocatorSize; 1.149 + UINT Diff = UNIT_SIZE * (SubAllocatorSize / 8 / UNIT_SIZE * 7); 1.150 + LoUnit = UnitsStart = HiUnit - Diff; 1.151 + for (i = 0, k=1; i < N1 ; i++, k += 1) Indx2Units[i] = (Byte)k; 1.152 + for (k++; i < N1 + N2 ;i++, k += 2) Indx2Units[i] = (Byte)k; 1.153 + for (k++; i < N1 + N2 + N3 ;i++,k += 3) Indx2Units[i] = (Byte)k; 1.154 + for (k++; i < N1 + N2 + N3 + N4; i++, k += 4) Indx2Units[i] = (Byte)k; 1.155 + GlueCount = 0; 1.156 + for (k = i = 0; k < 128; k++) 1.157 + { 1.158 + i += (Indx2Units[i] < k+1); 1.159 + Units2Indx[k] = (Byte)i; 1.160 + } 1.161 + } 1.162 + 1.163 + void GlueFreeBlocks() 1.164 + { 1.165 + UInt32 s0 = (UInt32)(HeapStart + SubAllocatorSize - Base); 1.166 + 1.167 + // We need add exta MEM_BLK with Stamp=0 1.168 + GetBlk(s0)->Stamp = 0; 1.169 + s0 += UNIT_SIZE; 1.170 + MEM_BLK *ps0 = GetBlk(s0); 1.171 + 1.172 + UInt32 p; 1.173 + int i; 1.174 + if (LoUnit != HiUnit) 1.175 + *LoUnit=0; 1.176 + ps0->Next = ps0->Prev = s0; 1.177 + 1.178 + for (i = 0; i < N_INDEXES; i++) 1.179 + while (FreeList[i] != 0) 1.180 + { 1.181 + MEM_BLK *pp = (MEM_BLK *)RemoveNode(i); 1.182 + pp->InsertAt(Base, s0); 1.183 + pp->Stamp = 0xFFFF; 1.184 + pp->NU = Indx2Units[i]; 1.185 + } 1.186 + for (p = ps0->Next; p != s0; p = GetBlk(p)->Next) 1.187 + { 1.188 + for (;;) 1.189 + { 1.190 + MEM_BLK *pp = GetBlk(p); 1.191 + MEM_BLK *pp1 = GetBlk(p + pp->NU * UNIT_SIZE); 1.192 + if (pp1->Stamp != 0xFFFF || int(pp->NU) + pp1->NU >= 0x10000) 1.193 + break; 1.194 + pp1->Remove(Base); 1.195 + pp->NU = (UInt16)(pp->NU + pp1->NU); 1.196 + } 1.197 + } 1.198 + while ((p = ps0->Next) != s0) 1.199 + { 1.200 + MEM_BLK *pp = GetBlk(p); 1.201 + pp->Remove(Base); 1.202 + int sz; 1.203 + for (sz = pp->NU; sz > 128; sz -= 128, p += 128 * UNIT_SIZE) 1.204 + InsertNode(Base + p, N_INDEXES - 1); 1.205 + if (Indx2Units[i = Units2Indx[sz-1]] != sz) 1.206 + { 1.207 + int k = sz - Indx2Units[--i]; 1.208 + InsertNode(Base + p + (sz - k) * UNIT_SIZE, k - 1); 1.209 + } 1.210 + InsertNode(Base + p, i); 1.211 + } 1.212 + } 1.213 + void* AllocUnitsRare(int indx) 1.214 + { 1.215 + if ( !GlueCount ) 1.216 + { 1.217 + GlueCount = 255; 1.218 + GlueFreeBlocks(); 1.219 + if (FreeList[indx] != 0) 1.220 + return RemoveNode(indx); 1.221 + } 1.222 + int i = indx; 1.223 + do 1.224 + { 1.225 + if (++i == N_INDEXES) 1.226 + { 1.227 + GlueCount--; 1.228 + i = U2B(Indx2Units[indx]); 1.229 + return (UnitsStart - pText > i) ? (UnitsStart -= i) : (NULL); 1.230 + } 1.231 + } while (FreeList[i] == 0); 1.232 + void* RetVal = RemoveNode(i); 1.233 + SplitBlock(RetVal, i, indx); 1.234 + return RetVal; 1.235 + } 1.236 + 1.237 + void* AllocUnits(int NU) 1.238 + { 1.239 + int indx = Units2Indx[NU - 1]; 1.240 + if (FreeList[indx] != 0) 1.241 + return RemoveNode(indx); 1.242 + void* RetVal = LoUnit; 1.243 + LoUnit += U2B(Indx2Units[indx]); 1.244 + if (LoUnit <= HiUnit) 1.245 + return RetVal; 1.246 + LoUnit -= U2B(Indx2Units[indx]); 1.247 + return AllocUnitsRare(indx); 1.248 + } 1.249 + 1.250 + void* AllocContext() 1.251 + { 1.252 + if (HiUnit != LoUnit) 1.253 + return (HiUnit -= UNIT_SIZE); 1.254 + if (FreeList[0] != 0) 1.255 + return RemoveNode(0); 1.256 + return AllocUnitsRare(0); 1.257 + } 1.258 + 1.259 + void* ExpandUnits(void* oldPtr, int oldNU) 1.260 + { 1.261 + int i0=Units2Indx[oldNU - 1], i1=Units2Indx[oldNU - 1 + 1]; 1.262 + if (i0 == i1) 1.263 + return oldPtr; 1.264 + void* ptr = AllocUnits(oldNU + 1); 1.265 + if (ptr) 1.266 + { 1.267 + memcpy(ptr, oldPtr, U2B(oldNU)); 1.268 + InsertNode(oldPtr, i0); 1.269 + } 1.270 + return ptr; 1.271 + } 1.272 + 1.273 + void* ShrinkUnits(void* oldPtr, int oldNU, int newNU) 1.274 + { 1.275 + int i0 = Units2Indx[oldNU - 1], i1 = Units2Indx[newNU - 1]; 1.276 + if (i0 == i1) 1.277 + return oldPtr; 1.278 + if (FreeList[i1] != 0) 1.279 + { 1.280 + void* ptr = RemoveNode(i1); 1.281 + memcpy(ptr, oldPtr, U2B(newNU)); 1.282 + InsertNode(oldPtr,i0); 1.283 + return ptr; 1.284 + } 1.285 + else 1.286 + { 1.287 + SplitBlock(oldPtr, i0, i1); 1.288 + return oldPtr; 1.289 + } 1.290 + } 1.291 + 1.292 + void FreeUnits(void* ptr, int oldNU) 1.293 + { 1.294 + InsertNode(ptr, Units2Indx[oldNU - 1]); 1.295 + } 1.296 +}; 1.297 + 1.298 +#endif