|
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 |