os/kernelhwsrv/userlibandfileserver/fileserver/sfsrv/cl_cdir.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// f32\sfsrv\cl_cdir.cpp
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
#include "cl_std.h"
sl@0
    19
#include <collate.h>
sl@0
    20
sl@0
    21
const TUint KCDirArrayGranularity=0x200;
sl@0
    22
const TInt KPartKeyLength = 8;
sl@0
    23
const TInt KCollationLevel0 = 0;
sl@0
    24
const TInt KCollationLevelMax = 3;
sl@0
    25
sl@0
    26
#define KCollationKeyAllocFail ((HBufC8*)-1)
sl@0
    27
sl@0
    28
///////////////////////////////////////////////////////////////////////////////
sl@0
    29
/**
sl@0
    30
 * @class TEntry2
sl@0
    31
 * @description TEntry's variant with pointer to collation key buffers
sl@0
    32
 * @internalComponent
sl@0
    33
 */
sl@0
    34
NONSHARABLE_CLASS(TEntry2)
sl@0
    35
    {
sl@0
    36
public:
sl@0
    37
	TEntry2(const TEntry& aEntry);
sl@0
    38
	~TEntry2();
sl@0
    39
public:
sl@0
    40
    TBool IsDir() const {return iEntry.IsDir();}
sl@0
    41
#ifndef	SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
sl@0
    42
    TInt64 Size() {return MAKE_TINT64(0,iEntry.iSize);}
sl@0
    43
#else
sl@0
    44
    TInt64 Size() {return iEntry.FileSize();}
sl@0
    45
#endif
sl@0
    46
    TTime Modified() const {return iEntry.iModified;}
sl@0
    47
    const TUidType& Type() const {return iEntry.iType;}
sl@0
    48
    const TDesC& Name() const {return iEntry.iName;}
sl@0
    49
private:
sl@0
    50
    TEntry2(const TEntry2& aEntry);
sl@0
    51
    TEntry2& operator=(const TEntry2& aEntry);
sl@0
    52
public:
sl@0
    53
	HBufC8* iPartKey;
sl@0
    54
	HBufC8* iFullKey;
sl@0
    55
	TEntry iEntry;
sl@0
    56
    };
sl@0
    57
sl@0
    58
TEntry2::TEntry2(const TEntry& aEntry) : iPartKey(0), iFullKey(0), iEntry(aEntry)
sl@0
    59
	{
sl@0
    60
	}
sl@0
    61
sl@0
    62
TEntry2::~TEntry2()
sl@0
    63
	{
sl@0
    64
	if (iPartKey != KCollationKeyAllocFail)
sl@0
    65
        delete iPartKey;
sl@0
    66
	if (iFullKey != KCollationKeyAllocFail)
sl@0
    67
	    delete iFullKey;
sl@0
    68
	}
sl@0
    69
sl@0
    70
inline TInt Entry2Size(const TEntry2& aEntry)
sl@0
    71
    {
sl@0
    72
    return sizeof(HBufC8*) * 2 + EntrySize(aEntry.iEntry, ETrue);
sl@0
    73
    }
sl@0
    74
///////////////////////////////////////////////////////////////////////////////
sl@0
    75
sl@0
    76
NONSHARABLE_CLASS(TKeyDir) : public TKeyArrayVar
sl@0
    77
	{
sl@0
    78
public:
sl@0
    79
	TKeyDir(TUint aKey);
sl@0
    80
	virtual TInt Compare(TInt aLeft,TInt aRight) const;
sl@0
    81
private:
sl@0
    82
	TInt CompareByName(TEntry2& aLeft, TEntry2& aRight) const;
sl@0
    83
private:
sl@0
    84
	TCollationMethod iCollationMethod;
sl@0
    85
	};
sl@0
    86
sl@0
    87
TKeyDir::TKeyDir(TUint aKey)
sl@0
    88
//
sl@0
    89
// Constructor
sl@0
    90
//
sl@0
    91
	: TKeyArrayVar(0,(TKeyCmpText)(aKey&0xff),aKey&(EDirsFirst|EDirsLast|EDescending|EDirDescending))
sl@0
    92
	{
sl@0
    93
	//
sl@0
    94
	// Create our own collation method to also consider punctuation when
sl@0
    95
	// sorting filenames.
sl@0
    96
	//
sl@0
    97
	iCollationMethod = *Mem::GetDefaultMatchingTable();
sl@0
    98
	iCollationMethod.iFlags |= TCollationMethod::EIgnoreNone | TCollationMethod::EFoldCase;
sl@0
    99
	}
sl@0
   100
sl@0
   101
sl@0
   102
TInt TKeyDir::Compare(TInt aLeft,TInt aRight) const
sl@0
   103
//
sl@0
   104
// Compare two directories for sorting.
sl@0
   105
//
sl@0
   106
	{
sl@0
   107
sl@0
   108
	if (aLeft==aRight)
sl@0
   109
		return(0);
sl@0
   110
	TEntry2& left = *(TEntry2*)At(aLeft);
sl@0
   111
	TEntry2& right = *(TEntry2*)At(aRight);
sl@0
   112
	TInt ret=0;
sl@0
   113
	if ((iKeyLength&EDirsFirst)==EDirsFirst)
sl@0
   114
		{
sl@0
   115
		if (left.IsDir())
sl@0
   116
			{
sl@0
   117
			if (!right.IsDir())
sl@0
   118
				ret=(-1); // left is a dir, right is not
sl@0
   119
			}
sl@0
   120
		else if (right.IsDir())
sl@0
   121
			ret=1; // right is a dir, left is not
sl@0
   122
		}
sl@0
   123
	else if ((iKeyLength&EDirsLast)==EDirsLast)
sl@0
   124
		{
sl@0
   125
		if (left.IsDir())
sl@0
   126
			{
sl@0
   127
			if (!right.IsDir())
sl@0
   128
				ret=1; // left is a dir, right is not
sl@0
   129
			}
sl@0
   130
		else if (right.IsDir())
sl@0
   131
			ret=(-1); // right is a dir, left is not
sl@0
   132
		}
sl@0
   133
sl@0
   134
	TInt cmpType=iCmpType;
sl@0
   135
	TInt keyLength=iKeyLength;
sl@0
   136
	TBool orderDirectories=(keyLength&EDirsFirst) || (keyLength&EDirsLast);
sl@0
   137
	if (orderDirectories && left.IsDir() && right.IsDir())
sl@0
   138
		{
sl@0
   139
		cmpType=ESortByName;
sl@0
   140
		if ((keyLength&EDirDescending)!=EDirDescending)
sl@0
   141
			keyLength&=~EDescending;
sl@0
   142
		else
sl@0
   143
			keyLength|=EDescending;
sl@0
   144
		}
sl@0
   145
sl@0
   146
	if (ret==0) // Both are the same type
sl@0
   147
		{
sl@0
   148
		ret=(-1); // left before right by default
sl@0
   149
		switch (cmpType)
sl@0
   150
			{
sl@0
   151
		case ESortNone:
sl@0
   152
			ret=1;
sl@0
   153
			break;
sl@0
   154
		case ESortByDate:
sl@0
   155
			if (left.Modified()>right.Modified())
sl@0
   156
				ret=1;
sl@0
   157
			else if (left.Modified()==right.Modified())
sl@0
   158
				ret=0;
sl@0
   159
			break;
sl@0
   160
		case ESortBySize:
sl@0
   161
#ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
sl@0
   162
		if (I64LOW(left.Size()) > I64LOW(right.Size()))
sl@0
   163
			ret=1;
sl@0
   164
		else if (I64LOW(left.Size())==I64LOW(right.Size()))
sl@0
   165
			ret=0;
sl@0
   166
#else
sl@0
   167
			if (left.Size() > right.Size())
sl@0
   168
				ret=1;
sl@0
   169
			else if (left.Size()==right.Size())
sl@0
   170
				ret=0;
sl@0
   171
#endif
sl@0
   172
			break;
sl@0
   173
		case ESortByExt:
sl@0
   174
			{
sl@0
   175
			TInt i1 = KErrNotFound, i2 = KErrNotFound;
sl@0
   176
			if (left.Name() != _L(".") && left.Name() != _L(".."))
sl@0
   177
				i1 = left.Name().LocateReverse('.');
sl@0
   178
			if (right.Name() != _L(".") && right.Name() != _L(".."))
sl@0
   179
				i2 = right.Name().LocateReverse('.');
sl@0
   180
			if (i1==KErrNotFound && i2!=KErrNotFound)
sl@0
   181
				ret=(-1);
sl@0
   182
			else if (i2==KErrNotFound && i1!=KErrNotFound)
sl@0
   183
				ret=1;
sl@0
   184
			else if ((i1==KErrNotFound && i2==KErrNotFound) || (ret=left.Name().Mid(i1).CompareC(right.Name().Mid(i2)))==0)
sl@0
   185
				goto byName;
sl@0
   186
			}
sl@0
   187
			break;
sl@0
   188
		case ESortByUid:
sl@0
   189
			if (left.Type()[1]==right.Type()[1])
sl@0
   190
				{
sl@0
   191
				if (left.Type()[2]==right.Type()[2])
sl@0
   192
					ret = CompareByName(left, right);
sl@0
   193
				else if (left.Type()[2].iUid>right.Type()[2].iUid)
sl@0
   194
					ret=1;
sl@0
   195
				}
sl@0
   196
			else if (left.Type()[1].iUid==0)
sl@0
   197
				ret=1;
sl@0
   198
			else if (right.Type()[1].iUid==0)
sl@0
   199
				ret=-1;
sl@0
   200
			else if (left.Type()[1].iUid>right.Type()[1].iUid)
sl@0
   201
				ret=1;
sl@0
   202
			break;
sl@0
   203
		case ESortByName:
sl@0
   204
byName:
sl@0
   205
			// Force the maximum collation level here (i.e. 3) for sorting strings 
sl@0
   206
			ret = CompareByName(left, right);
sl@0
   207
			break;
sl@0
   208
		default: // Default is bad news
sl@0
   209
			Panic(ECDirBadSortType);
sl@0
   210
			}
sl@0
   211
		}
sl@0
   212
	if ((keyLength&EDescending)==EDescending)
sl@0
   213
		ret=(-ret); // Descending sort order
sl@0
   214
	return(ret);
sl@0
   215
	}
sl@0
   216
sl@0
   217
TInt TKeyDir::CompareByName(TEntry2& aLeft, TEntry2& aRight) const
sl@0
   218
//
sl@0
   219
// Compare using collation key of entire name
sl@0
   220
//
sl@0
   221
	{
sl@0
   222
	TInt ret = -1;
sl@0
   223
	TInt r = KErrNone;
sl@0
   224
sl@0
   225
    // Allocate partial key first and handle potential error case
sl@0
   226
    // by calling old CompareC
sl@0
   227
	// Note: only compare on the first collation level (KCollationLevel0) for partial keys, 
sl@0
   228
	//       to avoid potential inconsistency between full key and partial key comparison.
sl@0
   229
	if (!aLeft.iPartKey)
sl@0
   230
		{
sl@0
   231
		TRAP(r, aLeft.iPartKey = aLeft.Name().Left(KPartKeyLength).GetCollationKeysL(KCollationLevel0, &iCollationMethod));
sl@0
   232
		if (r != KErrNone)
sl@0
   233
		    aLeft.iPartKey = KCollationKeyAllocFail;
sl@0
   234
		}
sl@0
   235
	if (!aRight.iPartKey)
sl@0
   236
		{
sl@0
   237
		TRAP(r, aRight.iPartKey = aRight.Name().Left(KPartKeyLength).GetCollationKeysL(KCollationLevel0, &iCollationMethod));
sl@0
   238
		if (r != KErrNone)
sl@0
   239
		    aRight.iPartKey = KCollationKeyAllocFail;
sl@0
   240
		}
sl@0
   241
	if (aLeft.iPartKey == KCollationKeyAllocFail || aRight.iPartKey == KCollationKeyAllocFail)
sl@0
   242
		return aLeft.Name().CompareC(aRight.Name());
sl@0
   243
sl@0
   244
	// Compare by partial key first
sl@0
   245
    ret = aLeft.iPartKey->Compare(*aRight.iPartKey);
sl@0
   246
    if (ret != 0)
sl@0
   247
        return ret;
sl@0
   248
sl@0
   249
    // Compare by full key if partial keys are identical
sl@0
   250
	if (!aLeft.iFullKey)
sl@0
   251
		{
sl@0
   252
		TRAP(r, aLeft.iFullKey = aLeft.Name().GetCollationKeysL(KCollationLevelMax, &iCollationMethod));
sl@0
   253
		if (r != KErrNone)
sl@0
   254
		    aLeft.iFullKey = KCollationKeyAllocFail;
sl@0
   255
		}
sl@0
   256
	if (!aRight.iFullKey)
sl@0
   257
		{
sl@0
   258
		TRAP(r, aRight.iFullKey = aRight.Name().GetCollationKeysL(KCollationLevelMax, &iCollationMethod));
sl@0
   259
		if (r != KErrNone)
sl@0
   260
		    aRight.iFullKey = KCollationKeyAllocFail;
sl@0
   261
		}
sl@0
   262
	if (aLeft.iFullKey == KCollationKeyAllocFail || aRight.iFullKey == KCollationKeyAllocFail)
sl@0
   263
	    // Using old CompareC if partial key allocation failed
sl@0
   264
		return aLeft.Name().CompareC(aRight.Name());
sl@0
   265
sl@0
   266
    // Compare using collation key of full names
sl@0
   267
    ret = aLeft.iFullKey->Compare(*aRight.iFullKey);
sl@0
   268
sl@0
   269
	return ret;
sl@0
   270
	}
sl@0
   271
sl@0
   272
sl@0
   273
sl@0
   274
EXPORT_C CDir::CDir()
sl@0
   275
/**
sl@0
   276
Default constructor.
sl@0
   277
*/
sl@0
   278
	{
sl@0
   279
	}
sl@0
   280
sl@0
   281
sl@0
   282
sl@0
   283
sl@0
   284
EXPORT_C CDir::~CDir()
sl@0
   285
/**
sl@0
   286
Destructor.
sl@0
   287
sl@0
   288
Frees all resources owned by the object, prior to its destruction.
sl@0
   289
*/
sl@0
   290
	{
sl@0
   291
sl@0
   292
	delete iArray;
sl@0
   293
	}
sl@0
   294
sl@0
   295
sl@0
   296
sl@0
   297
sl@0
   298
EXPORT_C CDir* CDir::NewL()
sl@0
   299
/**
sl@0
   300
Allocates and constructs a directory object.
sl@0
   301
sl@0
   302
This function is protected, which prevents objects of this class from being
sl@0
   303
directly constructed.
sl@0
   304
sl@0
   305
@return A pointer to the newly created object.
sl@0
   306
*/
sl@0
   307
	{
sl@0
   308
sl@0
   309
	CDir* pD=new(ELeave) CDir;
sl@0
   310
	pD->iArray=new CArrayPakFlat<TEntry>(KCDirArrayGranularity);
sl@0
   311
	if (pD->iArray==NULL)
sl@0
   312
		{
sl@0
   313
		delete pD;
sl@0
   314
		User::LeaveNoMemory();
sl@0
   315
		}
sl@0
   316
	return(pD);
sl@0
   317
	}
sl@0
   318
sl@0
   319
sl@0
   320
sl@0
   321
sl@0
   322
EXPORT_C TInt CDir::Count() const
sl@0
   323
/**
sl@0
   324
Gets the number of entries in the array of directory
sl@0
   325
entries.
sl@0
   326
sl@0
   327
@return The number of entries in the array.
sl@0
   328
*/
sl@0
   329
	{
sl@0
   330
sl@0
   331
	return(iArray->Count());
sl@0
   332
	}
sl@0
   333
sl@0
   334
sl@0
   335
sl@0
   336
sl@0
   337
EXPORT_C const TEntry& CDir::operator[](TInt anIndex) const
sl@0
   338
/**
sl@0
   339
Gets an entry from the array of directory
sl@0
   340
entries.
sl@0
   341
sl@0
   342
@param anIndex of the desired entry within the array.
sl@0
   343
sl@0
   344
@return A directory entry.
sl@0
   345
*/
sl@0
   346
	{
sl@0
   347
sl@0
   348
	return((*iArray)[anIndex]);
sl@0
   349
	}
sl@0
   350
sl@0
   351
sl@0
   352
/**
sl@0
   353
 * Utility class to manage dynamic array memory
sl@0
   354
 * @internalComponent
sl@0
   355
 */
sl@0
   356
NONSHARABLE_CLASS(CAutoArray) : public CBase
sl@0
   357
    {
sl@0
   358
public:
sl@0
   359
    ~CAutoArray();
sl@0
   360
public:
sl@0
   361
    CArrayVarFlat<TEntry2>* iArray;
sl@0
   362
    };
sl@0
   363
sl@0
   364
// Have to do this trick because CArrayVarFlat won't destroy element one by one
sl@0
   365
CAutoArray::~CAutoArray()
sl@0
   366
    {
sl@0
   367
    if (iArray)
sl@0
   368
        for (TInt i=0; i<iArray->Count(); ++i)
sl@0
   369
            {
sl@0
   370
            TEntry2& e = (*iArray)[i];
sl@0
   371
           	if (e.iPartKey != KCollationKeyAllocFail)
sl@0
   372
                delete e.iPartKey;
sl@0
   373
	        if (e.iFullKey != KCollationKeyAllocFail)
sl@0
   374
	            delete e.iFullKey;
sl@0
   375
            e.iPartKey = e.iFullKey = 0;
sl@0
   376
            }
sl@0
   377
    delete iArray;
sl@0
   378
    }
sl@0
   379
sl@0
   380
EXPORT_C TInt CDir::Sort(TUint aKey)
sl@0
   381
/**
sl@0
   382
Sorts the array of directory entries.
sl@0
   383
sl@0
   384
@param aKey A set of flags describing how the directory entries are to be sorted.
sl@0
   385
       The set of flags is defined by TEntryKey.
sl@0
   386
sl@0
   387
@return KErrNone, if successful, otherwise one of the other	 system-wide error
sl@0
   388
        codes.
sl@0
   389
sl@0
   390
@see TEntryKey
sl@0
   391
*/
sl@0
   392
	{
sl@0
   393
	CAutoArray autoArray;
sl@0
   394
	#define array autoArray.iArray
sl@0
   395
sl@0
   396
	// Create TEntry2 array from iArray.
sl@0
   397
	array = new CArrayVarFlat<TEntry2>(KCDirArrayGranularity);
sl@0
   398
	if (!array)
sl@0
   399
		return KErrNoMemory;
sl@0
   400
	
sl@0
   401
	TInt arrayCount = iArray->Count();
sl@0
   402
	if (arrayCount == 0)
sl@0
   403
		return KErrNone;
sl@0
   404
	
sl@0
   405
	TEntry2* entry2 = new TEntry2((*iArray)[0]);
sl@0
   406
	
sl@0
   407
	if (!entry2)
sl@0
   408
		return KErrNoMemory;
sl@0
   409
sl@0
   410
	TInt i, r;
sl@0
   411
	for (i=0; i<arrayCount; ++i)
sl@0
   412
		{
sl@0
   413
		entry2->iEntry = (*iArray)[i];
sl@0
   414
		// Pack here
sl@0
   415
		TUint32* pSizeHighSrc = PtrAdd((TUint32*)&(entry2->iEntry), sizeof(TEntry) - 2 * sizeof(TInt));
sl@0
   416
		TUint32* pSizeHighDst = PtrAdd((TUint32*)&(entry2->iEntry), EntrySize(entry2->iEntry, EFalse));
sl@0
   417
		
sl@0
   418
		*pSizeHighDst++ = *pSizeHighSrc++;	// Pack iSizeHigh
sl@0
   419
		*pSizeHighDst   = *pSizeHighSrc;	// Pack iReserved
sl@0
   420
		entry2->iEntry.iAtt |= KEntryAttPacked;
sl@0
   421
		
sl@0
   422
		TRAP(r, array->AppendL(*entry2, Entry2Size(*entry2)));
sl@0
   423
sl@0
   424
		if (r != KErrNone)
sl@0
   425
			{
sl@0
   426
			delete entry2;	
sl@0
   427
			return r;
sl@0
   428
			}
sl@0
   429
		}
sl@0
   430
sl@0
   431
	// Sort new array
sl@0
   432
	TKeyDir key(aKey);
sl@0
   433
	r = array->Sort(key);
sl@0
   434
	if (r != KErrNone)
sl@0
   435
		{
sl@0
   436
		delete entry2;
sl@0
   437
        return r;
sl@0
   438
		}
sl@0
   439
sl@0
   440
	// Copy sorted result back to iArray
sl@0
   441
	iArray->Reset();
sl@0
   442
	
sl@0
   443
	for (i=0; i<array->Count(); ++i)
sl@0
   444
		{
sl@0
   445
		entry2->iEntry = (*array)[i].iEntry;
sl@0
   446
		// Pack here
sl@0
   447
		TUint32* pSizeHighSrc = PtrAdd((TUint32*)&(entry2->iEntry), sizeof(TEntry) - 2 * sizeof(TInt));
sl@0
   448
		TUint32* pSizeHighDst = PtrAdd((TUint32*)&(entry2->iEntry), EntrySize(entry2->iEntry, EFalse));
sl@0
   449
		
sl@0
   450
		*pSizeHighDst++ = *pSizeHighSrc++;	// Pack iSizeHigh
sl@0
   451
		*pSizeHighDst   = *pSizeHighSrc;	// Pack iReserved
sl@0
   452
		entry2->iEntry.iAtt |= KEntryAttPacked;
sl@0
   453
		
sl@0
   454
		TRAP(r, iArray->AppendL(entry2->iEntry, EntrySize(entry2->iEntry, ETrue)));
sl@0
   455
		if (r != KErrNone)
sl@0
   456
			{
sl@0
   457
			delete entry2;	
sl@0
   458
			return r;
sl@0
   459
			}
sl@0
   460
		}
sl@0
   461
sl@0
   462
	delete entry2;
sl@0
   463
	return r;
sl@0
   464
	}
sl@0
   465
	
sl@0
   466
sl@0
   467
EXPORT_C void CDir::AddL(const TEntry& aEntry)
sl@0
   468
/**
sl@0
   469
Adds the specified entry to the directory.
sl@0
   470
sl@0
   471
Note that the function can leave.
sl@0
   472
sl@0
   473
@param aEntry The directory entry to be added.
sl@0
   474
*/
sl@0
   475
	{
sl@0
   476
	if(aEntry.iAtt & KEntryAttPacked)
sl@0
   477
		{
sl@0
   478
		iArray->AppendL(aEntry,EntrySize(aEntry, ETrue));
sl@0
   479
		}
sl@0
   480
	else
sl@0
   481
		{
sl@0
   482
		TEntry entry = aEntry;
sl@0
   483
		// Pack here
sl@0
   484
		TUint32* pSizeHighSrc = PtrAdd((TUint32*)&entry, sizeof(TEntry) - 2 * sizeof(TInt));
sl@0
   485
		TUint32* pSizeHighDst = PtrAdd((TUint32*)&entry, EntrySize(entry, EFalse));
sl@0
   486
		
sl@0
   487
		*pSizeHighDst++ = *pSizeHighSrc++;	// Pack iSizeHigh
sl@0
   488
		*pSizeHighDst   = *pSizeHighSrc;		// Pack iReserved
sl@0
   489
		entry.iAtt |= KEntryAttPacked;
sl@0
   490
		iArray->AppendL(entry,EntrySize(entry, ETrue));
sl@0
   491
		}
sl@0
   492
	}
sl@0
   493
sl@0
   494
sl@0
   495
sl@0
   496
sl@0
   497
EXPORT_C void CDir::ExtractL(TBool aRemove,CDir* & aDir)
sl@0
   498
/**
sl@0
   499
Copies all directory entries from this directory array, and adds them to
sl@0
   500
a new directory array.
sl@0
   501
sl@0
   502
The directory entries in this array can be deleted.
sl@0
   503
sl@0
   504
Note that the function can leave.
sl@0
   505
sl@0
   506
@param aRemove If ETrue, the  directory entries in this array are
sl@0
   507
               to be deleted after extraction;
sl@0
   508
               if EFalse, the directory entries are not to be deleted.
sl@0
   509
                
sl@0
   510
@param aDir    On return, a pointer to a CDir object containing
sl@0
   511
               the extracted directory entries.
sl@0
   512
*/
sl@0
   513
	{
sl@0
   514
sl@0
   515
	aDir=NULL;
sl@0
   516
	aDir=CDir::NewL();
sl@0
   517
	CArrayPakFlat<TEntry>& anArray=(*iArray);
sl@0
   518
	TInt count=anArray.Count();
sl@0
   519
	
sl@0
   520
	if (count == 0)
sl@0
   521
		return;
sl@0
   522
	
sl@0
   523
	TInt i=0;
sl@0
   524
	while (i<count)
sl@0
   525
		{
sl@0
   526
		TEntry& e=anArray[i];
sl@0
   527
		if (e.IsDir())
sl@0
   528
			aDir->AddL(e);
sl@0
   529
		i++;
sl@0
   530
		}
sl@0
   531
	if (aRemove)
sl@0
   532
		{
sl@0
   533
		i=0;
sl@0
   534
		while (i<count)
sl@0
   535
			{
sl@0
   536
			if (anArray[i].IsDir())
sl@0
   537
				{
sl@0
   538
				anArray.Delete(i);
sl@0
   539
				count--;
sl@0
   540
				continue;
sl@0
   541
				}
sl@0
   542
			i++;
sl@0
   543
			}
sl@0
   544
		anArray.Compress();
sl@0
   545
		}
sl@0
   546
	aDir->Compress();
sl@0
   547
	}
sl@0
   548
sl@0
   549
sl@0
   550
sl@0
   551
sl@0
   552
EXPORT_C void CDir::Compress()
sl@0
   553
/**
sl@0
   554
Compresses the directory.
sl@0
   555
sl@0
   556
This has the effect of potentially reducing the ammount of storage 
sl@0
   557
space required on the media for that directory and the files it contains. 
sl@0
   558
Some files are already compressed and will not compress further.
sl@0
   559
sl@0
   560
A potential side effect of compression is that each file is required to 
sl@0
   561
be uncompressed prior to use, generally increasing the time and 
sl@0
   562
processing cycles required to access that file.
sl@0
   563
sl@0
   564
*/
sl@0
   565
	{
sl@0
   566
sl@0
   567
	iArray->Compress();
sl@0
   568
	}
sl@0
   569