2013-04-07 10:58:58 +01:00
using System ;
using System.Text ;
2013-04-28 12:32:55 +01:00
2013-04-07 10:58:58 +01:00
namespace SharpCompress.Compressor.PPMd.H
{
internal class SubAllocator
{
2013-04-28 12:32:55 +01:00
public virtual int FakeUnitsStart
2013-04-07 10:58:58 +01:00
{
2013-04-28 12:32:55 +01:00
get { return fakeUnitsStart ; }
2013-04-07 10:58:58 +01:00
2013-04-28 12:32:55 +01:00
set { this . fakeUnitsStart = value ; }
2013-04-07 10:58:58 +01:00
}
2013-04-28 12:32:55 +01:00
public virtual int HeapEnd
2013-04-07 10:58:58 +01:00
{
2013-04-28 12:32:55 +01:00
get { return heapEnd ; }
}
2013-04-07 10:58:58 +01:00
2013-04-28 12:32:55 +01:00
public virtual int PText
{
get { return pText ; }
2013-04-07 10:58:58 +01:00
2013-04-28 12:32:55 +01:00
set { pText = value ; }
2013-04-07 10:58:58 +01:00
}
2013-04-28 12:32:55 +01:00
public virtual int UnitsStart
{
get { return unitsStart ; }
2013-04-07 10:58:58 +01:00
2013-04-28 12:32:55 +01:00
set { this . unitsStart = value ; }
2013-04-07 10:58:58 +01:00
}
2013-04-28 12:32:55 +01:00
public virtual byte [ ] Heap
{
get { return heap ; }
2013-04-07 10:58:58 +01:00
}
2013-04-28 12:32:55 +01:00
2013-04-07 10:58:58 +01:00
//UPGRADE_NOTE: Final was removed from the declaration of 'N4 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
public const int N1 = 4 ;
public const int N2 = 4 ;
public const int N3 = 4 ;
2013-04-28 12:32:55 +01:00
public static readonly int N4 = ( 128 + 3 - 1 * N1 - 2 * N2 - 3 * N3 ) / 4 ;
2013-04-07 10:58:58 +01:00
//UPGRADE_NOTE: Final was removed from the declaration of 'N_INDEXES '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
public static readonly int N_INDEXES = N1 + N2 + N3 + N4 ;
//UPGRADE_NOTE: Final was removed from the declaration of 'UNIT_SIZE '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
//UPGRADE_NOTE: The initialization of 'UNIT_SIZE' was moved to static method 'SharpCompress.Unpack.PPM.SubAllocator'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
public static readonly int UNIT_SIZE ;
public const int FIXED_UNIT_SIZE = 12 ;
private int subAllocatorSize ;
// byte Indx2Units[N_INDEXES], Units2Indx[128], GlueCount;
private int [ ] indx2Units = new int [ N_INDEXES ] ;
private int [ ] units2Indx = new int [ 128 ] ;
private int glueCount ;
// byte *HeapStart,*LoUnit, *HiUnit;
private int heapStart , loUnit , hiUnit ;
//UPGRADE_NOTE: Final was removed from the declaration of 'freeList '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private RarNode [ ] freeList = new RarNode [ N_INDEXES ] ;
// byte *pText, *UnitsStart,*HeapEnd,*FakeUnitsStart;
private int pText , unitsStart , heapEnd , fakeUnitsStart ;
private byte [ ] heap ;
private int freeListPos ;
private int tempMemBlockPos ;
// Temp fields
private RarNode tempRarNode = null ;
private RarMemBlock tempRarMemBlock1 = null ;
private RarMemBlock tempRarMemBlock2 = null ;
private RarMemBlock tempRarMemBlock3 = null ;
public SubAllocator ( )
{
clean ( ) ;
}
public virtual void clean ( )
{
subAllocatorSize = 0 ;
}
private void insertNode ( int p , int indx )
{
RarNode temp = tempRarNode ;
temp . Address = p ;
temp . SetNext ( freeList [ indx ] . GetNext ( ) ) ;
freeList [ indx ] . SetNext ( temp ) ;
}
public virtual void incPText ( )
{
pText + + ;
}
private int removeNode ( int indx )
{
int retVal = freeList [ indx ] . GetNext ( ) ;
RarNode temp = tempRarNode ;
temp . Address = retVal ;
freeList [ indx ] . SetNext ( temp . GetNext ( ) ) ;
return retVal ;
}
private int U2B ( int NU )
{
2013-04-28 12:32:55 +01:00
return UNIT_SIZE * NU ;
2013-04-07 10:58:58 +01:00
}
/* memblockptr */
2013-04-28 12:32:55 +01:00
2013-04-07 10:58:58 +01:00
private int MBPtr ( int BasePtr , int Items )
{
return ( BasePtr + U2B ( Items ) ) ;
}
private void splitBlock ( int pv , 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 virtual void stopSubAllocator ( )
{
if ( subAllocatorSize ! = 0 )
{
subAllocatorSize = 0 ;
//ArrayFactory.BYTES_FACTORY.recycle(heap);
heap = null ;
heapStart = 1 ;
// rarfree(HeapStart);
// Free temp fields
tempRarNode = null ;
tempRarMemBlock1 = null ;
tempRarMemBlock2 = null ;
tempRarMemBlock3 = null ;
}
}
public virtual int GetAllocatedMemory ( )
{
return subAllocatorSize ;
}
public virtual bool startSubAllocator ( int SASize )
{
int t = SASize ;
if ( subAllocatorSize = = t )
{
return true ;
}
stopSubAllocator ( ) ;
2013-04-28 12:32:55 +01:00
int allocSize = t / FIXED_UNIT_SIZE * UNIT_SIZE + UNIT_SIZE ;
2013-04-07 10:58:58 +01:00
// adding space for freelist (needed for poiters)
// 1+ for null pointer
2013-04-28 12:32:55 +01:00
int realAllocSize = 1 + allocSize + 4 * N_INDEXES ;
2013-04-07 10:58:58 +01:00
// adding space for an additional memblock
tempMemBlockPos = realAllocSize ;
realAllocSize + = RarMemBlock . size ;
heap = new byte [ realAllocSize ] ;
heapStart = 1 ;
heapEnd = heapStart + allocSize - UNIT_SIZE ;
subAllocatorSize = t ;
// Bug fixed
freeListPos = heapStart + allocSize ;
//UPGRADE_ISSUE: The following fragment of code could not be parsed and was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1156'"
//assert(realAllocSize - tempMemBlockPos == RarMemBlock.size): realAllocSize
//+ + tempMemBlockPos + + RarMemBlock.size;
// Init freeList
for ( int i = 0 , pos = freeListPos ; i < freeList . Length ; i + + , pos + = RarNode . size )
{
freeList [ i ] = new RarNode ( heap ) ;
freeList [ i ] . Address = pos ;
}
// Init temp fields
tempRarNode = new RarNode ( heap ) ;
tempRarMemBlock1 = new RarMemBlock ( heap ) ;
tempRarMemBlock2 = new RarMemBlock ( heap ) ;
tempRarMemBlock3 = new RarMemBlock ( heap ) ;
return true ;
}
private void glueFreeBlocks ( )
{
RarMemBlock s0 = tempRarMemBlock1 ;
s0 . Address = tempMemBlockPos ;
RarMemBlock p = tempRarMemBlock2 ;
RarMemBlock p1 = tempRarMemBlock3 ;
int i , k , sz ;
if ( loUnit ! = hiUnit )
{
heap [ loUnit ] = 0 ;
}
for ( i = 0 , s0 . SetPrev ( s0 ) , s0 . SetNext ( s0 ) ; i < N_INDEXES ; i + + )
{
while ( freeList [ i ] . GetNext ( ) ! = 0 )
{
p . Address = removeNode ( i ) ; // =(RAR_MEM_BLK*)RemoveNode(i);
p . InsertAt ( s0 ) ; // p->insertAt(&s0);
p . Stamp = 0xFFFF ; // p->Stamp=0xFFFF;
p . SetNU ( indx2Units [ i ] ) ; // p->NU=Indx2Units[i];
}
}
for ( p . Address = s0 . GetNext ( ) ; p . Address ! = s0 . Address ; p . Address = p . GetNext ( ) )
{
// while ((p1=MBPtr(p,p->NU))->Stamp == 0xFFFF && int(p->NU)+p1->NU
// < 0x10000)
// Bug fixed
p1 . Address = MBPtr ( p . Address , p . GetNU ( ) ) ;
while ( p1 . Stamp = = 0xFFFF & & p . GetNU ( ) + p1 . GetNU ( ) < 0x10000 )
{
p1 . Remove ( ) ;
p . SetNU ( p . GetNU ( ) + p1 . GetNU ( ) ) ; // ->NU += p1->NU;
p1 . Address = MBPtr ( p . Address , p . GetNU ( ) ) ;
}
}
// while ((p=s0.next) != &s0)
// Bug fixed
p . Address = s0 . GetNext ( ) ;
while ( p . Address ! = s0 . Address )
{
for ( p . Remove ( ) , sz = p . GetNU ( ) ; sz > 128 ; sz - = 128 , p . Address = MBPtr ( p . Address , 128 ) )
{
insertNode ( p . Address , N_INDEXES - 1 ) ;
}
if ( indx2Units [ i = units2Indx [ sz - 1 ] ] ! = sz )
{
k = sz - indx2Units [ - - i ] ;
insertNode ( MBPtr ( p . Address , sz - k ) , k - 1 ) ;
}
insertNode ( p . Address , i ) ;
p . Address = s0 . GetNext ( ) ;
}
}
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 ] ) ;
2013-04-28 12:32:55 +01:00
int j = FIXED_UNIT_SIZE * indx2Units [ indx ] ;
2013-04-07 10:58:58 +01:00
if ( fakeUnitsStart - pText > j )
{
fakeUnitsStart - = j ;
unitsStart - = i ;
return unitsStart ;
}
return ( 0 ) ;
}
2013-04-28 12:32:55 +01:00
} while ( freeList [ i ] . GetNext ( ) = = 0 ) ;
2013-04-07 10:58:58 +01:00
int retVal = removeNode ( i ) ;
splitBlock ( retVal , i , indx ) ;
return retVal ;
}
public virtual 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 virtual int allocContext ( )
{
if ( hiUnit ! = loUnit )
return ( hiUnit - = UNIT_SIZE ) ;
if ( freeList [ 0 ] . GetNext ( ) ! = 0 )
{
return removeNode ( 0 ) ;
}
return allocUnitsRare ( 0 ) ;
}
public virtual 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));
Array . Copy ( heap , oldPtr , heap , ptr , U2B ( OldNU ) ) ;
insertNode ( oldPtr , i0 ) ;
}
return ptr ;
}
public virtual int shrinkUnits ( int oldPtr , int oldNU , int newNU )
{
// System.out.println("SubAllocator.shrinkUnits(" + OldPtr + ", " +
// OldNU + ", " + NewNU + ")");
int i0 = units2Indx [ oldNU - 1 ] ;
int 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];
// }
Array . Copy ( heap , oldPtr , heap , ptr , U2B ( newNU ) ) ;
insertNode ( oldPtr , i0 ) ;
return ptr ;
}
else
{
splitBlock ( oldPtr , i0 , i1 ) ;
return oldPtr ;
}
}
public virtual void freeUnits ( int ptr , int OldNU )
{
insertNode ( ptr , units2Indx [ OldNU - 1 ] ) ;
}
public virtual void decPText ( int dPText )
{
PText = PText - dPText ;
}
public virtual void initSubAllocator ( )
{
int i , k ;
2013-04-28 12:32:55 +01:00
Utility . Fill ( heap , freeListPos , freeListPos + sizeOfFreeList ( ) , ( byte ) 0 ) ;
2013-04-07 10:58:58 +01:00
pText = heapStart ;
2013-04-28 12:32:55 +01:00
int size2 = FIXED_UNIT_SIZE * ( subAllocatorSize / 8 / FIXED_UNIT_SIZE * 7 ) ;
int realSize2 = size2 / FIXED_UNIT_SIZE * UNIT_SIZE ;
2013-04-07 10:58:58 +01:00
int size1 = subAllocatorSize - size2 ;
2013-04-28 12:32:55 +01:00
int realSize1 = size1 / FIXED_UNIT_SIZE * UNIT_SIZE + size1 % FIXED_UNIT_SIZE ;
2013-04-07 10:58:58 +01:00
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 & 0xff ;
}
for ( k + + ; i < N1 + N2 ; i + + , k + = 2 )
{
indx2Units [ i ] = k & 0xff ;
}
for ( k + + ; i < N1 + N2 + N3 ; i + + , k + = 3 )
{
indx2Units [ i ] = k & 0xff ;
}
for ( k + + ; i < ( N1 + N2 + N3 + N4 ) ; i + + , k + = 4 )
{
indx2Units [ i ] = k & 0xff ;
}
for ( glueCount = 0 , k = 0 , i = 0 ; k < 128 ; k + + )
{
i + = ( ( indx2Units [ i ] < ( k + 1 ) ) ? 1 : 0 ) ;
units2Indx [ k ] = i & 0xff ;
}
}
private int sizeOfFreeList ( )
{
2013-04-28 12:32:55 +01:00
return freeList . Length * RarNode . size ;
2013-04-07 10:58:58 +01:00
}
// Debug
// public void dumpHeap() {
// File file = new File("P:\\test\\heapdumpj");
// OutputStream out = null;
// try {
// out = new FileOutputStream(file);
// out.write(heap, heapStart, heapEnd - heapStart);
// out.flush();
// System.out.println("Heap dumped to " + file.getAbsolutePath());
// }
// catch (IOException e) {
// e.printStackTrace();
// }
// finally {
// FileUtil.close(out);
// }
// }
// Debug
public override System . String ToString ( )
{
StringBuilder buffer = new StringBuilder ( ) ;
buffer . Append ( "SubAllocator[" ) ;
buffer . Append ( "\n subAllocatorSize=" ) ;
buffer . Append ( subAllocatorSize ) ;
buffer . Append ( "\n glueCount=" ) ;
buffer . Append ( glueCount ) ;
buffer . Append ( "\n heapStart=" ) ;
buffer . Append ( heapStart ) ;
buffer . Append ( "\n loUnit=" ) ;
buffer . Append ( loUnit ) ;
buffer . Append ( "\n hiUnit=" ) ;
buffer . Append ( hiUnit ) ;
buffer . Append ( "\n pText=" ) ;
buffer . Append ( pText ) ;
buffer . Append ( "\n unitsStart=" ) ;
buffer . Append ( unitsStart ) ;
buffer . Append ( "\n]" ) ;
return buffer . ToString ( ) ;
}
2013-04-28 12:32:55 +01:00
2013-04-07 10:58:58 +01:00
static SubAllocator ( )
{
UNIT_SIZE = System . Math . Max ( PPMContext . size , RarMemBlock . size ) ;
}
}
}