os/kernelhwsrv/userlibandfileserver/fileserver/sfsrv/cl_cdir.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/userlibandfileserver/fileserver/sfsrv/cl_cdir.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,569 @@
     1.4 +// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of the License "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// f32\sfsrv\cl_cdir.cpp
    1.18 +// 
    1.19 +//
    1.20 +
    1.21 +#include "cl_std.h"
    1.22 +#include <collate.h>
    1.23 +
    1.24 +const TUint KCDirArrayGranularity=0x200;
    1.25 +const TInt KPartKeyLength = 8;
    1.26 +const TInt KCollationLevel0 = 0;
    1.27 +const TInt KCollationLevelMax = 3;
    1.28 +
    1.29 +#define KCollationKeyAllocFail ((HBufC8*)-1)
    1.30 +
    1.31 +///////////////////////////////////////////////////////////////////////////////
    1.32 +/**
    1.33 + * @class TEntry2
    1.34 + * @description TEntry's variant with pointer to collation key buffers
    1.35 + * @internalComponent
    1.36 + */
    1.37 +NONSHARABLE_CLASS(TEntry2)
    1.38 +    {
    1.39 +public:
    1.40 +	TEntry2(const TEntry& aEntry);
    1.41 +	~TEntry2();
    1.42 +public:
    1.43 +    TBool IsDir() const {return iEntry.IsDir();}
    1.44 +#ifndef	SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
    1.45 +    TInt64 Size() {return MAKE_TINT64(0,iEntry.iSize);}
    1.46 +#else
    1.47 +    TInt64 Size() {return iEntry.FileSize();}
    1.48 +#endif
    1.49 +    TTime Modified() const {return iEntry.iModified;}
    1.50 +    const TUidType& Type() const {return iEntry.iType;}
    1.51 +    const TDesC& Name() const {return iEntry.iName;}
    1.52 +private:
    1.53 +    TEntry2(const TEntry2& aEntry);
    1.54 +    TEntry2& operator=(const TEntry2& aEntry);
    1.55 +public:
    1.56 +	HBufC8* iPartKey;
    1.57 +	HBufC8* iFullKey;
    1.58 +	TEntry iEntry;
    1.59 +    };
    1.60 +
    1.61 +TEntry2::TEntry2(const TEntry& aEntry) : iPartKey(0), iFullKey(0), iEntry(aEntry)
    1.62 +	{
    1.63 +	}
    1.64 +
    1.65 +TEntry2::~TEntry2()
    1.66 +	{
    1.67 +	if (iPartKey != KCollationKeyAllocFail)
    1.68 +        delete iPartKey;
    1.69 +	if (iFullKey != KCollationKeyAllocFail)
    1.70 +	    delete iFullKey;
    1.71 +	}
    1.72 +
    1.73 +inline TInt Entry2Size(const TEntry2& aEntry)
    1.74 +    {
    1.75 +    return sizeof(HBufC8*) * 2 + EntrySize(aEntry.iEntry, ETrue);
    1.76 +    }
    1.77 +///////////////////////////////////////////////////////////////////////////////
    1.78 +
    1.79 +NONSHARABLE_CLASS(TKeyDir) : public TKeyArrayVar
    1.80 +	{
    1.81 +public:
    1.82 +	TKeyDir(TUint aKey);
    1.83 +	virtual TInt Compare(TInt aLeft,TInt aRight) const;
    1.84 +private:
    1.85 +	TInt CompareByName(TEntry2& aLeft, TEntry2& aRight) const;
    1.86 +private:
    1.87 +	TCollationMethod iCollationMethod;
    1.88 +	};
    1.89 +
    1.90 +TKeyDir::TKeyDir(TUint aKey)
    1.91 +//
    1.92 +// Constructor
    1.93 +//
    1.94 +	: TKeyArrayVar(0,(TKeyCmpText)(aKey&0xff),aKey&(EDirsFirst|EDirsLast|EDescending|EDirDescending))
    1.95 +	{
    1.96 +	//
    1.97 +	// Create our own collation method to also consider punctuation when
    1.98 +	// sorting filenames.
    1.99 +	//
   1.100 +	iCollationMethod = *Mem::GetDefaultMatchingTable();
   1.101 +	iCollationMethod.iFlags |= TCollationMethod::EIgnoreNone | TCollationMethod::EFoldCase;
   1.102 +	}
   1.103 +
   1.104 +
   1.105 +TInt TKeyDir::Compare(TInt aLeft,TInt aRight) const
   1.106 +//
   1.107 +// Compare two directories for sorting.
   1.108 +//
   1.109 +	{
   1.110 +
   1.111 +	if (aLeft==aRight)
   1.112 +		return(0);
   1.113 +	TEntry2& left = *(TEntry2*)At(aLeft);
   1.114 +	TEntry2& right = *(TEntry2*)At(aRight);
   1.115 +	TInt ret=0;
   1.116 +	if ((iKeyLength&EDirsFirst)==EDirsFirst)
   1.117 +		{
   1.118 +		if (left.IsDir())
   1.119 +			{
   1.120 +			if (!right.IsDir())
   1.121 +				ret=(-1); // left is a dir, right is not
   1.122 +			}
   1.123 +		else if (right.IsDir())
   1.124 +			ret=1; // right is a dir, left is not
   1.125 +		}
   1.126 +	else if ((iKeyLength&EDirsLast)==EDirsLast)
   1.127 +		{
   1.128 +		if (left.IsDir())
   1.129 +			{
   1.130 +			if (!right.IsDir())
   1.131 +				ret=1; // left is a dir, right is not
   1.132 +			}
   1.133 +		else if (right.IsDir())
   1.134 +			ret=(-1); // right is a dir, left is not
   1.135 +		}
   1.136 +
   1.137 +	TInt cmpType=iCmpType;
   1.138 +	TInt keyLength=iKeyLength;
   1.139 +	TBool orderDirectories=(keyLength&EDirsFirst) || (keyLength&EDirsLast);
   1.140 +	if (orderDirectories && left.IsDir() && right.IsDir())
   1.141 +		{
   1.142 +		cmpType=ESortByName;
   1.143 +		if ((keyLength&EDirDescending)!=EDirDescending)
   1.144 +			keyLength&=~EDescending;
   1.145 +		else
   1.146 +			keyLength|=EDescending;
   1.147 +		}
   1.148 +
   1.149 +	if (ret==0) // Both are the same type
   1.150 +		{
   1.151 +		ret=(-1); // left before right by default
   1.152 +		switch (cmpType)
   1.153 +			{
   1.154 +		case ESortNone:
   1.155 +			ret=1;
   1.156 +			break;
   1.157 +		case ESortByDate:
   1.158 +			if (left.Modified()>right.Modified())
   1.159 +				ret=1;
   1.160 +			else if (left.Modified()==right.Modified())
   1.161 +				ret=0;
   1.162 +			break;
   1.163 +		case ESortBySize:
   1.164 +#ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
   1.165 +		if (I64LOW(left.Size()) > I64LOW(right.Size()))
   1.166 +			ret=1;
   1.167 +		else if (I64LOW(left.Size())==I64LOW(right.Size()))
   1.168 +			ret=0;
   1.169 +#else
   1.170 +			if (left.Size() > right.Size())
   1.171 +				ret=1;
   1.172 +			else if (left.Size()==right.Size())
   1.173 +				ret=0;
   1.174 +#endif
   1.175 +			break;
   1.176 +		case ESortByExt:
   1.177 +			{
   1.178 +			TInt i1 = KErrNotFound, i2 = KErrNotFound;
   1.179 +			if (left.Name() != _L(".") && left.Name() != _L(".."))
   1.180 +				i1 = left.Name().LocateReverse('.');
   1.181 +			if (right.Name() != _L(".") && right.Name() != _L(".."))
   1.182 +				i2 = right.Name().LocateReverse('.');
   1.183 +			if (i1==KErrNotFound && i2!=KErrNotFound)
   1.184 +				ret=(-1);
   1.185 +			else if (i2==KErrNotFound && i1!=KErrNotFound)
   1.186 +				ret=1;
   1.187 +			else if ((i1==KErrNotFound && i2==KErrNotFound) || (ret=left.Name().Mid(i1).CompareC(right.Name().Mid(i2)))==0)
   1.188 +				goto byName;
   1.189 +			}
   1.190 +			break;
   1.191 +		case ESortByUid:
   1.192 +			if (left.Type()[1]==right.Type()[1])
   1.193 +				{
   1.194 +				if (left.Type()[2]==right.Type()[2])
   1.195 +					ret = CompareByName(left, right);
   1.196 +				else if (left.Type()[2].iUid>right.Type()[2].iUid)
   1.197 +					ret=1;
   1.198 +				}
   1.199 +			else if (left.Type()[1].iUid==0)
   1.200 +				ret=1;
   1.201 +			else if (right.Type()[1].iUid==0)
   1.202 +				ret=-1;
   1.203 +			else if (left.Type()[1].iUid>right.Type()[1].iUid)
   1.204 +				ret=1;
   1.205 +			break;
   1.206 +		case ESortByName:
   1.207 +byName:
   1.208 +			// Force the maximum collation level here (i.e. 3) for sorting strings 
   1.209 +			ret = CompareByName(left, right);
   1.210 +			break;
   1.211 +		default: // Default is bad news
   1.212 +			Panic(ECDirBadSortType);
   1.213 +			}
   1.214 +		}
   1.215 +	if ((keyLength&EDescending)==EDescending)
   1.216 +		ret=(-ret); // Descending sort order
   1.217 +	return(ret);
   1.218 +	}
   1.219 +
   1.220 +TInt TKeyDir::CompareByName(TEntry2& aLeft, TEntry2& aRight) const
   1.221 +//
   1.222 +// Compare using collation key of entire name
   1.223 +//
   1.224 +	{
   1.225 +	TInt ret = -1;
   1.226 +	TInt r = KErrNone;
   1.227 +
   1.228 +    // Allocate partial key first and handle potential error case
   1.229 +    // by calling old CompareC
   1.230 +	// Note: only compare on the first collation level (KCollationLevel0) for partial keys, 
   1.231 +	//       to avoid potential inconsistency between full key and partial key comparison.
   1.232 +	if (!aLeft.iPartKey)
   1.233 +		{
   1.234 +		TRAP(r, aLeft.iPartKey = aLeft.Name().Left(KPartKeyLength).GetCollationKeysL(KCollationLevel0, &iCollationMethod));
   1.235 +		if (r != KErrNone)
   1.236 +		    aLeft.iPartKey = KCollationKeyAllocFail;
   1.237 +		}
   1.238 +	if (!aRight.iPartKey)
   1.239 +		{
   1.240 +		TRAP(r, aRight.iPartKey = aRight.Name().Left(KPartKeyLength).GetCollationKeysL(KCollationLevel0, &iCollationMethod));
   1.241 +		if (r != KErrNone)
   1.242 +		    aRight.iPartKey = KCollationKeyAllocFail;
   1.243 +		}
   1.244 +	if (aLeft.iPartKey == KCollationKeyAllocFail || aRight.iPartKey == KCollationKeyAllocFail)
   1.245 +		return aLeft.Name().CompareC(aRight.Name());
   1.246 +
   1.247 +	// Compare by partial key first
   1.248 +    ret = aLeft.iPartKey->Compare(*aRight.iPartKey);
   1.249 +    if (ret != 0)
   1.250 +        return ret;
   1.251 +
   1.252 +    // Compare by full key if partial keys are identical
   1.253 +	if (!aLeft.iFullKey)
   1.254 +		{
   1.255 +		TRAP(r, aLeft.iFullKey = aLeft.Name().GetCollationKeysL(KCollationLevelMax, &iCollationMethod));
   1.256 +		if (r != KErrNone)
   1.257 +		    aLeft.iFullKey = KCollationKeyAllocFail;
   1.258 +		}
   1.259 +	if (!aRight.iFullKey)
   1.260 +		{
   1.261 +		TRAP(r, aRight.iFullKey = aRight.Name().GetCollationKeysL(KCollationLevelMax, &iCollationMethod));
   1.262 +		if (r != KErrNone)
   1.263 +		    aRight.iFullKey = KCollationKeyAllocFail;
   1.264 +		}
   1.265 +	if (aLeft.iFullKey == KCollationKeyAllocFail || aRight.iFullKey == KCollationKeyAllocFail)
   1.266 +	    // Using old CompareC if partial key allocation failed
   1.267 +		return aLeft.Name().CompareC(aRight.Name());
   1.268 +
   1.269 +    // Compare using collation key of full names
   1.270 +    ret = aLeft.iFullKey->Compare(*aRight.iFullKey);
   1.271 +
   1.272 +	return ret;
   1.273 +	}
   1.274 +
   1.275 +
   1.276 +
   1.277 +EXPORT_C CDir::CDir()
   1.278 +/**
   1.279 +Default constructor.
   1.280 +*/
   1.281 +	{
   1.282 +	}
   1.283 +
   1.284 +
   1.285 +
   1.286 +
   1.287 +EXPORT_C CDir::~CDir()
   1.288 +/**
   1.289 +Destructor.
   1.290 +
   1.291 +Frees all resources owned by the object, prior to its destruction.
   1.292 +*/
   1.293 +	{
   1.294 +
   1.295 +	delete iArray;
   1.296 +	}
   1.297 +
   1.298 +
   1.299 +
   1.300 +
   1.301 +EXPORT_C CDir* CDir::NewL()
   1.302 +/**
   1.303 +Allocates and constructs a directory object.
   1.304 +
   1.305 +This function is protected, which prevents objects of this class from being
   1.306 +directly constructed.
   1.307 +
   1.308 +@return A pointer to the newly created object.
   1.309 +*/
   1.310 +	{
   1.311 +
   1.312 +	CDir* pD=new(ELeave) CDir;
   1.313 +	pD->iArray=new CArrayPakFlat<TEntry>(KCDirArrayGranularity);
   1.314 +	if (pD->iArray==NULL)
   1.315 +		{
   1.316 +		delete pD;
   1.317 +		User::LeaveNoMemory();
   1.318 +		}
   1.319 +	return(pD);
   1.320 +	}
   1.321 +
   1.322 +
   1.323 +
   1.324 +
   1.325 +EXPORT_C TInt CDir::Count() const
   1.326 +/**
   1.327 +Gets the number of entries in the array of directory
   1.328 +entries.
   1.329 +
   1.330 +@return The number of entries in the array.
   1.331 +*/
   1.332 +	{
   1.333 +
   1.334 +	return(iArray->Count());
   1.335 +	}
   1.336 +
   1.337 +
   1.338 +
   1.339 +
   1.340 +EXPORT_C const TEntry& CDir::operator[](TInt anIndex) const
   1.341 +/**
   1.342 +Gets an entry from the array of directory
   1.343 +entries.
   1.344 +
   1.345 +@param anIndex of the desired entry within the array.
   1.346 +
   1.347 +@return A directory entry.
   1.348 +*/
   1.349 +	{
   1.350 +
   1.351 +	return((*iArray)[anIndex]);
   1.352 +	}
   1.353 +
   1.354 +
   1.355 +/**
   1.356 + * Utility class to manage dynamic array memory
   1.357 + * @internalComponent
   1.358 + */
   1.359 +NONSHARABLE_CLASS(CAutoArray) : public CBase
   1.360 +    {
   1.361 +public:
   1.362 +    ~CAutoArray();
   1.363 +public:
   1.364 +    CArrayVarFlat<TEntry2>* iArray;
   1.365 +    };
   1.366 +
   1.367 +// Have to do this trick because CArrayVarFlat won't destroy element one by one
   1.368 +CAutoArray::~CAutoArray()
   1.369 +    {
   1.370 +    if (iArray)
   1.371 +        for (TInt i=0; i<iArray->Count(); ++i)
   1.372 +            {
   1.373 +            TEntry2& e = (*iArray)[i];
   1.374 +           	if (e.iPartKey != KCollationKeyAllocFail)
   1.375 +                delete e.iPartKey;
   1.376 +	        if (e.iFullKey != KCollationKeyAllocFail)
   1.377 +	            delete e.iFullKey;
   1.378 +            e.iPartKey = e.iFullKey = 0;
   1.379 +            }
   1.380 +    delete iArray;
   1.381 +    }
   1.382 +
   1.383 +EXPORT_C TInt CDir::Sort(TUint aKey)
   1.384 +/**
   1.385 +Sorts the array of directory entries.
   1.386 +
   1.387 +@param aKey A set of flags describing how the directory entries are to be sorted.
   1.388 +       The set of flags is defined by TEntryKey.
   1.389 +
   1.390 +@return KErrNone, if successful, otherwise one of the other	 system-wide error
   1.391 +        codes.
   1.392 +
   1.393 +@see TEntryKey
   1.394 +*/
   1.395 +	{
   1.396 +	CAutoArray autoArray;
   1.397 +	#define array autoArray.iArray
   1.398 +
   1.399 +	// Create TEntry2 array from iArray.
   1.400 +	array = new CArrayVarFlat<TEntry2>(KCDirArrayGranularity);
   1.401 +	if (!array)
   1.402 +		return KErrNoMemory;
   1.403 +	
   1.404 +	TInt arrayCount = iArray->Count();
   1.405 +	if (arrayCount == 0)
   1.406 +		return KErrNone;
   1.407 +	
   1.408 +	TEntry2* entry2 = new TEntry2((*iArray)[0]);
   1.409 +	
   1.410 +	if (!entry2)
   1.411 +		return KErrNoMemory;
   1.412 +
   1.413 +	TInt i, r;
   1.414 +	for (i=0; i<arrayCount; ++i)
   1.415 +		{
   1.416 +		entry2->iEntry = (*iArray)[i];
   1.417 +		// Pack here
   1.418 +		TUint32* pSizeHighSrc = PtrAdd((TUint32*)&(entry2->iEntry), sizeof(TEntry) - 2 * sizeof(TInt));
   1.419 +		TUint32* pSizeHighDst = PtrAdd((TUint32*)&(entry2->iEntry), EntrySize(entry2->iEntry, EFalse));
   1.420 +		
   1.421 +		*pSizeHighDst++ = *pSizeHighSrc++;	// Pack iSizeHigh
   1.422 +		*pSizeHighDst   = *pSizeHighSrc;	// Pack iReserved
   1.423 +		entry2->iEntry.iAtt |= KEntryAttPacked;
   1.424 +		
   1.425 +		TRAP(r, array->AppendL(*entry2, Entry2Size(*entry2)));
   1.426 +
   1.427 +		if (r != KErrNone)
   1.428 +			{
   1.429 +			delete entry2;	
   1.430 +			return r;
   1.431 +			}
   1.432 +		}
   1.433 +
   1.434 +	// Sort new array
   1.435 +	TKeyDir key(aKey);
   1.436 +	r = array->Sort(key);
   1.437 +	if (r != KErrNone)
   1.438 +		{
   1.439 +		delete entry2;
   1.440 +        return r;
   1.441 +		}
   1.442 +
   1.443 +	// Copy sorted result back to iArray
   1.444 +	iArray->Reset();
   1.445 +	
   1.446 +	for (i=0; i<array->Count(); ++i)
   1.447 +		{
   1.448 +		entry2->iEntry = (*array)[i].iEntry;
   1.449 +		// Pack here
   1.450 +		TUint32* pSizeHighSrc = PtrAdd((TUint32*)&(entry2->iEntry), sizeof(TEntry) - 2 * sizeof(TInt));
   1.451 +		TUint32* pSizeHighDst = PtrAdd((TUint32*)&(entry2->iEntry), EntrySize(entry2->iEntry, EFalse));
   1.452 +		
   1.453 +		*pSizeHighDst++ = *pSizeHighSrc++;	// Pack iSizeHigh
   1.454 +		*pSizeHighDst   = *pSizeHighSrc;	// Pack iReserved
   1.455 +		entry2->iEntry.iAtt |= KEntryAttPacked;
   1.456 +		
   1.457 +		TRAP(r, iArray->AppendL(entry2->iEntry, EntrySize(entry2->iEntry, ETrue)));
   1.458 +		if (r != KErrNone)
   1.459 +			{
   1.460 +			delete entry2;	
   1.461 +			return r;
   1.462 +			}
   1.463 +		}
   1.464 +
   1.465 +	delete entry2;
   1.466 +	return r;
   1.467 +	}
   1.468 +	
   1.469 +
   1.470 +EXPORT_C void CDir::AddL(const TEntry& aEntry)
   1.471 +/**
   1.472 +Adds the specified entry to the directory.
   1.473 +
   1.474 +Note that the function can leave.
   1.475 +
   1.476 +@param aEntry The directory entry to be added.
   1.477 +*/
   1.478 +	{
   1.479 +	if(aEntry.iAtt & KEntryAttPacked)
   1.480 +		{
   1.481 +		iArray->AppendL(aEntry,EntrySize(aEntry, ETrue));
   1.482 +		}
   1.483 +	else
   1.484 +		{
   1.485 +		TEntry entry = aEntry;
   1.486 +		// Pack here
   1.487 +		TUint32* pSizeHighSrc = PtrAdd((TUint32*)&entry, sizeof(TEntry) - 2 * sizeof(TInt));
   1.488 +		TUint32* pSizeHighDst = PtrAdd((TUint32*)&entry, EntrySize(entry, EFalse));
   1.489 +		
   1.490 +		*pSizeHighDst++ = *pSizeHighSrc++;	// Pack iSizeHigh
   1.491 +		*pSizeHighDst   = *pSizeHighSrc;		// Pack iReserved
   1.492 +		entry.iAtt |= KEntryAttPacked;
   1.493 +		iArray->AppendL(entry,EntrySize(entry, ETrue));
   1.494 +		}
   1.495 +	}
   1.496 +
   1.497 +
   1.498 +
   1.499 +
   1.500 +EXPORT_C void CDir::ExtractL(TBool aRemove,CDir* & aDir)
   1.501 +/**
   1.502 +Copies all directory entries from this directory array, and adds them to
   1.503 +a new directory array.
   1.504 +
   1.505 +The directory entries in this array can be deleted.
   1.506 +
   1.507 +Note that the function can leave.
   1.508 +
   1.509 +@param aRemove If ETrue, the  directory entries in this array are
   1.510 +               to be deleted after extraction;
   1.511 +               if EFalse, the directory entries are not to be deleted.
   1.512 +                
   1.513 +@param aDir    On return, a pointer to a CDir object containing
   1.514 +               the extracted directory entries.
   1.515 +*/
   1.516 +	{
   1.517 +
   1.518 +	aDir=NULL;
   1.519 +	aDir=CDir::NewL();
   1.520 +	CArrayPakFlat<TEntry>& anArray=(*iArray);
   1.521 +	TInt count=anArray.Count();
   1.522 +	
   1.523 +	if (count == 0)
   1.524 +		return;
   1.525 +	
   1.526 +	TInt i=0;
   1.527 +	while (i<count)
   1.528 +		{
   1.529 +		TEntry& e=anArray[i];
   1.530 +		if (e.IsDir())
   1.531 +			aDir->AddL(e);
   1.532 +		i++;
   1.533 +		}
   1.534 +	if (aRemove)
   1.535 +		{
   1.536 +		i=0;
   1.537 +		while (i<count)
   1.538 +			{
   1.539 +			if (anArray[i].IsDir())
   1.540 +				{
   1.541 +				anArray.Delete(i);
   1.542 +				count--;
   1.543 +				continue;
   1.544 +				}
   1.545 +			i++;
   1.546 +			}
   1.547 +		anArray.Compress();
   1.548 +		}
   1.549 +	aDir->Compress();
   1.550 +	}
   1.551 +
   1.552 +
   1.553 +
   1.554 +
   1.555 +EXPORT_C void CDir::Compress()
   1.556 +/**
   1.557 +Compresses the directory.
   1.558 +
   1.559 +This has the effect of potentially reducing the ammount of storage 
   1.560 +space required on the media for that directory and the files it contains. 
   1.561 +Some files are already compressed and will not compress further.
   1.562 +
   1.563 +A potential side effect of compression is that each file is required to 
   1.564 +be uncompressed prior to use, generally increasing the time and 
   1.565 +processing cycles required to access that file.
   1.566 +
   1.567 +*/
   1.568 +	{
   1.569 +
   1.570 +	iArray->Compress();
   1.571 +	}
   1.572 +