userlibandfileserver/fileserver/sfat/sl_utl.cpp
changeset 43 96e5fb8b040d
equal deleted inserted replaced
-1:000000000000 43:96e5fb8b040d
       
     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