BitField.cpp

00001 /*********************************************************************** 00002 * * 00003 * ViTooKi * 00004 * * 00005 * title: BitField.cpp * 00006 * * 00007 * * 00008 * * 00009 * ITEC institute of the University of Klagenfurt (Austria) * 00010 * http://www.itec.uni-klu.ac.at * 00011 * * 00012 * * 00013 * For more information visit the ViTooKi homepage: * 00014 * http://ViTooKi.sourceforge.net * 00015 * vitooki-user@lists.sourceforge.net * 00016 * vitooki-devel@lists.sourceforge.net * 00017 * * 00018 * This file is part of ViTooKi, a free video toolkit. * 00019 * ViTooKi is free software; you can redistribute it and/or * 00020 * modify it under the terms of the GNU General Public License * 00021 * as published by the Free Software Foundation; either version 2 * 00022 * of the License, or (at your option) any later version. * 00023 * * 00024 * This program is distributed in the hope that it will be useful, * 00025 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00026 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00027 * GNU General Public License for more details. * 00028 * * 00029 * You should have received a copy of the GNU General Public License * 00030 * along with this program; if not, write to the Free Software * 00031 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * 00032 * MA 02111-1307, USA. * 00033 * * 00034 ***********************************************************************/ 00035 00036 /*********************************************************************** 00037 * * 00038 * REVISION HISTORY: * 00039 * * 00040 * * 00041 * * 00042 ***********************************************************************/ 00043 00044 #include "BitField.hpp" 00045 #include <assert.h> 00046 00047 BitField::BitField(char* data, u32 size) 00048 { 00049 assert(data); 00050 maxSize=size; 00051 bits=(u32*) data; 00052 }; 00053 00054 00055 BitField::BitField(u32 size, bool initToValue) 00056 { 00057 dprintf_full("BitField::BitField(size:%u, initVal %i)\n",size,(int)initToValue); 00058 maxSize=size; 00059 u32 newSize=(maxSize+(sizeof(u32)*8-1))/(sizeof(u32)*8); 00060 this->bits=new u32[newSize]; 00061 assert(bits); 00062 u32 setToVal=0; 00063 if(initToValue) 00064 setToVal=0xffffffff; 00065 for(u32 i=0;i<newSize;i++) { 00066 bits[i]=setToVal; 00067 } 00068 }; 00069 00070 BitField::~BitField() 00071 { 00072 delete[] bits; 00073 } 00074 00075 void BitField::clearBit(u32 pos) 00076 { 00077 if(pos>=maxSize) 00078 return; 00079 //dprintf_full("BitField::clearBit(u32 %u) first u32 is %u\n",pos,bits[0]); 00080 u32 posInArray=pos/(sizeof(u32)*8); 00081 u32 bitInPos=pos%(sizeof(u32)*8); 00082 bits[posInArray]&=(((u32)0xffffffff)-(1<<bitInPos)); 00083 }; 00084 00085 void BitField::setBit(u32 pos) 00086 { 00087 if(pos>=maxSize) 00088 return; 00089 //dprintf_full("BitField::setBit(u32 %u) first u32 is %u\n",pos,bits[0]); 00090 u32 posInArray=pos/(sizeof(u32)*8); 00091 u32 bitInPos=pos%(sizeof(u32)*8); 00092 bits[posInArray]|=(1<<bitInPos); 00093 }; 00094 00095 bool BitField::getBit(u32 pos) const 00096 { 00097 if(pos>=maxSize) 00098 return false; 00099 00100 u32 posInArray=pos/(sizeof(u32)*8); 00101 u32 bitInPos=pos%(sizeof(u32)*8); 00102 return bits[posInArray]&(1<<bitInPos); 00103 }; 00104 00105 void BitField::invert() 00106 { 00107 bool val; 00108 for(u32 i=0;i<maxSize;i++) { 00109 val=getBit(i); 00110 if(val) // if true set to false 00111 clearBit(i); 00112 else // if false set to true 00113 setBit(i); 00114 } 00115 }; 00116 00126 BitField* BitField::createWithNewSize(u32 size, bool initValueForMissing) 00127 { 00128 00129 BitField* b=new BitField(size,initValueForMissing); 00130 00131 // copy full bytes with normal memcopy 00132 u32 posInArray=size/(sizeof(u32)*8); 00133 if(size>maxSize) //prevent buffer overflow 00134 posInArray=maxSize/(sizeof(u32)*8); 00135 00136 memcpy(b->bits,bits,posInArray*sizeof(u32)); 00137 00138 // copy the remaining bits (up to 31) manually 00139 u32 startPosRemaining=posInArray*(sizeof(u32)*8); 00140 u32 endPos=MIN(size,maxSize); 00141 for(u32 i=startPosRemaining;i<endPos;i++) { 00142 if(getBit(i)) 00143 b->setBit(i); 00144 else 00145 b->clearBit(i); 00146 } 00147 return b; 00148 }; 00149 00152 const char* BitField::toBinaryString(u32* sizeInU32) const 00153 { 00154 *sizeInU32=(maxSize+(sizeof(u32)*8-1))/(sizeof(u32)*8); 00155 return (const char*)bits; 00156 }; 00157 00160 char* BitField::toAsciiString() const 00161 { 00162 char* temp=new char[maxSize+1]; 00163 for(u32 i=0;i<maxSize;i++) 00164 temp[i]=( getBit(i) ? '1' : '0'); 00165 00166 temp[maxSize]='\0'; 00167 return temp; 00168 }; 00169 00171 bool BitField::isAllSet() const 00172 { 00173 u32 lastFullU32=maxSize/(sizeof(u32)*8); 00174 u32 restBits=lastFullU32*(sizeof(u32)*8); 00175 u32 i; 00176 00177 for(i=0;i<lastFullU32;i++) { 00178 if( (bits[i] & 0xffffffff)!=0xffffffff) 00179 return false; 00180 } 00181 // check the rest 00182 for(i=restBits;i<maxSize;i++) { 00183 if(!getBit(i)) 00184 return false; 00185 } 00186 return true; 00187 }; 00188 00190 bool BitField::isAllCleared() const 00191 { 00192 u32 lastFullU32=maxSize/(sizeof(u32)*8); 00193 u32 restBits=lastFullU32*(sizeof(u32)*8); 00194 u32 i; 00195 00196 for(i=0;i<lastFullU32;i++) { 00197 if( (bits[i] | 0x00000000)!=0x00000000) 00198 return false; 00199 } 00200 // check the rest 00201 for(i=restBits;i<maxSize;i++) { 00202 if(getBit(i)) 00203 return false; 00204 } 00205 return true; 00206 }; 00207 00209 float BitField::getPercentageSetBits() const 00210 { 00211 float res=0; 00212 int count=0; 00213 for(u32 i=0;i<maxSize;i++) { 00214 if(getBit(i)) 00215 count++; 00216 } 00217 if(count>0) // thus maxSize > 0 00218 res= (float)((double)count)/((double)maxSize); 00219 return res; 00220 }; 00221 00224 BitField* BitField::fromAsciiString(const char* str) 00225 { 00226 if(str==NULL) 00227 return NULL; 00228 00229 u32 sizeStr=strlen(str); 00230 BitField* b=new BitField(sizeStr,true); 00231 // only check for 0 and just hope that the string is valid 00232 // init to 1 because hopefully we will have more 1 than 0 00233 // in the string 00234 for(u32 i=0;i<sizeStr;i++) { 00235 if(str[i]=='0') 00236 b->clearBit(i); 00237 } 00238 return b; 00239 }; 00240 00243 BitField* BitField::fromBinaryString(const char* bin, u32 numBits) { 00244 BitField* b=new BitField(numBits,false); 00245 u32 bytes=(numBits+sizeof(char)-1)/sizeof(char); 00246 memcpy(b->bits,bin,bytes); 00247 return b; 00248 }; 00249 00251 BitField* BitField::fromBinaryString(char* bin, u32 numBits) 00252 { 00253 return new BitField(bin,numBits); 00254 }; 00255 00261 char* BitField::toHexString() const 00262 { 00263 // one char represents 4 bits 0111 -> 7 00264 int size=(maxSize+3)/4; 00265 // add 9 Byte header (32bit size in Hex + _) 00266 size+=9; 00267 char* result=new char[size+1]; 00268 // write header 00269 sprintf(result,"%8X_",maxSize); 00270 int cnt=0; 00271 00272 for(u32 i=0;i<maxSize;i+=4) { 00273 cnt=(getBit(i) ? 1 : 0); 00274 cnt+=(getBit(i+1) ? 1 : 0)<<1; 00275 cnt+=(getBit(i+2) ? 1 : 0)<<2; 00276 cnt+=(getBit(i+3) ? 1 : 0)<<3; 00277 if(cnt>9) { 00278 cnt-=10; 00279 cnt+='A'; 00280 } 00281 else 00282 cnt+='0'; 00283 result[9+i/4]=cnt; 00284 } 00285 result[size]='\0'; 00286 return result; 00287 }; 00289 BitField* BitField::fromHexString(const char* bin) 00290 { 00291 assert(bin); 00292 const char* payload=strchr(bin,'_'); 00293 if(!payload) { 00294 dprintf_err("BitField::fromHexString: invalid header\n"); 00295 return NULL; 00296 } 00297 payload++; // skip '_' 00298 u32 maxSize=0; 00299 if(0==sscanf(bin,"%x",&maxSize)) 00300 return NULL; 00301 if( strlen(payload) != ( (maxSize+3)/4)) { 00302 dprintf_err("BitField::fromHexString invalid header or incomplete data: >%s<\n",bin); 00303 return NULL; 00304 } 00305 const char* lBin=payload; 00306 BitField* b=new BitField(maxSize,true); 00307 char t='\0'; 00308 u32 i=0; 00309 for(u32 j=0;j<maxSize;j+=4) { 00310 t=lBin[j/4]; 00311 if(t>='A' && t <= 'F') 00312 i=t-'A'+10; 00313 else if(t>='0' && t<='9') 00314 i=t-'0'; 00315 else if(t=='\0') 00316 return b; //should be impossible 00317 else { 00318 dprintf_err("BitField::fromHexString Invalid char in hex string >%i<\n",t); 00319 delete b; return NULL; 00320 } 00321 // valid i 00322 // extract 4 bits from i, loop unrolling :-)))) 00323 // no need to handle last iteration specially, clearBit takes care of that 00324 if(!(i & 1u)) 00325 b->clearBit(j); 00326 if(!(i & 2u)) 00327 b->clearBit(j+1); 00328 if(!(i & 4u)) 00329 b->clearBit(j+2); 00330 if(!(i & 8u)) 00331 b->clearBit(j+3); 00332 }; 00333 dprintf_full("BitField::fromHexString: Successfully created bitfield\n"); 00334 return b; 00335 }; 00336 00346 u32 BitField::getBitRange(u32 startPos, int* nrBits, bool littleEndian) 00347 { 00348 assert(nrBits); 00349 if( (*nrBits)==0 || (*nrBits)>32 || startPos+(*nrBits)>maxSize) { 00350 (*nrBits)=-1; 00351 return 0; 00352 } 00353 // everything is valid 00354 u32 result=0; 00355 u32 shamt=0; //shift amount 00356 u32 i=0; 00357 if(!littleEndian) { 00358 shamt=(*nrBits)-1; 00359 } 00360 for (i=startPos;i<startPos+(*nrBits);i++) { 00361 result+=(getBit(i)?1:0)<<shamt; 00362 if(littleEndian) 00363 shamt++; 00364 else 00365 shamt--; 00366 } 00367 00368 return result; 00369 }; 00370 00371 /* writes @param nrBits of @param value starting with @param startBit at position @param startPos. 00372 * returns false if startBit+nrBits is greater 32, if nrBits is not in range 1..32, 00373 * if startBit is not in range 0..32-nrBits, or startPos+nBits is greater than maxSize 00374 * @param littleEndian specifies endianness. When set to true the decimal value for the 00375 * requested bitrange is calculated as if the first bit has the lowest value. 00376 * e.g.: Bit 0 1000 Bit 3 -> littleEndian=true --> 1 littleEndian=false --> 8 00377 */ 00378 bool BitField::writeBitRange(u32 startPos, int nrBits, u32 value, u32 startBit, bool littleEndian) 00379 { 00380 if(startBit+nrBits>32 || nrBits<1 || nrBits>32 || startPos+nrBits>maxSize) 00381 return false; 00382 00383 // write bits startBit..startBit+nrBits-1 from value to the bitfield according to endianness 00384 // little endianness: pos startBit equals to startPos 00385 // big endianness: pos startBit+nrBits-1 equals to startpos 00386 u32 shamt=0; 00387 u32 i=0; 00388 u32 val=0; 00389 if(!littleEndian) { 00390 shamt=nrBits-1; 00391 } 00392 00393 for(i=startPos;i<startPos+nrBits;i++) { 00394 val=(value>>(startBit+shamt))&1; 00395 if(val==1) 00396 setBit(i); 00397 else 00398 clearBit(i); 00399 if(littleEndian) 00400 shamt++; 00401 else 00402 shamt--; 00403 } 00404 00405 return true; 00406 }; 00407 00408 void BitField::doTest() 00409 { 00410 u32 i=0; 00411 BitField b(128,false); 00412 assert(b.getPercentageSetBits()<0.0001f); 00413 assert(b.isAllCleared()); 00414 b.setBit(128); //should be ignored 00415 assert(b.isAllCleared()); 00416 float f=b.getPercentageSetBits(); 00417 for(i=0;i<128;i++) { 00418 b.setBit(i); 00419 assert(f<b.getPercentageSetBits()); 00420 f=b.getPercentageSetBits(); 00421 } 00422 assert(b.isAllSet()); 00423 b.invert(); 00424 assert(b.isAllCleared()); 00425 b.invert(); 00426 assert(b.isAllSet()); 00427 char* tmp=new char[33]; 00428 char* tmp2=new char[33]; 00429 strcpy(tmp,"10000000000000011111111001111111"); 00430 BitField* b2=BitField::fromAsciiString(tmp); 00431 char* t2=b2->toAsciiString(); 00432 printf("X%sX\n",t2); 00433 assert(strcmp(tmp,t2)==0); 00434 delete[] t2; 00435 for(i=0;i<32;i++) 00436 tmp2[i]= (b2->getBit(i)?1:0)+'0'; 00437 tmp2[32]='\0'; 00438 printf("X%sX\n",tmp2); 00439 assert(strcmp(tmp,tmp2)==0); 00440 00441 delete[] tmp2; 00442 00443 assert(b2->getBit(33)==false); 00444 00445 int nrBits=8; 00446 assert(1==b2->getBitRange(0,&nrBits,true)); 00447 assert(nrBits==8); 00448 assert(128==b2->getBitRange(0,&nrBits,false)); 00449 assert(nrBits==8); 00450 assert(128==b2->getBitRange(8,&nrBits,true)); 00451 assert(nrBits==8); 00452 assert(1==b2->getBitRange(8,&nrBits,false)); 00453 assert(nrBits==8); 00454 nrBits=0; 00455 assert(0==b2->getBitRange(0,&nrBits,false)); 00456 assert(nrBits==-1); 00457 nrBits=16; 00458 assert((127+254*256)==b2->getBitRange(16,&nrBits,true)); 00459 assert(nrBits==16); 00460 assert((127+254*256)==b2->getBitRange(16,&nrBits,false)); 00461 assert(nrBits==16); 00462 nrBits=32; 00463 printf("%x\n",b2->getBitRange(0,&nrBits,true)); 00464 assert(0xfe7f8001==b2->getBitRange(0,&nrBits,true)); 00465 assert(nrBits==32); 00466 printf("%x\n",b2->getBitRange(0,&nrBits,false)); 00467 assert(0x8001fe7f==b2->getBitRange(0,&nrBits,false)); 00468 assert(nrBits==32); 00469 assert(0==b2->getBitRange(1,&nrBits,true)); 00470 assert(nrBits==-1); 00471 nrBits=1; 00472 assert(1==b2->getBitRange(31,&nrBits,true)); 00473 assert(nrBits==1); 00474 assert(0==b2->getBitRange(32,&nrBits,true)); 00475 assert(nrBits==-1); 00476 00477 BitField* b3=new BitField(32,false); 00478 nrBits=32; 00479 u32 val=b2->getBitRange(0,&nrBits,true); 00480 b3->writeBitRange(0,nrBits,val,0,true); 00481 char* b3Tmp=b3->toAsciiString(); 00482 printf("X%sX\n",b3Tmp); 00483 assert(strcmp(tmp,b3Tmp)==0); 00484 delete[] b3Tmp; 00485 00486 val=b2->getBitRange(0,&nrBits,false); 00487 b3->writeBitRange(0,nrBits,val,0,false); 00488 b3Tmp=b3->toAsciiString(); 00489 printf("X%sX\n",b3Tmp); 00490 assert(strcmp(tmp,b3Tmp)==0); 00491 00492 delete b2;delete[] tmp; 00493 delete b3; delete[] b3Tmp; 00494 00495 // Test 4 hex 00496 const char* t4="A_FF0"; 00497 BitField* b4=BitField::fromHexString(t4); 00498 assert(b4); 00499 char* t4_1=b4->toHexString(); 00500 assert(strstr(t4_1,t4)); 00501 delete[] t4_1; 00502 00503 }; 00504