imgtools/romtools/rombuild/r_dir.cpp
changeset 0 044383f39525
child 590 360bd6b35136
equal deleted inserted replaced
-1:000000000000 0:044383f39525
       
     1 /*
       
     2 * Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 * e32tools/rombuild/r_dir.cpp
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 #include <stdlib.h>
       
    21 #include <string.h>
       
    22 #include "r_dir.h"
       
    23 #include "r_obey.h"
       
    24 #include "r_rom.h"
       
    25 #include "r_global.h"
       
    26 
       
    27 // Generalised set handling
       
    28 
       
    29 // class SetMember
       
    30 TInt SetMember::TotalInSystem=0;
       
    31 
       
    32 SetMember::~SetMember()
       
    33 	{
       
    34 	TotalInSystem--;
       
    35 	TRACE(TDIR,Print(EAlways,"SetMember %08x Destruct Remaining=%d\n",this,TotalInSystem));
       
    36 	}
       
    37 
       
    38 void SetMember::Close()
       
    39 	{
       
    40 	delete this;
       
    41 	}
       
    42 
       
    43 // class FiniteSet
       
    44 FiniteSet::FiniteSet(TInt aMaxCount)
       
    45 	: SetMember(EFiniteSetType), iMaxCount(aMaxCount), iCount(0), iMembers(NULL)
       
    46 	{}
       
    47 
       
    48 FiniteSet::FiniteSet(const FiniteSet& aSet)
       
    49 	: SetMember(aSet), iMaxCount(aSet.iMaxCount), iCount(0), iMembers(NULL)
       
    50 	{}
       
    51 
       
    52 FiniteSet* FiniteSet::New(TInt aMaxCount)
       
    53 	{
       
    54 	FiniteSet* pS=new FiniteSet(aMaxCount);
       
    55 	if (pS)
       
    56 		pS=pS->Construct();
       
    57 	return pS;
       
    58 	}
       
    59 
       
    60 FiniteSet* FiniteSet::Construct()
       
    61 	{
       
    62 	SetMember** pM=new SetMember*[iMaxCount];
       
    63 	if (!pM)
       
    64 		{
       
    65 		delete this;
       
    66 		return NULL;
       
    67 		}
       
    68 	iMembers=pM;
       
    69 	TInt i;
       
    70 	for(i=0; i<iMaxCount; i++)
       
    71 		pM[i]=NULL;
       
    72 	return this;
       
    73 	}
       
    74 
       
    75 FiniteSet* FiniteSet::Singleton(TInt aMaxCount, const SetMember& aMember)
       
    76 	{
       
    77 	FiniteSet* pS=New(aMaxCount);
       
    78 	if (pS)
       
    79 		{
       
    80 		pS->iCount=1;
       
    81 		pS->iMembers[0]=(SetMember*)&aMember;
       
    82 		}
       
    83 	return pS;
       
    84 	}
       
    85 
       
    86 FiniteSet::~FiniteSet()
       
    87 	{
       
    88 	TRACE(TDIR,Print(EAlways,"FiniteSet %08x Destruct, iCount=%d\n",this,iCount));
       
    89 	TInt i;
       
    90 	for (i=0; i<iCount; i++)
       
    91 		iMembers[i]->Close();
       
    92 	delete[] iMembers;
       
    93 	}
       
    94 
       
    95 TInt FiniteSet::Find(const SetMember& aMember, TInt& anIndex) const
       
    96 	{
       
    97 	if (iCount==0)
       
    98 		{
       
    99 		anIndex=0;
       
   100 		return KErrNotFound;
       
   101 		}
       
   102 	TInt k=aMember.Compare(*iMembers[0]);
       
   103 	if (k==0)
       
   104 		{
       
   105 		anIndex=0;
       
   106 		return KErrNone;
       
   107 		}
       
   108 	if (k<0)
       
   109 		{
       
   110 		anIndex=0;
       
   111 		return KErrNotFound;
       
   112 		}
       
   113 	if (iCount==1)
       
   114 		{
       
   115 		anIndex=1;
       
   116 		return KErrNotFound;
       
   117 		}
       
   118 	TInt r=iCount-1;
       
   119 	k=aMember.Compare(*iMembers[r]);
       
   120 	if (k==0)
       
   121 		{
       
   122 		anIndex=r;
       
   123 		return KErrNone;
       
   124 		}
       
   125 	if (k>0)
       
   126 		{
       
   127 		anIndex=iCount;
       
   128 		return KErrNotFound;
       
   129 		}
       
   130 	if (iCount==2)
       
   131 		{
       
   132 		anIndex=1;
       
   133 		return KErrNotFound;
       
   134 		}
       
   135 	TInt l=0;
       
   136 	while(r-l>1)
       
   137 		{
       
   138 		TInt m=(l+r)>>1;
       
   139 		k=aMember.Compare(*iMembers[m]);
       
   140 		if (k==0)
       
   141 			{
       
   142 			anIndex=m;
       
   143 			return KErrNone;
       
   144 			}
       
   145 		if (k>0)
       
   146 			l=m;
       
   147 		else
       
   148 			r=m;
       
   149 		}
       
   150 	anIndex=r;
       
   151 	return KErrNotFound;
       
   152 	}
       
   153 
       
   154 TInt FiniteSet::Compare(const SetMember& aSetMember) const
       
   155 	{
       
   156 	TInt k=Type()-aSetMember.Type();
       
   157 	if (k!=0)
       
   158 		return k;
       
   159 	const FiniteSet& s=(const FiniteSet&)aSetMember;
       
   160 	TInt c=Min(iCount,s.iCount);
       
   161 	TInt i;
       
   162 	for(i=0; i<c; i++)
       
   163 		{
       
   164 		k=iMembers[i]->Compare(s[i]);
       
   165 		if (k!=0)
       
   166 			return k;
       
   167 		}
       
   168 	return (iCount-s.iCount);
       
   169 	}
       
   170 
       
   171 SetMember* FiniteSet::Copy() const
       
   172 	{
       
   173 	FiniteSet* pS=new FiniteSet(*this);
       
   174 	if (pS)
       
   175 		{
       
   176 		SetMember** pA=new SetMember*[iMaxCount];
       
   177 		if (!pA)
       
   178 			{
       
   179 			delete pS;
       
   180 			return NULL;
       
   181 			}
       
   182 		pS->iMembers=pA;
       
   183 		TInt i;
       
   184 		for(i=0; i<iCount; i++)
       
   185 			{
       
   186 			SetMember* pM=iMembers[i]->Copy();
       
   187 			if (!pM)
       
   188 				{
       
   189 				delete pS;
       
   190 				return NULL;
       
   191 				}
       
   192 			pA[i]=pM;
       
   193 			pS->iCount++;
       
   194 			}
       
   195 		}
       
   196 	return pS;
       
   197 	}
       
   198 
       
   199 TInt FiniteSet::Find(const SetMember& aMember) const
       
   200 	{
       
   201 	TInt i;
       
   202 	TInt r=Find(aMember,i);
       
   203 	if (r<0)
       
   204 		return r;
       
   205 	return i;
       
   206 	}
       
   207 
       
   208 TBool FiniteSet::SubsetOf(const FiniteSet& aSet) const
       
   209 	{
       
   210 	if (iCount>aSet.iCount)
       
   211 		return EFalse;
       
   212 	TInt i;
       
   213 	for(i=0; i<iCount; i++)
       
   214 		{
       
   215 		TInt j;
       
   216 		if (aSet.Find(*iMembers[i],j)!=KErrNone)
       
   217 			return EFalse;
       
   218 		}
       
   219 	return ETrue;
       
   220 	}
       
   221 
       
   222 TInt FiniteSet::Intersection(const FiniteSet& aSet)
       
   223 	{
       
   224 	if (iCount==0)
       
   225 		return KErrNotFound;
       
   226 	TInt i;
       
   227 	for(i=0; i<iCount; i++)
       
   228 		{
       
   229 		TInt j;
       
   230 		if (aSet.Find(*iMembers[i],j)!=KErrNone)
       
   231 			Detach(i)->Close();
       
   232 		}
       
   233 	return iCount ? KErrNone : KErrNotFound;
       
   234 	}
       
   235 
       
   236 TInt FiniteSet::Union(const FiniteSet& aSet)
       
   237 	{
       
   238 	TInt i;
       
   239 	for(i=0; i<aSet.iCount; i++)
       
   240 		{
       
   241 		const SetMember& m=*aSet.iMembers[i];
       
   242 		TInt j;
       
   243 		if (Find(m,j)!=KErrNone)
       
   244 			{
       
   245 			const SetMember* pC=m.Copy();
       
   246 			if (!pC)
       
   247 				return KErrNoMemory;
       
   248 			TInt r=Insert(*pC,j);
       
   249 			if (r!=KErrNone)
       
   250 				return r;
       
   251 			}
       
   252 		}
       
   253 	return iCount ? KErrNone : KErrNotFound;
       
   254 	}
       
   255 
       
   256 TInt FiniteSet::Difference(const FiniteSet& aSet)
       
   257 	{
       
   258 	if (iCount==0)
       
   259 		return KErrNotFound;
       
   260 	TInt i;
       
   261 	for(i=0; i<iCount; i++)
       
   262 		{
       
   263 		TInt j;
       
   264 		if (aSet.Find(*iMembers[i],j)==KErrNone)
       
   265 			Detach(i)->Close();
       
   266 		}
       
   267 	return iCount ? KErrNone : KErrNotFound;
       
   268 	}
       
   269 
       
   270 TInt FiniteSet::Add(const SetMember& aMember)
       
   271 	{
       
   272 	TInt i;
       
   273 	TInt r=Find(aMember,i);
       
   274 	if (r==KErrNotFound && Insert(aMember,i)==KErrOverflow)
       
   275 		return KErrOverflow;
       
   276 	return r;
       
   277 	}
       
   278 
       
   279 TInt FiniteSet::Remove(const SetMember& aMember)
       
   280 	{
       
   281 	TInt i;
       
   282 	TInt r=Find(aMember,i);
       
   283 	if (r==KErrNone)
       
   284 		Detach(i)->Close();
       
   285 	return r;
       
   286 	}
       
   287 
       
   288 SetMember* FiniteSet::Detach(TInt anIndex)
       
   289 	{
       
   290 	TInt i;
       
   291 	SetMember* pM=iMembers[anIndex];
       
   292 	for(i=anIndex; i<iCount-1; i++)
       
   293 		iMembers[i]=iMembers[i+1];
       
   294 	iCount--;
       
   295 	return pM;
       
   296 	}
       
   297 
       
   298 TInt FiniteSet::Insert(const SetMember& aMember, TInt anIndex)
       
   299 	{
       
   300 	if (iCount==iMaxCount)
       
   301 		return KErrOverflow;
       
   302 	TInt i;
       
   303 	for(i=iCount-1; i>=anIndex; i--)
       
   304 		iMembers[i+1]=iMembers[i];
       
   305 	iMembers[anIndex]=(SetMember*)&aMember;
       
   306 	iCount++;
       
   307 	return KErrNone;
       
   308 	}
       
   309 
       
   310 // ROMBUILD-specific stuff
       
   311 
       
   312 inline TLinAddr ActualToRomAddress(TAny* anAddr)
       
   313 	{ return TLinAddr(anAddr)-TheRomMem+TheRomLinearAddress; }
       
   314 
       
   315 // class TVariantList
       
   316 TInt TVariantList::NumVariants;
       
   317 THardwareVariant TVariantList::Variants[TVariantList::EMaxVariants];
       
   318 void TVariantList::Setup(CObeyFile* aObey)
       
   319 	{
       
   320 	NumVariants=aObey->iNumberOfVariants;
       
   321 	if (NumVariants>EMaxVariants)
       
   322 		Print(EError,"Too many variants");
       
   323 	TInt i;
       
   324 	for(i=0; i<NumVariants; i++)
       
   325 		{
       
   326 		Variants[i]=aObey->iVariants[i]->iHardwareVariant;
       
   327 		}
       
   328 	}
       
   329 
       
   330 TVariantList::TVariantList(THardwareVariant a)
       
   331 	{
       
   332 	iList=0;
       
   333 	TInt i;
       
   334 	for (i=0; i<NumVariants; i++)
       
   335 		{
       
   336 		if (Variants[i]<=a)
       
   337 			iList|=TUint(1<<i);
       
   338 		}
       
   339 	}
       
   340 
       
   341 THardwareVariant TVariantList::Lookup() const
       
   342 	{
       
   343 	TInt i;
       
   344 	for (i=0; i<NumVariants; i++)
       
   345 		{
       
   346 		if (iList & TUint(1<<i))
       
   347 			return Variants[i];
       
   348 		}
       
   349 	return THardwareVariant(0);
       
   350 	}
       
   351 
       
   352 void TVariantList::SetNumVariants(TInt aNumVariants)
       
   353 {
       
   354 	NumVariants = aNumVariants;
       
   355 	if (NumVariants>EMaxVariants)
       
   356 		Print(EError,"Too many variants");
       
   357 }
       
   358 
       
   359 void TVariantList::SetVariants(THardwareVariant* aVariants)
       
   360 {
       
   361 	TInt Index = NumVariants;
       
   362 	while(Index--)
       
   363 	{
       
   364 		Variants[Index] = aVariants[Index];
       
   365 	}
       
   366 }
       
   367 
       
   368 void DumpRomEntry(const TRomEntry& e)
       
   369 	{
       
   370 	char name[256];
       
   371 	char* d = name;
       
   372 	const wchar_t* s = (const wchar_t*)e.iName;
       
   373 	const wchar_t* sE = s + e.iNameLength;
       
   374 	for (; s<sE; *d++ = (char)*s++) {}
       
   375 	*d++ = 0;
       
   376 	Print(ELog, "RomEntry @ %08x: SZ=%08x A=%08x att=%02x name %s\n", &e, e.iSize, e.iAddressLin, e.iAtt, name);
       
   377 	}
       
   378 
       
   379 // class Entry
       
   380 TRomEntry* Entry::CreateRomEntry(char*& anAddr) const
       
   381 	{
       
   382 
       
   383 	TRomEntry *pE=(TRomEntry*)anAddr;
       
   384 	pE->iAtt=iRomNode->iAtt;
       
   385 	pE->iSize=iRomNode->iRomFile->iAddresses.iSize;
       
   386 	pE->iAddressLin=iRomNode->iRomFile->iAddresses.iRunAddr;
       
   387 	if (IsFile())
       
   388 		iRomNode->iRomFile->SetRomEntry(pE);
       
   389 	pE->iName[0]=0;
       
   390 	pE->iName[1]=0;
       
   391 	TInt nl=iRomNode->NameCpy((char*)pE->iName);
       
   392 	pE->iNameLength=(TUint8)nl;
       
   393 	if (Unicode)
       
   394 		nl<<=1;
       
   395 	anAddr+=Align4(KRomEntrySize+nl);
       
   396 	TRACE(TDIR,DumpRomEntry(*pE));
       
   397 	return pE;
       
   398 	}
       
   399 
       
   400 const TText* Entry::Name() const
       
   401 	{
       
   402 	return iRomNode->iName;
       
   403 	}
       
   404 
       
   405 // class FileEntry
       
   406 FileEntry::FileEntry(const FileEntry& aFileEntry)
       
   407 	: Entry(aFileEntry)
       
   408 	{
       
   409 	iVariants=aFileEntry.iVariants;
       
   410 	iRomNode=aFileEntry.iRomNode;
       
   411 	}
       
   412 
       
   413 FileEntry* FileEntry::New(TRomNode* aFile)
       
   414 	{
       
   415 	FileEntry* pE=new FileEntry();
       
   416 	if (pE)
       
   417 		{
       
   418 		pE->iRomNode=aFile;
       
   419 		pE->iVariants=TVariantList(aFile->HardwareVariant());
       
   420 		}
       
   421 	return pE;
       
   422 	}
       
   423 
       
   424 TInt FileEntry::Compare(const SetMember& aMember) const
       
   425 	{
       
   426 	TInt k=Type()-aMember.Type();
       
   427 	if (k!=0)
       
   428 		return k;
       
   429 	FileEntry *entry=(FileEntry *)&aMember;
       
   430 	return (iRomNode->iIdentifier-entry->iRomNode->iIdentifier);
       
   431 	}
       
   432 
       
   433 SetMember* FileEntry::Copy() const
       
   434 	{
       
   435 	return new FileEntry(*this);
       
   436 	}
       
   437 
       
   438 FileEntry::~FileEntry()
       
   439 	{
       
   440 	}
       
   441 
       
   442 // class DirEntry
       
   443 DirEntry::DirEntry(const DirEntry& aDirEntry)
       
   444 	: Entry(aDirEntry)
       
   445 	{
       
   446 	iVariants=aDirEntry.iVariants;
       
   447 	iRomNode=aDirEntry.iRomNode;
       
   448 	iDir=aDirEntry.iDir;
       
   449 	}
       
   450 
       
   451 DirEntry* DirEntry::New(TRomNode* aFile, Directory* aDir)
       
   452 	{
       
   453 	DirEntry* pE=new DirEntry();
       
   454 	if (pE)
       
   455 		{
       
   456 		pE->iRomNode=aFile;
       
   457 		pE->iVariants=aDir->iVariants;
       
   458 		pE->iDir=aDir;
       
   459 		if (aDir)
       
   460 			aDir->Open();
       
   461 		}
       
   462 	return pE;
       
   463 	}
       
   464 
       
   465 TInt DirEntry::Compare(const SetMember& aMember) const
       
   466 	{
       
   467 	TInt k=Type()-aMember.Type();
       
   468 	if (k!=0)
       
   469 		return k;
       
   470 	DirEntry *entry=(DirEntry *)&aMember;
       
   471 	return (iDir->iIdentifier - entry->iDir->iIdentifier);
       
   472 	}
       
   473 
       
   474 SetMember* DirEntry::Copy() const
       
   475 	{
       
   476 	DirEntry* pE=new DirEntry(*this);
       
   477 	if (pE && pE->iDir)
       
   478 		pE->iDir->Open();
       
   479 	return pE;
       
   480 	}
       
   481 
       
   482 DirEntry::~DirEntry()
       
   483 	{
       
   484 	if (iDir)
       
   485 		iDir->Close();
       
   486 	}
       
   487 
       
   488 // data structure and function for qsort
       
   489 struct SortableEntry 
       
   490 	{
       
   491 	unsigned int iOffset;
       
   492 	Entry* iEntry;
       
   493 	};
       
   494 
       
   495 int compare(const void* left, const void* right)
       
   496 	{
       
   497 	const SortableEntry* le  = (const SortableEntry*)left;
       
   498 	const SortableEntry* re = (const SortableEntry*)right;
       
   499 	if (le->iEntry->IsDir())
       
   500 		{
       
   501 		if (!re->iEntry->IsDir())
       
   502 			return -1;	// dir < file
       
   503 		}
       
   504 	else
       
   505 		{
       
   506 		if (re->iEntry->IsDir())
       
   507 			return +1;	// file > dir
       
   508 		}
       
   509 	// Both the same type of entry, sort by name.
       
   510 	// Sorting the 8-bit data using ASCII folding matches the sort order in terms of 16 bit
       
   511 	// characters provided that 8-bit data is actually CESU-8 rather than UTF-8. The two
       
   512 	// formats differ only when using surrogates (ie unicode values >= 0x10000). UTF-8 encodes
       
   513 	// an entire 32 bit value as a sequence of up to 6 bytes whereas CESU-8 encodes UTF-16
       
   514 	// values independently.
       
   515 	const char* l = (const char*)le->iEntry->Name();
       
   516 	const char* r = (const char*)re->iEntry->Name();
       
   517 	int result, lc, rc;
       
   518 	do	{
       
   519 		lc = *l++;
       
   520 		rc = *r++;
       
   521 		if (lc >= 'A' && lc <= 'Z')
       
   522 			lc += ('a' - 'A');
       
   523 		if (rc >= 'A' && rc <= 'Z')
       
   524 			rc += ('a' - 'A');
       
   525 		result = lc - rc;
       
   526 		} while (lc && result==0);
       
   527 	return result;
       
   528 	}
       
   529 
       
   530 
       
   531 TRomDir* DirEntry::CreateRomEntries(char*& anAddr) const
       
   532 	{
       
   533 	TInt i;
       
   534 	TInt count=iDir->Count();
       
   535 	TInt subdircount=0;
       
   536 	for(i=0; i<count; i++)
       
   537 		{
       
   538 		Entry* pE=(Entry*)&(*iDir)[i];
       
   539 		if (pE->IsDir())
       
   540 			{
       
   541 			subdircount++;
       
   542 			// Recursively build & place the subdirectories
       
   543 			DirEntry *pD=(DirEntry*)pE;
       
   544 			TRomDir *pR=pD->iDir->iRomDir;
       
   545 			if (!pR)
       
   546 				{
       
   547 				pR=pD->CreateRomEntries(anAddr);
       
   548 				pD->iDir->iRomDir=pR;
       
   549 				}
       
   550 			}
       
   551 		}
       
   552 	// Now place & build the TRomDir for this directory
       
   553 	TInt *pS=(TInt*)anAddr;
       
   554 	iDir->iRomDir=(TRomDir*)anAddr;
       
   555 	*pS=0;
       
   556 	anAddr+=sizeof(TInt);
       
   557 
       
   558 	char* offsetbase=anAddr;
       
   559 	SortableEntry* array=new SortableEntry [count];
       
   560 	if (array==0)
       
   561 		{
       
   562 		Print(EError,"Failed to allocate array of SortableEntry\n");
       
   563 		exit(-1);
       
   564 		}
       
   565 
       
   566 	for(i=0; i<count; i++)
       
   567 		{
       
   568 		Entry* pE=(Entry*)&(*iDir)[i];
       
   569 		array[i].iOffset=anAddr-offsetbase;
       
   570 		array[i].iEntry=pE;
       
   571 		TRomEntry *pR=pE->CreateRomEntry(anAddr);
       
   572 		if (pE->IsDir())
       
   573 			{
       
   574 			TRomDir *pD=((DirEntry*)pE)->iDir->iRomDir;
       
   575 			if (pD)
       
   576 				pR->iAddressLin=ActualToRomAddress(pD);
       
   577 			else
       
   578 				Print(EError,"Failed to fix up subdirectory address\n");
       
   579 			}
       
   580 		}
       
   581 	*pS=TInt(anAddr-(char*)pS-sizeof(TInt));
       
   582 
       
   583 	// Emit table of offsets for the subdirs and files in sorted order
       
   584 	if (gSortedRomFs)
       
   585 		{
       
   586 	TInt filecount=count-subdircount;
       
   587 	if (filecount>65535 || subdircount>65535)
       
   588 		{
       
   589 		Print(EError,"Too many files or subdirectories\n");
       
   590 		exit(-1);
       
   591 		}
       
   592 	TUint16* ptr=(TUint16*)anAddr;
       
   593 	*ptr++=(TUint16)subdircount;
       
   594 	*ptr++=(TUint16)filecount;
       
   595 	qsort(array,count,sizeof(SortableEntry),&compare);
       
   596 	for (i=0; i<count; i++)
       
   597 		{
       
   598 		unsigned int scaledOffset = array[i].iOffset>>2;
       
   599 		if ((array[i].iOffset & 3) != 0 || scaledOffset > 65535)
       
   600 			Print(EError, "Bad offset into directory\n");
       
   601 		*ptr++ = (TUint16)scaledOffset;
       
   602 		}
       
   603 	anAddr=(char*)ALIGN4((int)ptr);
       
   604 		}
       
   605 	delete [] array;
       
   606 	return (TRomDir*)pS;
       
   607 	}
       
   608 
       
   609 // class Directory
       
   610 TInt Directory::DirectoryCount=0;
       
   611 Directory::Directory(TInt aMaxCount)
       
   612 	: FiniteSet(aMaxCount), iRomDir(NULL), iAccessCount(1)
       
   613 	{
       
   614 	iIdentifier=Directory::DirectoryCount++;
       
   615 	}
       
   616 
       
   617 Directory* Directory::New(TInt aMaxCount, TVariantList aList)
       
   618 	{
       
   619 	Directory *pD=new Directory(aMaxCount);
       
   620 	if (pD)
       
   621 		{
       
   622 		pD->iVariants=aList;
       
   623 		pD=(Directory*)pD->Construct();
       
   624 		}
       
   625 	return pD;
       
   626 	}
       
   627 
       
   628 Directory::~Directory()
       
   629 	{
       
   630 	TRACE(TDIR,Print(EAlways,"Directory %08x Destruct\n",this));
       
   631 	}
       
   632 
       
   633 void Directory::Open()
       
   634 	{
       
   635 	iAccessCount++;
       
   636 	TRACE(TDIR,Print(EAlways,"Directory %08x Open() access count=%d\n",this,iAccessCount));
       
   637 	}
       
   638 
       
   639 void Directory::Close()
       
   640 	{
       
   641 	TRACE(TDIR,Print(EAlways,"Directory %08x Close() access count=%d\n",this,iAccessCount));
       
   642 	if (--iAccessCount==0)
       
   643 		delete this;
       
   644 	}
       
   645 
       
   646 TInt Directory::Compile(const FiniteSet& aSet)
       
   647 	{
       
   648 	TInt i;
       
   649 	TInt count=aSet.Count();
       
   650 	for(i=0; i<count; i++)
       
   651 		{
       
   652 		Entry *pE=(Entry*)&aSet[i];
       
   653 		if (iVariants<=pE->Variants())
       
   654 			{
       
   655 			Entry *pN=(Entry*)pE->Copy();
       
   656 			if (!pN)
       
   657 				return KErrNoMemory;
       
   658 			pN->Restrict(iVariants);
       
   659 			TInt r=Add(*pN);
       
   660 			if (r==KErrOverflow)
       
   661 				return r;
       
   662 			}
       
   663 		}
       
   664 	return KErrNone;
       
   665 	}
       
   666 
       
   667 TInt Directory::Merge(const Directory& aDir)
       
   668 	{
       
   669 	TInt i;
       
   670 	TInt r=Find(aDir,i);
       
   671 	if (r==KErrNone)
       
   672 		{
       
   673 		((Directory*)iMembers[i])->iVariants.Union(aDir.iVariants);
       
   674 		return KErrAlreadyExists;
       
   675 		}
       
   676 	else if (Insert(aDir,i)==KErrOverflow)
       
   677 		return KErrOverflow;
       
   678 	return KErrNone;
       
   679 	}
       
   680 
       
   681 // class RomFileStructure
       
   682 RomFileStructure::RomFileStructure(TInt aMaxCount)
       
   683 	: FiniteSet(aMaxCount)
       
   684 	{}
       
   685 
       
   686 RomFileStructure::~RomFileStructure()
       
   687 	{
       
   688 	}
       
   689 
       
   690 RomFileStructure* RomFileStructure::New(TInt aMaxCount)
       
   691 	{
       
   692 	RomFileStructure* pS=new RomFileStructure(aMaxCount);
       
   693 	if (pS)
       
   694 		pS=(RomFileStructure*)pS->Construct();
       
   695 	return pS;
       
   696 	}
       
   697 
       
   698 void RomFileStructure::Destroy()
       
   699 	{
       
   700 	}
       
   701 
       
   702 TInt RomFileStructure::ProcessDirectory(TRomNode* aDir)
       
   703 	{
       
   704 	TRACE(TSCRATCH, Print(EAlways, "ProcessDirectory (%08x) %s\n",aDir,aDir->iName));
       
   705 	TRACE(TDIR,Print(EAlways,"ProcessDirectory %s\nInitial:\n",aDir->iName));
       
   706 	TRACE(TDIR,DebugPrint());
       
   707 	TInt dirs=0;
       
   708 	TInt files=0;
       
   709 	aDir->CountDirectory(files,dirs);
       
   710 	TInt maxSize=files+dirs*TVariantList::NumVariants;
       
   711 	TRACE(TDIR,Print(EAlways,"files=%d dirs=%d maxSize=%d\n",files,dirs,maxSize));
       
   712 	RomFileStructure* pS=New(maxSize);
       
   713 	if (!pS)
       
   714 		return KErrNoMemory;
       
   715 	TInt r=aDir->ProcessDirectory(pS);
       
   716 	TRACE(TDIR,Print(EAlways,"FileList:\n"));
       
   717 	TRACE(TDIR,pS->DebugPrint());
       
   718 	Directory* dir[TVariantList::EMaxVariants];
       
   719 	TInt v;
       
   720 	for(v=0; v<TVariantList::NumVariants; v++)
       
   721 		{
       
   722 		TVariantList vList(v);
       
   723 		Directory *pD=Directory::New(files+dirs,vList);
       
   724 		if (!pD)
       
   725 			return KErrNoMemory;
       
   726 		dir[v]=pD;
       
   727 		r=pD->Compile(*pS);
       
   728 		if (r!=KErrNone)
       
   729 			return r;
       
   730 		TRACE(TDIR,Print(EAlways,"Variant %d Directory:\n",v));
       
   731 		TRACE(TDIR,pD->DebugPrint());
       
   732 		}
       
   733 	pS->Close();
       
   734 	Directory *pX=Directory::New(TVariantList::NumVariants,TVariantList());
       
   735 	if (!pX)
       
   736 		return KErrNoMemory;
       
   737 	for(v=0; v<TVariantList::NumVariants; v++)
       
   738 		{
       
   739 		if (dir[v]->Empty())
       
   740 			r=KErrAlreadyExists;
       
   741 		else
       
   742 			r=pX->Merge(*dir[v]);
       
   743 		if (r==KErrAlreadyExists)
       
   744 			{
       
   745 			dir[v]->Close();
       
   746 			dir[v]=NULL;
       
   747 			}
       
   748 		else if (r!=KErrNone)
       
   749 			return r;
       
   750 		}
       
   751 	TRACE(TDIR,Print(EAlways,"Final Directories:\n",v));
       
   752 	TRACE(TDIR,pX->DebugPrint());
       
   753 	TInt count=pX->Count();
       
   754 	TInt i;
       
   755 	for(i=0; i<count; i++)
       
   756 		{
       
   757 		Directory* pD=(Directory*)&(*pX)[i];
       
   758 		DirEntry* pE=DirEntry::New(aDir,pD);
       
   759 		if (!pE)
       
   760 			return KErrNoMemory;
       
   761 		r=Add(*pE);	// accumulate into the caller
       
   762 		if (r==KErrOverflow)
       
   763 			return r;
       
   764 		}
       
   765 	pX->Close();
       
   766 	return KErrNone;
       
   767 	}
       
   768 
       
   769 
       
   770 // DEBUG
       
   771 
       
   772 void FileEntry::DebugPrint() const
       
   773 	{
       
   774 	Print(EAlways,"FileEntry %08x %08x %s\n",iRomNode,iVariants.Mask(),iRomNode->iName);
       
   775 	}
       
   776 
       
   777 void DirEntry::DebugPrint() const
       
   778 	{
       
   779 	Print(EAlways,"DirEntry %08x %08x %08x %s\n",iRomNode,iVariants.Mask(),iDir,iRomNode->iName);
       
   780 	}
       
   781 
       
   782 void FiniteSet::DebugPrint() const
       
   783 	{
       
   784 	if (Count()==0)
       
   785 		Print(EAlways,"FiniteSet 0\n");
       
   786 	else
       
   787 		{
       
   788 		Print(EAlways,"FiniteSet %d {\n",Count());
       
   789 		TInt i;
       
   790 		for (i=0; i<Count(); i++)
       
   791 			{
       
   792 			iMembers[i]->DebugPrint();
       
   793 			}
       
   794 		Print(EAlways,"}\n");
       
   795 		}
       
   796 	}
       
   797 
       
   798 void Directory::DebugPrint() const
       
   799 	{
       
   800 	Print(EAlways,"Directory %08x %08x\n",iVariants.Mask(),iRomDir);
       
   801 	FiniteSet::DebugPrint();
       
   802 	}
       
   803 
       
   804 
       
   805 
       
   806 
       
   807