diff options
author | theuni <theuni-nospam-@xbmc.org> | 2011-01-24 16:05:21 -0500 |
---|---|---|
committer | theuni <theuni-nospam-@xbmc.org> | 2011-01-24 16:05:21 -0500 |
commit | c51b1189e3d5353e842991f5859ddcea0f73e426 (patch) | |
tree | ef2cb8a6184699aa614f3655dca4ce661cdc108e /lib/UnrarXLib/suballoc.cpp | |
parent | be61ebdc9e897fe40c6f371111724de79ddee8d5 (diff) |
Merged cptspiff's code-reshuffle branch.
Squashed commit due to build breakage during code-reshuffle history.
Conflicts:
xbmc/Util.cpp
xbmc/cdrip/CDDARipper.cpp
xbmc/filesystem/Directory.cpp
xbmc/filesystem/File.cpp
Diffstat (limited to 'lib/UnrarXLib/suballoc.cpp')
-rw-r--r-- | lib/UnrarXLib/suballoc.cpp | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/lib/UnrarXLib/suballoc.cpp b/lib/UnrarXLib/suballoc.cpp new file mode 100644 index 0000000000..a23bc98eae --- /dev/null +++ b/lib/UnrarXLib/suballoc.cpp @@ -0,0 +1,260 @@ +/**************************************************************************** + * This file is part of PPMd project * + * Written and distributed to public domain by Dmitry Shkarin 1997, * + * 1999-2000 * + * Contents: memory allocation routines * + ****************************************************************************/ + +SubAllocator::SubAllocator() +{ + Clean(); +} + + +void SubAllocator::Clean() +{ + SubAllocatorSize=0; +} + + +inline void SubAllocator::InsertNode(void* p,int indx) +{ + ((RAR_NODE*) p)->next=FreeList[indx].next; + FreeList[indx].next=(RAR_NODE*) p; +} + + +inline void* SubAllocator::RemoveNode(int indx) +{ + RAR_NODE* RetVal=FreeList[indx].next; + FreeList[indx].next=RetVal->next; + return RetVal; +} + + +inline uint SubAllocator::U2B(int NU) +{ + return /*8*NU+4*NU*/UNIT_SIZE*NU; +} + + +inline void SubAllocator::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 SubAllocator::StopSubAllocator() +{ + if ( SubAllocatorSize ) + { + SubAllocatorSize=0; + rarfree(HeapStart); + } +} + + +bool SubAllocator::StartSubAllocator(int SASize) +{ + uint t=(uint)(SASize) << 20; + if ((uint)SubAllocatorSize == t) + return TRUE; + StopSubAllocator(); + uint AllocSize=t/FIXED_UNIT_SIZE*UNIT_SIZE+UNIT_SIZE; +#ifdef XBOX + if ((HeapStart=(byte *)rarmalloc(AllocSize)) == NULL) + { + ErrHandler.MemoryError(); + return FALSE; + } +#else + // this is uggly, we keep halfing the size till + // we manage to alloc, it's likely that we + // fail to alloc + uint AllocSize2 = AllocSize; + while(AllocSize2 && (HeapStart=(byte *)rarmalloc(AllocSize2)) == NULL) + AllocSize2<<=1; + + if(HeapStart == NULL) + { + ErrHandler.MemoryError(); + return FALSE; + } + + if(AllocSize != AllocSize2) + OutputDebugString("ERROR - had to allocate smaller data than required, extract can very well fail"); + +#endif + HeapEnd=HeapStart+AllocSize-UNIT_SIZE; + SubAllocatorSize=t; + return TRUE; +} + + +void SubAllocator::InitSubAllocator() +{ + int i, k; + memset(FreeList,0,sizeof(FreeList)); + pText=HeapStart; + uint Size2=FIXED_UNIT_SIZE*(SubAllocatorSize/8/FIXED_UNIT_SIZE*7); + uint RealSize2=Size2/FIXED_UNIT_SIZE*UNIT_SIZE; + uint Size1=SubAllocatorSize-Size2; + uint 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; + 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 SubAllocator::GlueFreeBlocks() +{ + RAR_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=(RAR_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* SubAllocator::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]); + int j=12*Indx2Units[indx]; + if (FakeUnitsStart-pText > j) + { + FakeUnitsStart-=j; + UnitsStart -= i; + return(UnitsStart); + } + return(NULL); + } + } while ( !FreeList[i].next ); + void* RetVal=RemoveNode(i); + SplitBlock(RetVal,i,indx); + return RetVal; +} + + +inline void* SubAllocator::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* SubAllocator::AllocContext() +{ + if (HiUnit != LoUnit) + return (HiUnit -= UNIT_SIZE); + if ( FreeList->next ) + return RemoveNode(0); + return AllocUnitsRare(0); +} + + +void* SubAllocator::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; +} + + +void* SubAllocator::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 SubAllocator::FreeUnits(void* ptr,int OldNU) +{ + InsertNode(ptr,Units2Indx[OldNU-1]); +} |