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