|
1 // Copyright (c) 1996-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". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
|
17 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
|
18 //!! |
|
19 //!! WARNING!! DO NOT edit this file !! '\sfat' component is obsolete and is not being used. '\sfat32'replaces it |
|
20 //!! |
|
21 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
|
22 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
|
23 |
|
24 |
|
25 #include "sl_std.h" |
|
26 |
|
27 //----------------------------------------------------------------------------- |
|
28 /** |
|
29 Removes trailing dots from aName. |
|
30 @return new string descriptor that may have its length adjusted |
|
31 */ |
|
32 TPtrC RemoveTrailingDots(const TDesC& aName) |
|
33 { |
|
34 TInt len = aName.Length(); |
|
35 |
|
36 while(len > 0) |
|
37 { |
|
38 if(aName[len-1] == '.') |
|
39 len--; |
|
40 else |
|
41 break; |
|
42 } |
|
43 |
|
44 TPtrC ptrNoDots(aName.Ptr(), len); |
|
45 return ptrNoDots; |
|
46 } |
|
47 |
|
48 |
|
49 TUint32 Log2(TUint32 aVal) |
|
50 { |
|
51 __ASSERT_COMPILE(sizeof(TUint32) == 4); |
|
52 ASSERT(aVal); |
|
53 |
|
54 TUint32 bitPos=31; |
|
55 |
|
56 if(!(aVal >> 16)) {bitPos-=16; aVal<<=16;} |
|
57 if(!(aVal >> 24)) {bitPos-=8; aVal<<=8 ;} |
|
58 if(!(aVal >> 28)) {bitPos-=4; aVal<<=4 ;} |
|
59 if(!(aVal >> 30)) {bitPos-=2; aVal<<=2 ;} |
|
60 if(!(aVal >> 31)) {bitPos-=1;} |
|
61 |
|
62 return bitPos; |
|
63 } |
|
64 |
|
65 |
|
66 TTime DosTimeToTTime(TInt aDosTime,TInt aDosDate) |
|
67 // |
|
68 // Deciphers the dos time/date entry information and converts to TTime |
|
69 // |
|
70 { |
|
71 TInt secMask=0x1F; |
|
72 TInt minMask=0x07E0; |
|
73 TInt hrMask=0xF800; |
|
74 TInt dayMask=0x1F; |
|
75 TInt monthMask=0x01E0; |
|
76 TInt yearMask=0xFE00; |
|
77 |
|
78 TInt secs=(aDosTime&secMask)*2; |
|
79 TInt mins=(aDosTime&minMask)>>5; |
|
80 TInt hrs=(aDosTime&hrMask)>>11; |
|
81 TInt days=(aDosDate&dayMask)-1; |
|
82 TMonth months=(TMonth)(((aDosDate&monthMask)>>5)-1); |
|
83 TInt years=((aDosDate&yearMask)>>9)+1980; |
|
84 |
|
85 TDateTime datetime; |
|
86 TInt ret=datetime.Set(years,months,days,hrs,mins,secs,0); |
|
87 if (ret==KErrNone) |
|
88 return(TTime(datetime)); |
|
89 return(TTime(0)); |
|
90 } |
|
91 |
|
92 TInt DosTimeFromTTime(const TTime& aTime) |
|
93 // |
|
94 // Converts a TTime to a dos time |
|
95 // |
|
96 { |
|
97 TDateTime dateTime=aTime.DateTime(); |
|
98 TInt dosSecs=dateTime.Second()/2; |
|
99 TInt dosMins=dateTime.Minute()<<5; |
|
100 TInt dosHrs=dateTime.Hour()<<11; |
|
101 return dosSecs|dosMins|dosHrs; |
|
102 } |
|
103 |
|
104 TInt DosDateFromTTime(const TTime& aTime) |
|
105 // |
|
106 // Converts a TTime to a dos date |
|
107 // |
|
108 { |
|
109 |
|
110 TDateTime dateTime=aTime.DateTime(); |
|
111 TInt dosDays=dateTime.Day()+1; |
|
112 TInt dosMonths=(dateTime.Month()+1)<<5; |
|
113 TInt dosYears=(dateTime.Year()-1980)<<9; |
|
114 return dosDays|dosMonths|dosYears; |
|
115 } |
|
116 |
|
117 TBuf8<12> DosNameToStdFormat(const TDesC8& aDosName) |
|
118 // |
|
119 // Converts xxx.yyy to standard format aaaaaaaayyy |
|
120 // |
|
121 { |
|
122 |
|
123 __ASSERT_DEBUG(aDosName.Length()>=0 && aDosName.Length()<=12,Fault(EFatBadDosFormatName)); |
|
124 TBuf8<12> result; |
|
125 Mem::Fill((TUint8*)result.Ptr(),result.MaxSize(),' '); |
|
126 TInt dotPos=aDosName.Locate('.'); |
|
127 if (dotPos==KErrNotFound) |
|
128 { |
|
129 result=aDosName; |
|
130 result.SetLength(11); |
|
131 return result; |
|
132 } |
|
133 result=aDosName.Left(dotPos); |
|
134 result.SetLength(11); |
|
135 TPtr8 ext(&result[8],3); |
|
136 ext=aDosName.Right(aDosName.Length()-dotPos-1); |
|
137 return result; |
|
138 } |
|
139 |
|
140 TBuf8<12> DosNameFromStdFormat(const TDesC8& aStdFormatName) |
|
141 // |
|
142 // Converts aaaaaaaayyy to dos name format xxx.yyy |
|
143 // |
|
144 { |
|
145 |
|
146 __ASSERT_DEBUG(aStdFormatName.Length()==11,Fault(EFatBadStdFormatName)); |
|
147 TBuf8<12> result; |
|
148 TInt nameLen=aStdFormatName.Locate(' '); |
|
149 if (nameLen>8 || nameLen==KErrNotFound) |
|
150 nameLen=8; |
|
151 result=aStdFormatName.Left(nameLen); |
|
152 TPtrC8 ext(&aStdFormatName[8],3); |
|
153 TInt extLen=ext.Locate(' '); |
|
154 if (extLen) |
|
155 result.Append(TChar('.')); |
|
156 if (extLen==KErrNotFound) |
|
157 extLen=3; |
|
158 result.Append(ext.Left(extLen)); |
|
159 if(result.Length() && result[0]==0x05 ) |
|
160 { |
|
161 result[0]=0xE5; |
|
162 } |
|
163 return result; |
|
164 } |
|
165 |
|
166 TInt NumberOfVFatEntries(TInt aNameLength) |
|
167 // |
|
168 // Return the number of VFat entries required to describe a filename of length aNameLength |
|
169 // |
|
170 { |
|
171 TInt numberOfEntries=0; |
|
172 if (aNameLength%KMaxVFatEntryName) |
|
173 aNameLength++; // Include a zero terminator |
|
174 // If aNameLength is a exact multiple of KMaxVFatEntryName, don't bother |
|
175 // with a zero terminator - it just adds an unnecessary directory entry |
|
176 |
|
177 numberOfEntries=(1+(aNameLength/KMaxVFatEntryName)); |
|
178 |
|
179 if (aNameLength%KMaxVFatEntryName) |
|
180 numberOfEntries++; |
|
181 |
|
182 return(numberOfEntries); |
|
183 } |
|
184 |
|
185 //----------------------------------------------------------------------------- |
|
186 /** |
|
187 Calculate DOS short name checksum |
|
188 @param aShortName short name descriptor (must be at least 11 bytes long) |
|
189 @return checksum |
|
190 */ |
|
191 TUint8 CalculateShortNameCheckSum(const TDesC8& aShortName) |
|
192 { |
|
193 |
|
194 ASSERT(aShortName.Length() >= KFatDirNameSize); |
|
195 const TUint8* pName = aShortName.Ptr(); |
|
196 |
|
197 const TUint32 w0 = ((const TUint32*)pName)[0]; |
|
198 const TUint32 w1 = ((const TUint32*)pName)[1]; |
|
199 |
|
200 TUint32 chkSum = w0 & 0xFF; |
|
201 |
|
202 chkSum = (TUint8)(((chkSum<<7) | (chkSum>>1)) + ((w0 << 16) >> 24)); |
|
203 chkSum = (TUint8)(((chkSum<<7) | (chkSum>>1)) + ((w0 << 8) >> 24)); |
|
204 chkSum = (TUint8)(((chkSum<<7) | (chkSum>>1)) + ( w0 >> 24)); |
|
205 |
|
206 chkSum = (TUint8)(((chkSum<<7) | (chkSum>>1)) + (w1) & 0xFF); |
|
207 chkSum = (TUint8)(((chkSum<<7) | (chkSum>>1)) + ((w1 << 16) >> 24)); |
|
208 chkSum = (TUint8)(((chkSum<<7) | (chkSum>>1)) + ((w1 << 8) >> 24)); |
|
209 chkSum = (TUint8)(((chkSum<<7) | (chkSum>>1)) + ( w1 >> 24)); |
|
210 |
|
211 chkSum = (TUint8)(((chkSum<<7) | (chkSum>>1)) + pName[8]); |
|
212 chkSum = (TUint8)(((chkSum<<7) | (chkSum>>1)) + pName[9]); |
|
213 chkSum = (TUint8)(((chkSum<<7) | (chkSum>>1)) + pName[10]); |
|
214 |
|
215 return (TUint8)chkSum; |
|
216 } |
|
217 |
|
218 //----------------------------------------------------------------------------- |
|
219 |
|
220 const TUint32 K_FFFF = 0xFFFFFFFF; //-- all one bits, beware rigth shifts of signed integers! |
|
221 |
|
222 |
|
223 RBitVector::RBitVector() |
|
224 :iNumBits(0), ipData(NULL), iNumWords(0) |
|
225 { |
|
226 } |
|
227 |
|
228 |
|
229 RBitVector::~RBitVector() |
|
230 { |
|
231 Close(); |
|
232 } |
|
233 |
|
234 /** |
|
235 Panics. |
|
236 @param aPanicCode a panic code |
|
237 */ |
|
238 void RBitVector::Panic(TPanicCode aPanicCode) const |
|
239 { |
|
240 _LIT(KPanicCat,"RBitVector"); |
|
241 User::Panic(KPanicCat, aPanicCode); |
|
242 } |
|
243 |
|
244 /** explicitly closes the object and deallocates memory */ |
|
245 void RBitVector::Close() |
|
246 { |
|
247 iNumBits = 0; |
|
248 iNumWords =0; |
|
249 User::Free(ipData); |
|
250 ipData = NULL; |
|
251 } |
|
252 |
|
253 //----------------------------------------------------------------------------- |
|
254 |
|
255 /** |
|
256 Comparison perator. |
|
257 @param aRhs a vector to compate with. |
|
258 @panic ESizeMismatch in the case of different vector sizes |
|
259 */ |
|
260 TBool RBitVector::operator==(const RBitVector& aRhs) const |
|
261 { |
|
262 __ASSERT_ALWAYS(ipData, Panic(ENotInitialised)); |
|
263 __ASSERT_ALWAYS(iNumBits == aRhs.iNumBits, Panic(ESizeMismatch)); |
|
264 |
|
265 |
|
266 if(!iNumBits) |
|
267 return ETrue; //-- comparing 0-lenght arrays |
|
268 |
|
269 if(this == &aRhs) |
|
270 return ETrue; //-- comparing with itself |
|
271 |
|
272 if(iNumWords >= 1) |
|
273 { |
|
274 const TUint32 cntBytes = (iNumBits >> 5) << 2; //-- bytes to compare |
|
275 if(memcompare((const TUint8*)ipData, cntBytes, (const TUint8*)aRhs.ipData, cntBytes)) |
|
276 return EFalse; |
|
277 } |
|
278 |
|
279 const TUint32 bitsRest = iNumBits & 0x1F; |
|
280 if(bitsRest) |
|
281 { |
|
282 const TUint32 mask = K_FFFF >> (32-bitsRest); |
|
283 return ( (ipData[iNumWords-1] & mask) == (aRhs.ipData[iNumWords-1] & mask) ); |
|
284 } |
|
285 |
|
286 return ETrue; |
|
287 } |
|
288 |
|
289 TBool RBitVector::operator!=(const RBitVector& aRhs) const |
|
290 { |
|
291 return ! ((*this) == aRhs); |
|
292 } |
|
293 |
|
294 //----------------------------------------------------------------------------- |
|
295 |
|
296 /** The same as Create(), but leaves on error */ |
|
297 void RBitVector::CreateL(TUint32 aNumBits) |
|
298 { |
|
299 User::LeaveIfError(Create(aNumBits)); |
|
300 } |
|
301 |
|
302 |
|
303 /** |
|
304 Create the vector with the size of aNumBits bits. |
|
305 @return system-wide error codes: |
|
306 KErrNoMemory unable to allocate sufficient amount of memory for the array |
|
307 KErrInUse an attempt to call Create() for non-empty vector. Close it first. |
|
308 KErrArgument invalid aNumBits value == 0 |
|
309 */ |
|
310 TInt RBitVector::Create(TUint32 aNumBits) |
|
311 { |
|
312 |
|
313 if(ipData) |
|
314 return KErrInUse; //-- array is already in use. Close it first. |
|
315 |
|
316 if(!aNumBits) |
|
317 return KErrArgument; |
|
318 |
|
319 //-- memory is allocated by word (32 bit) quiantities |
|
320 const TUint32 numWords = (aNumBits >> 5) + ((aNumBits & 0x1F) > 0 ? 1:0); |
|
321 ipData = (TUint32*)User::AllocZ(numWords << 2); |
|
322 |
|
323 if(!ipData) |
|
324 return KErrNoMemory; |
|
325 |
|
326 iNumBits = aNumBits; |
|
327 iNumWords = numWords; |
|
328 |
|
329 return KErrNone; |
|
330 } |
|
331 |
|
332 |
|
333 /** |
|
334 Fill a bit vector with a given bit value |
|
335 @param aVal a bit value |
|
336 */ |
|
337 void RBitVector::Fill(TBool aVal) |
|
338 { |
|
339 __ASSERT_ALWAYS(ipData, Panic(ENotInitialised)); |
|
340 memset(ipData, (aVal ? 0xFF : 0x00), iNumWords << 2); |
|
341 } |
|
342 |
|
343 /** Invert all bits in a bit vector */ |
|
344 void RBitVector::Invert() |
|
345 { |
|
346 __ASSERT_ALWAYS(ipData, Panic(ENotInitialised)); |
|
347 for(TUint32 i=0; i<iNumWords; ++i) |
|
348 ipData[i] ^= K_FFFF; |
|
349 } |
|
350 |
|
351 |
|
352 /** |
|
353 Perform "And" operation between 2 vectors. They shall be the same size. |
|
354 @param aRhs a vector from the right hand side |
|
355 @panic ESizeMismatch in the case of different vector sizes |
|
356 */ |
|
357 void RBitVector::And(const RBitVector& aRhs) |
|
358 { |
|
359 __ASSERT_ALWAYS(ipData, Panic(ENotInitialised)); |
|
360 __ASSERT_ALWAYS(iNumBits == aRhs.iNumBits, Panic(ESizeMismatch)); |
|
361 for(TUint32 i=0; i<iNumWords; ++i) |
|
362 { |
|
363 ipData[i] &= aRhs.ipData[i]; |
|
364 } |
|
365 } |
|
366 |
|
367 /** |
|
368 Perform "Or" operation between 2 vectors. They shall be the same size. |
|
369 @param aRhs a vector from the right hand side |
|
370 @panic ESizeMismatch in the case of different vector sizes |
|
371 */ |
|
372 void RBitVector::Or(const RBitVector& aRhs) |
|
373 { |
|
374 __ASSERT_ALWAYS(ipData, Panic(ENotInitialised)); |
|
375 __ASSERT_ALWAYS(iNumBits == aRhs.iNumBits, Panic(ESizeMismatch)); |
|
376 for(TUint32 i=0; i<iNumWords; ++i) |
|
377 { |
|
378 ipData[i] |= aRhs.ipData[i]; |
|
379 } |
|
380 } |
|
381 |
|
382 /** |
|
383 Perform "Xor" operation between 2 vectors. They shall be the same size. |
|
384 @param aRhs a vector from the right hand side |
|
385 @panic ESizeMismatch in the case of different vector sizes |
|
386 */ |
|
387 void RBitVector::Xor(const RBitVector& aRhs) |
|
388 { |
|
389 __ASSERT_ALWAYS(ipData, Panic(ENotInitialised)); |
|
390 __ASSERT_ALWAYS(iNumBits == aRhs.iNumBits, Panic(ESizeMismatch)); |
|
391 for(TUint32 i=0; i<iNumWords; ++i) |
|
392 { |
|
393 ipData[i] ^= aRhs.ipData[i]; |
|
394 } |
|
395 } |
|
396 |
|
397 //----------------------------------------------------------------------------- |
|
398 /** |
|
399 Fill a range from bit number "aIndexFrom" to "aIndexTo" inclusively with the value of aVal |
|
400 |
|
401 @param aIndexFrom start bit number (inclusive) |
|
402 @param aIndexTo end bit number (inclusive) |
|
403 @param aVal the value to be used to fill the range (0s or 1s) |
|
404 */ |
|
405 void RBitVector::Fill(TUint32 aIndexFrom, TUint32 aIndexTo, TBool aVal) |
|
406 { |
|
407 __ASSERT_ALWAYS(ipData, Panic(ENotInitialised)); |
|
408 |
|
409 //-- swap indexes if they are not in order |
|
410 if(aIndexFrom > aIndexTo) |
|
411 { |
|
412 const TUint32 tmp = aIndexFrom; |
|
413 aIndexFrom = aIndexTo; |
|
414 aIndexTo = tmp; |
|
415 } |
|
416 |
|
417 __ASSERT_ALWAYS((aIndexFrom < iNumBits) && (aIndexTo < iNumBits), Panic(EIndexOutOfRange)); |
|
418 |
|
419 const TUint32 wordStart = WordNum(aIndexFrom); |
|
420 const TUint32 wordTo = WordNum(aIndexTo); |
|
421 |
|
422 if(aVal) |
|
423 {//-- filling a range with '1' |
|
424 |
|
425 TUint32 shift = BitInWord(aIndexFrom); |
|
426 const TUint32 mask1 = (K_FFFF >> shift) << shift; |
|
427 |
|
428 TUint32 mask2 = K_FFFF; |
|
429 shift = 1+BitInWord(aIndexTo); |
|
430 if(shift < 32) |
|
431 { |
|
432 mask2 = ~((mask2 >> shift) << shift); |
|
433 } |
|
434 |
|
435 if(wordTo == wordStart) |
|
436 {//-- a special case, filling is in the same word |
|
437 ipData[wordStart] |= (mask1 & mask2); |
|
438 } |
|
439 else |
|
440 { |
|
441 ipData[wordStart] |= mask1; |
|
442 ipData[wordTo] |= mask2; |
|
443 |
|
444 const TUint32 wholeWordsBetween = wordTo - wordStart - 1; //-- whole words that can be bulk filled |
|
445 |
|
446 if(wholeWordsBetween) |
|
447 memset(ipData+wordStart+1, 0xFF, wholeWordsBetween << 2); |
|
448 |
|
449 } |
|
450 } |
|
451 else |
|
452 {//-- filling a range with '0' |
|
453 |
|
454 //-- if you need this functionality, remove the panic and uncomment the code below. |
|
455 |
|
456 Panic(ENotImplemented); |
|
457 |
|
458 /* |
|
459 TUint32 shift = BitInWord(aIndexFrom); |
|
460 const TUint32 mask1 = ~((K_FFFF >> shift) << shift); |
|
461 |
|
462 TUint32 mask2 = 0; |
|
463 shift = 1+BitInWord(aIndexTo); |
|
464 if(shift < 32) |
|
465 { |
|
466 mask2 = ((K_FFFF >> shift) << shift); |
|
467 } |
|
468 |
|
469 if(wordTo == wordStart) |
|
470 {//-- a special case, filling is in the same word |
|
471 ipData[wordStart] &= (mask1 | mask2); |
|
472 } |
|
473 else |
|
474 { |
|
475 ipData[wordStart] &= mask1; |
|
476 ipData[wordTo] &= mask2; |
|
477 |
|
478 const TUint32 wholeWordsBetween = wordTo - wordStart - 1; //-- whole words that can be bulk filled |
|
479 |
|
480 if(wholeWordsBetween) |
|
481 memset(ipData+wordStart+1, 0x00, wholeWordsBetween << 2); |
|
482 |
|
483 } |
|
484 */ |
|
485 } |
|
486 |
|
487 } |
|
488 |
|
489 //----------------------------------------------------------------------------- |
|
490 |
|
491 /** |
|
492 Search for a specified bit value ('0' or '1') in the vector from the given position. |
|
493 @param aStartPos zero-based index; from this position the search will start. This position isn't included to the search. |
|
494 On return may contain a new position if the specified bit is found in specified direction. |
|
495 @param aBitVal zero or non-zero bit to search. |
|
496 @param aDir Specifies the search direction |
|
497 |
|
498 @return ETrue if the specified bit value is found; aStartPos gets updated. |
|
499 EFalse otherwise. |
|
500 |
|
501 */ |
|
502 TBool RBitVector::Find(TUint32& aStartPos, TBool aBitVal, TFindDirection aDir) const |
|
503 { |
|
504 __ASSERT_ALWAYS(aStartPos < iNumBits, Panic(EIndexOutOfRange)); |
|
505 ASSERT(iNumWords && ipData); |
|
506 |
|
507 switch(aDir) |
|
508 { |
|
509 case ERight: //-- Search from the given position to the right |
|
510 return FindToRight(aStartPos, aBitVal); |
|
511 |
|
512 case ELeft: //-- Search from the given position to the left (towards lower index) |
|
513 return FindToLeft(aStartPos, aBitVal); |
|
514 |
|
515 case ENearestL: //-- Search for the nearest value in both directions starting from left |
|
516 return FindNearest(aStartPos, aBitVal, ETrue); |
|
517 |
|
518 case ENearestR: //-- Search for the nearest value in both directions starting from right |
|
519 return FindNearest(aStartPos, aBitVal, EFalse); |
|
520 |
|
521 default: |
|
522 Panic(EWrondFindDirection); |
|
523 return EFalse; |
|
524 |
|
525 }; |
|
526 |
|
527 } |
|
528 |
|
529 //----------------------------------------------------------------------------- |
|
530 /** |
|
531 Internal method to look for a given bit value in the right direction. |
|
532 see TBool RBitVector::Find(...) |
|
533 */ |
|
534 TBool RBitVector::FindToRight(TUint32& aStartPos, TBool aBitVal) const |
|
535 { |
|
536 if(aStartPos >= iNumBits-1) |
|
537 return EFalse; //-- no way to the right |
|
538 |
|
539 const TUint32 startPos = aStartPos+1; |
|
540 const TUint32 fInvert = aBitVal ? 0 : K_FFFF; //-- invert everything if we are looking for '0' bit |
|
541 |
|
542 TUint32 wordNum = WordNum(startPos); |
|
543 TUint32 val = ipData[wordNum] ^ fInvert; |
|
544 |
|
545 if(wordNum == iNumWords-1) |
|
546 {//-- process the last word in the array, some higher bits might not belong to the bit vector |
|
547 val = MaskLastWord(val); |
|
548 } |
|
549 |
|
550 const TUint32 shift = BitInWord(startPos); |
|
551 val = (val >> shift) << shift; //-- mask unused low bits |
|
552 |
|
553 if(val) |
|
554 {//-- there are '1' bits in the current word |
|
555 goto found; |
|
556 } |
|
557 else |
|
558 {//-- search in higher words |
|
559 wordNum++; |
|
560 |
|
561 while(iNumWords-wordNum > 1) |
|
562 { |
|
563 val = ipData[wordNum] ^ fInvert; |
|
564 if(val) |
|
565 goto found; |
|
566 |
|
567 wordNum++; |
|
568 } |
|
569 |
|
570 if(wordNum == iNumWords-1) |
|
571 {//-- process the last word in the array, some higher bith might not belong to the bit vector |
|
572 val = ipData[wordNum] ^ fInvert; |
|
573 val = MaskLastWord(val); |
|
574 |
|
575 if(val) |
|
576 goto found; |
|
577 } |
|
578 } |
|
579 |
|
580 return EFalse; //-- haven't found anything |
|
581 |
|
582 found: |
|
583 |
|
584 val &= (~val+1); //-- select rightmost bit |
|
585 aStartPos = (wordNum << 5)+Log2(val); |
|
586 return ETrue; |
|
587 } |
|
588 |
|
589 |
|
590 //----------------------------------------------------------------------------- |
|
591 |
|
592 /** |
|
593 Internal method to look for a given bit value in the left direction. |
|
594 see TBool RBitVector::Find(...) |
|
595 */ |
|
596 TBool RBitVector::FindToLeft(TUint32& aStartPos, TBool aBitVal) const |
|
597 { |
|
598 if(!aStartPos) |
|
599 return EFalse; //-- no way to the left |
|
600 |
|
601 const TUint32 startPos=aStartPos-1; |
|
602 const TUint32 fInvert = aBitVal ? 0 : K_FFFF; //-- invert everything if we are looking for '0' bit |
|
603 |
|
604 TUint32 wordNum = WordNum(startPos); |
|
605 TUint32 val = ipData[wordNum] ^ fInvert; |
|
606 |
|
607 const TUint32 shift = 31-(BitInWord(startPos)); |
|
608 val = (val << shift) >> shift; //-- mask unused high bits |
|
609 |
|
610 if(val) |
|
611 {//-- there are '1' bits in the current word |
|
612 goto found; |
|
613 } |
|
614 else |
|
615 {//-- search in the lower words |
|
616 while(wordNum) |
|
617 { |
|
618 wordNum--; |
|
619 val=ipData[wordNum] ^ fInvert; |
|
620 if(val) |
|
621 goto found; |
|
622 } |
|
623 } |
|
624 |
|
625 return EFalse; //-- nothing found |
|
626 |
|
627 found: |
|
628 aStartPos = (wordNum << 5)+Log2(val); |
|
629 return ETrue; |
|
630 } |
|
631 |
|
632 //----------------------------------------------------------------------------- |
|
633 |
|
634 /** |
|
635 Internal method to look for a given bit value in the both directions. |
|
636 see TBool RBitVector::Find(...) |
|
637 */ |
|
638 TBool RBitVector::FindNearest(TUint32& aStartPos, TBool aBitVal, TBool aToLeft) const |
|
639 { |
|
640 if(iNumBits < 2) |
|
641 return EFalse; |
|
642 |
|
643 if(aStartPos == 0) |
|
644 return FindToRight(aStartPos, aBitVal); |
|
645 |
|
646 if(aStartPos == iNumBits-1) |
|
647 return FindToLeft(aStartPos, aBitVal); |
|
648 |
|
649 |
|
650 const TUint32 fInvert = aBitVal ? 0 : K_FFFF; //-- invert everything if we are looking for '0' bit |
|
651 |
|
652 TUint32 wordNum = WordNum(aStartPos); |
|
653 TUint32 l_Idx; //-- index of the word to the left |
|
654 TUint32 r_Idx; //-- index of the word to the right |
|
655 |
|
656 l_Idx = r_Idx = wordNum; |
|
657 |
|
658 TBool noWayLeft = (wordNum == 0); //-- if we are in the first word |
|
659 TBool noWayRight = (wordNum == iNumWords-1); //-- if we are in the last word |
|
660 |
|
661 //-- look in the current word first |
|
662 TUint32 val = ipData[wordNum] ^ fInvert; |
|
663 |
|
664 if(noWayRight) |
|
665 { //-- this is the last word in the array, mask unused high bits in the last word |
|
666 val = MaskLastWord(val); |
|
667 } |
|
668 |
|
669 const TUint32 bitPos = aStartPos & 0x1F; |
|
670 val &= ~(1<<bitPos); //-- mask the bit at current position |
|
671 |
|
672 if(val == 0) |
|
673 {//-- no '1' bits in the current word |
|
674 noWayLeft = ItrLeft(l_Idx); |
|
675 noWayRight = ItrRight(r_Idx); |
|
676 } |
|
677 else if(bitPos == 0) |
|
678 { |
|
679 noWayLeft = ItrLeft(l_Idx); //-- move to the previous word |
|
680 } |
|
681 else if(bitPos == 31) |
|
682 { |
|
683 noWayRight = ItrRight(r_Idx); //-- move to the next word |
|
684 } |
|
685 else |
|
686 {//-- look in the current word, in both halves to the left and right from the start position |
|
687 |
|
688 const TUint32 shift1 = 32-bitPos; |
|
689 const TUint32 partLo = (val << shift1) >> shift1; //-- towards lower bits |
|
690 |
|
691 const TUint32 shift2 = bitPos+1; |
|
692 const TUint32 partHi = (val >> shift2) << shift2; //-- towards higher bits |
|
693 |
|
694 |
|
695 if(partLo && !partHi) //-- only lower part has '1' bits |
|
696 { |
|
697 aStartPos = (wordNum << 5)+Log2(partLo); |
|
698 return ETrue; |
|
699 } |
|
700 else if(!partLo && partHi) //-- only higher part has '1' bits |
|
701 { |
|
702 aStartPos = (wordNum << 5)+Log2( (partHi & (~partHi+1)) ); |
|
703 return ETrue; |
|
704 } |
|
705 else if(partLo && partHi) //-- both parts contain '1' bits, select the nearest one |
|
706 { |
|
707 const TUint32 posL = (wordNum << 5)+Log2(partLo); |
|
708 const TUint32 posR = (wordNum << 5)+Log2( (partHi & (~partHi+1)) ); |
|
709 |
|
710 ASSERT(aStartPos > posL); |
|
711 ASSERT(posR > aStartPos); |
|
712 const TUint32 distL = aStartPos-posL; |
|
713 const TUint32 distR = posR-aStartPos; |
|
714 |
|
715 if(distL < distR) |
|
716 { |
|
717 aStartPos = posL; |
|
718 return ETrue; |
|
719 } |
|
720 else if(distL > distR) |
|
721 { |
|
722 aStartPos = posR; |
|
723 return ETrue; |
|
724 } |
|
725 else |
|
726 {//-- distL == distR, take into account search priority |
|
727 aStartPos = aToLeft ? posL : posR; |
|
728 return ETrue; |
|
729 } |
|
730 } |
|
731 else //-- (!partLo && !partHi), nothing in the current word |
|
732 { |
|
733 ASSERT(0); |
|
734 } |
|
735 |
|
736 }// if(bitPos > 0 && bitPos < 31) |
|
737 |
|
738 //-- now we are processing separate words from both sides of the search position |
|
739 for(;;) |
|
740 { |
|
741 TUint32 wL = ipData[l_Idx] ^ fInvert; |
|
742 TUint32 wR = ipData[r_Idx] ^ fInvert; |
|
743 if(r_Idx == iNumWords-1) |
|
744 { //-- this is the last word in the array, mask unused high bits in the last word |
|
745 wR = MaskLastWord(wR); |
|
746 } |
|
747 |
|
748 if(wL && !wR) |
|
749 { |
|
750 aStartPos = (l_Idx << 5)+Log2(wL); |
|
751 return ETrue; |
|
752 } |
|
753 else if(!wL && wR) |
|
754 { |
|
755 aStartPos = (r_Idx << 5)+Log2( (wR & (~wR+1)) ); |
|
756 return ETrue; |
|
757 } |
|
758 else if(wL && wR) |
|
759 { |
|
760 const TUint32 posL = (l_Idx << 5)+Log2(wL); |
|
761 const TUint32 posR = (r_Idx << 5)+Log2( (wR & (~wR+1)) ); |
|
762 |
|
763 ASSERT(aStartPos > posL); |
|
764 ASSERT(posR > aStartPos); |
|
765 const TUint32 distL = aStartPos-posL; |
|
766 const TUint32 distR = posR-aStartPos; |
|
767 |
|
768 if(distL < distR) |
|
769 { |
|
770 aStartPos = posL; |
|
771 return ETrue; |
|
772 } |
|
773 else if(distL > distR) |
|
774 { |
|
775 aStartPos = posR; |
|
776 return ETrue; |
|
777 } |
|
778 else |
|
779 {//-- distL == distR, take into account search priority |
|
780 aStartPos = aToLeft ? posL : posR; |
|
781 return ETrue; |
|
782 } |
|
783 |
|
784 }//else if(wL && wR) |
|
785 |
|
786 |
|
787 if(noWayLeft) |
|
788 { |
|
789 aStartPos = r_Idx << 5; |
|
790 return FindToRight(aStartPos, aBitVal); |
|
791 } |
|
792 else |
|
793 { |
|
794 noWayLeft = ItrLeft(l_Idx); |
|
795 } |
|
796 |
|
797 if(noWayRight) |
|
798 { |
|
799 aStartPos = l_Idx << 5; |
|
800 return FindToLeft(aStartPos, aBitVal); |
|
801 } |
|
802 else |
|
803 { |
|
804 noWayRight = ItrRight(r_Idx); |
|
805 } |
|
806 |
|
807 }//for(;;) |
|
808 |
|
809 //return EFalse; |
|
810 } |
|
811 |
|
812 //----------------------------------------------------------------------------- |
|
813 /** |
|
814 Find out if two vectors are different. |
|
815 |
|
816 @param aRhs vector to compare with |
|
817 @param aDiffIndex if there is a differene, here will be the number of the first different bit |
|
818 @return ETrue if vectors differ, EFalse, if they are identical. |
|
819 */ |
|
820 TBool RBitVector::Diff(const RBitVector& aRhs, TUint32& aDiffIndex) const |
|
821 { |
|
822 __ASSERT_ALWAYS(ipData, Panic(ENotInitialised)); |
|
823 __ASSERT_ALWAYS(iNumBits == aRhs.iNumBits, Panic(ESizeMismatch)); |
|
824 ASSERT(iNumWords > 0); |
|
825 |
|
826 TUint32 diffWord=0; |
|
827 TUint32 wordNum=0; |
|
828 |
|
829 //-- compare all but the last word in the array |
|
830 for(wordNum=0; wordNum < iNumWords-1; ++wordNum) |
|
831 { |
|
832 diffWord = ipData[wordNum] ^ aRhs.ipData[wordNum]; |
|
833 if(diffWord) |
|
834 break; //-- found difference |
|
835 } |
|
836 |
|
837 //-- process the last word in the array |
|
838 if(!diffWord) |
|
839 { |
|
840 diffWord = MaskLastWord(ipData[wordNum]) ^ MaskLastWord(aRhs.ipData[wordNum]); |
|
841 } |
|
842 |
|
843 if(!diffWord) |
|
844 return EFalse; //-- vectors are the same |
|
845 |
|
846 //-- calculate the position of the bit that different. |
|
847 diffWord &= (~diffWord+1); //-- select rightmost bit |
|
848 aDiffIndex = (wordNum << 5)+Log2(diffWord); |
|
849 |
|
850 return ETrue; |
|
851 } |
|
852 //----------------------------------------------------------------------------- |
|
853 |
|
854 /** |
|
855 Iterate to the left (towards lower index) in the array of words ipData |
|
856 |
|
857 @param aIdx index within ipData array to be decremented; if it's possible to move left, it will be decreased |
|
858 @return ETrue if there is no way left i.e. aIdx is 0. EFalse otherwise and aIdx decreased. |
|
859 */ |
|
860 TBool RBitVector::ItrLeft(TUint32& aIdx) const |
|
861 { |
|
862 if(aIdx == 0) |
|
863 return ETrue; |
|
864 else |
|
865 { |
|
866 aIdx--; |
|
867 return EFalse; |
|
868 } |
|
869 } |
|
870 |
|
871 |
|
872 /** |
|
873 Iterate to the right (towards higher index) in the array of words ipData |
|
874 |
|
875 @param aIdx index within ipData array to be incremented; if it's possible to move right, it will be increased |
|
876 @return ETrue if there is no way right i.e. aIdx corresponds to the last word. EFalse otherwise and aIdx increased. |
|
877 */ |
|
878 TBool RBitVector::ItrRight(TUint32& aIdx) const |
|
879 { |
|
880 if(aIdx < iNumWords-1) |
|
881 { |
|
882 aIdx++; |
|
883 return EFalse; |
|
884 } |
|
885 else |
|
886 return ETrue; |
|
887 } |
|
888 |
|
889 |
|
890 |
|
891 |
|
892 |
|
893 |
|
894 |
|
895 |