Update contrib.
1 // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // f32\sfsrv\cl_cdir.cpp
21 const TUint KCDirArrayGranularity=0x200;
22 const TInt KPartKeyLength = 8;
23 const TInt KCollationLevel0 = 0;
24 const TInt KCollationLevelMax = 3;
26 #define KCollationKeyAllocFail ((HBufC8*)-1)
28 ///////////////////////////////////////////////////////////////////////////////
31 * @description TEntry's variant with pointer to collation key buffers
34 NONSHARABLE_CLASS(TEntry2)
37 TEntry2(const TEntry& aEntry);
40 TBool IsDir() const {return iEntry.IsDir();}
41 #ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
42 TInt64 Size() {return MAKE_TINT64(0,iEntry.iSize);}
44 TInt64 Size() {return iEntry.FileSize();}
46 TTime Modified() const {return iEntry.iModified;}
47 const TUidType& Type() const {return iEntry.iType;}
48 const TDesC& Name() const {return iEntry.iName;}
50 TEntry2(const TEntry2& aEntry);
51 TEntry2& operator=(const TEntry2& aEntry);
58 TEntry2::TEntry2(const TEntry& aEntry) : iPartKey(0), iFullKey(0), iEntry(aEntry)
64 if (iPartKey != KCollationKeyAllocFail)
66 if (iFullKey != KCollationKeyAllocFail)
70 inline TInt Entry2Size(const TEntry2& aEntry)
72 return sizeof(HBufC8*) * 2 + EntrySize(aEntry.iEntry, ETrue);
74 ///////////////////////////////////////////////////////////////////////////////
76 NONSHARABLE_CLASS(TKeyDir) : public TKeyArrayVar
80 virtual TInt Compare(TInt aLeft,TInt aRight) const;
82 TInt CompareByName(TEntry2& aLeft, TEntry2& aRight) const;
84 TCollationMethod iCollationMethod;
87 TKeyDir::TKeyDir(TUint aKey)
91 : TKeyArrayVar(0,(TKeyCmpText)(aKey&0xff),aKey&(EDirsFirst|EDirsLast|EDescending|EDirDescending))
94 // Create our own collation method to also consider punctuation when
97 iCollationMethod = *Mem::GetDefaultMatchingTable();
98 iCollationMethod.iFlags |= TCollationMethod::EIgnoreNone | TCollationMethod::EFoldCase;
102 TInt TKeyDir::Compare(TInt aLeft,TInt aRight) const
104 // Compare two directories for sorting.
110 TEntry2& left = *(TEntry2*)At(aLeft);
111 TEntry2& right = *(TEntry2*)At(aRight);
113 if ((iKeyLength&EDirsFirst)==EDirsFirst)
118 ret=(-1); // left is a dir, right is not
120 else if (right.IsDir())
121 ret=1; // right is a dir, left is not
123 else if ((iKeyLength&EDirsLast)==EDirsLast)
128 ret=1; // left is a dir, right is not
130 else if (right.IsDir())
131 ret=(-1); // right is a dir, left is not
134 TInt cmpType=iCmpType;
135 TInt keyLength=iKeyLength;
136 TBool orderDirectories=(keyLength&EDirsFirst) || (keyLength&EDirsLast);
137 if (orderDirectories && left.IsDir() && right.IsDir())
140 if ((keyLength&EDirDescending)!=EDirDescending)
141 keyLength&=~EDescending;
143 keyLength|=EDescending;
146 if (ret==0) // Both are the same type
148 ret=(-1); // left before right by default
155 if (left.Modified()>right.Modified())
157 else if (left.Modified()==right.Modified())
161 #ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
162 if (I64LOW(left.Size()) > I64LOW(right.Size()))
164 else if (I64LOW(left.Size())==I64LOW(right.Size()))
167 if (left.Size() > right.Size())
169 else if (left.Size()==right.Size())
175 TInt i1 = KErrNotFound, i2 = KErrNotFound;
176 if (left.Name() != _L(".") && left.Name() != _L(".."))
177 i1 = left.Name().LocateReverse('.');
178 if (right.Name() != _L(".") && right.Name() != _L(".."))
179 i2 = right.Name().LocateReverse('.');
180 if (i1==KErrNotFound && i2!=KErrNotFound)
182 else if (i2==KErrNotFound && i1!=KErrNotFound)
184 else if ((i1==KErrNotFound && i2==KErrNotFound) || (ret=left.Name().Mid(i1).CompareC(right.Name().Mid(i2)))==0)
189 if (left.Type()[1]==right.Type()[1])
191 if (left.Type()[2]==right.Type()[2])
192 ret = CompareByName(left, right);
193 else if (left.Type()[2].iUid>right.Type()[2].iUid)
196 else if (left.Type()[1].iUid==0)
198 else if (right.Type()[1].iUid==0)
200 else if (left.Type()[1].iUid>right.Type()[1].iUid)
205 // Force the maximum collation level here (i.e. 3) for sorting strings
206 ret = CompareByName(left, right);
208 default: // Default is bad news
209 Panic(ECDirBadSortType);
212 if ((keyLength&EDescending)==EDescending)
213 ret=(-ret); // Descending sort order
217 TInt TKeyDir::CompareByName(TEntry2& aLeft, TEntry2& aRight) const
219 // Compare using collation key of entire name
225 // Allocate partial key first and handle potential error case
226 // by calling old CompareC
227 // Note: only compare on the first collation level (KCollationLevel0) for partial keys,
228 // to avoid potential inconsistency between full key and partial key comparison.
231 TRAP(r, aLeft.iPartKey = aLeft.Name().Left(KPartKeyLength).GetCollationKeysL(KCollationLevel0, &iCollationMethod));
233 aLeft.iPartKey = KCollationKeyAllocFail;
235 if (!aRight.iPartKey)
237 TRAP(r, aRight.iPartKey = aRight.Name().Left(KPartKeyLength).GetCollationKeysL(KCollationLevel0, &iCollationMethod));
239 aRight.iPartKey = KCollationKeyAllocFail;
241 if (aLeft.iPartKey == KCollationKeyAllocFail || aRight.iPartKey == KCollationKeyAllocFail)
242 return aLeft.Name().CompareC(aRight.Name());
244 // Compare by partial key first
245 ret = aLeft.iPartKey->Compare(*aRight.iPartKey);
249 // Compare by full key if partial keys are identical
252 TRAP(r, aLeft.iFullKey = aLeft.Name().GetCollationKeysL(KCollationLevelMax, &iCollationMethod));
254 aLeft.iFullKey = KCollationKeyAllocFail;
256 if (!aRight.iFullKey)
258 TRAP(r, aRight.iFullKey = aRight.Name().GetCollationKeysL(KCollationLevelMax, &iCollationMethod));
260 aRight.iFullKey = KCollationKeyAllocFail;
262 if (aLeft.iFullKey == KCollationKeyAllocFail || aRight.iFullKey == KCollationKeyAllocFail)
263 // Using old CompareC if partial key allocation failed
264 return aLeft.Name().CompareC(aRight.Name());
266 // Compare using collation key of full names
267 ret = aLeft.iFullKey->Compare(*aRight.iFullKey);
274 EXPORT_C CDir::CDir()
284 EXPORT_C CDir::~CDir()
288 Frees all resources owned by the object, prior to its destruction.
298 EXPORT_C CDir* CDir::NewL()
300 Allocates and constructs a directory object.
302 This function is protected, which prevents objects of this class from being
303 directly constructed.
305 @return A pointer to the newly created object.
309 CDir* pD=new(ELeave) CDir;
310 pD->iArray=new CArrayPakFlat<TEntry>(KCDirArrayGranularity);
311 if (pD->iArray==NULL)
314 User::LeaveNoMemory();
322 EXPORT_C TInt CDir::Count() const
324 Gets the number of entries in the array of directory
327 @return The number of entries in the array.
331 return(iArray->Count());
337 EXPORT_C const TEntry& CDir::operator[](TInt anIndex) const
339 Gets an entry from the array of directory
342 @param anIndex of the desired entry within the array.
344 @return A directory entry.
348 return((*iArray)[anIndex]);
353 * Utility class to manage dynamic array memory
356 NONSHARABLE_CLASS(CAutoArray) : public CBase
361 CArrayVarFlat<TEntry2>* iArray;
364 // Have to do this trick because CArrayVarFlat won't destroy element one by one
365 CAutoArray::~CAutoArray()
368 for (TInt i=0; i<iArray->Count(); ++i)
370 TEntry2& e = (*iArray)[i];
371 if (e.iPartKey != KCollationKeyAllocFail)
373 if (e.iFullKey != KCollationKeyAllocFail)
375 e.iPartKey = e.iFullKey = 0;
380 EXPORT_C TInt CDir::Sort(TUint aKey)
382 Sorts the array of directory entries.
384 @param aKey A set of flags describing how the directory entries are to be sorted.
385 The set of flags is defined by TEntryKey.
387 @return KErrNone, if successful, otherwise one of the other system-wide error
393 CAutoArray autoArray;
394 #define array autoArray.iArray
396 // Create TEntry2 array from iArray.
397 array = new CArrayVarFlat<TEntry2>(KCDirArrayGranularity);
401 TInt arrayCount = iArray->Count();
405 TEntry2* entry2 = new TEntry2((*iArray)[0]);
411 for (i=0; i<arrayCount; ++i)
413 entry2->iEntry = (*iArray)[i];
415 TUint32* pSizeHighSrc = PtrAdd((TUint32*)&(entry2->iEntry), sizeof(TEntry) - 2 * sizeof(TInt));
416 TUint32* pSizeHighDst = PtrAdd((TUint32*)&(entry2->iEntry), EntrySize(entry2->iEntry, EFalse));
418 *pSizeHighDst++ = *pSizeHighSrc++; // Pack iSizeHigh
419 *pSizeHighDst = *pSizeHighSrc; // Pack iReserved
420 entry2->iEntry.iAtt |= KEntryAttPacked;
422 TRAP(r, array->AppendL(*entry2, Entry2Size(*entry2)));
433 r = array->Sort(key);
440 // Copy sorted result back to iArray
443 for (i=0; i<array->Count(); ++i)
445 entry2->iEntry = (*array)[i].iEntry;
447 TUint32* pSizeHighSrc = PtrAdd((TUint32*)&(entry2->iEntry), sizeof(TEntry) - 2 * sizeof(TInt));
448 TUint32* pSizeHighDst = PtrAdd((TUint32*)&(entry2->iEntry), EntrySize(entry2->iEntry, EFalse));
450 *pSizeHighDst++ = *pSizeHighSrc++; // Pack iSizeHigh
451 *pSizeHighDst = *pSizeHighSrc; // Pack iReserved
452 entry2->iEntry.iAtt |= KEntryAttPacked;
454 TRAP(r, iArray->AppendL(entry2->iEntry, EntrySize(entry2->iEntry, ETrue)));
467 EXPORT_C void CDir::AddL(const TEntry& aEntry)
469 Adds the specified entry to the directory.
471 Note that the function can leave.
473 @param aEntry The directory entry to be added.
476 if(aEntry.iAtt & KEntryAttPacked)
478 iArray->AppendL(aEntry,EntrySize(aEntry, ETrue));
482 TEntry entry = aEntry;
484 TUint32* pSizeHighSrc = PtrAdd((TUint32*)&entry, sizeof(TEntry) - 2 * sizeof(TInt));
485 TUint32* pSizeHighDst = PtrAdd((TUint32*)&entry, EntrySize(entry, EFalse));
487 *pSizeHighDst++ = *pSizeHighSrc++; // Pack iSizeHigh
488 *pSizeHighDst = *pSizeHighSrc; // Pack iReserved
489 entry.iAtt |= KEntryAttPacked;
490 iArray->AppendL(entry,EntrySize(entry, ETrue));
497 EXPORT_C void CDir::ExtractL(TBool aRemove,CDir* & aDir)
499 Copies all directory entries from this directory array, and adds them to
500 a new directory array.
502 The directory entries in this array can be deleted.
504 Note that the function can leave.
506 @param aRemove If ETrue, the directory entries in this array are
507 to be deleted after extraction;
508 if EFalse, the directory entries are not to be deleted.
510 @param aDir On return, a pointer to a CDir object containing
511 the extracted directory entries.
517 CArrayPakFlat<TEntry>& anArray=(*iArray);
518 TInt count=anArray.Count();
526 TEntry& e=anArray[i];
536 if (anArray[i].IsDir())
552 EXPORT_C void CDir::Compress()
554 Compresses the directory.
556 This has the effect of potentially reducing the ammount of storage
557 space required on the media for that directory and the files it contains.
558 Some files are already compressed and will not compress further.
560 A potential side effect of compression is that each file is required to
561 be uncompressed prior to use, generally increasing the time and
562 processing cycles required to access that file.