DevMaster.net Forums
[[ Home | Forums | 3D Engines Database | Wiki | Articles/Tutorials | Game Dev Jobs | IRC Chat Network | Contact Us ]]

Go Back   DevMaster.net Forums > Site Discussions > Code & Snapshot Discussion
User Name
Password
Register FAQ Members List Search Today's Posts Mark Forums Read

Reply
 
Thread Tools Search this Thread Display Modes
Old 02-08-2005, 02:48 AM   #1
bladder
DevMaster Staff
 
bladder's Avatar
 
Join Date: Sep 2003
Location: Hell
Posts: 1,109
Default

This bit flags class is a pretty handy utility that could be needed from time to time. It's small and it saves a lot of typing. It strictly uses integer types ( or I suppose types that are copy constructable and provide operators >>, <<, |, &, ^, ~, != and ==). The nce thing about this bit class is that you can do stuff like

bits[0] = false

which operate on individual bits by having operator [] return a type of proxy object that is technically an intermediary between operator [] and the assignment of true/false to a single bit.

Code:
template< typename T > class cBasicBitFlags; template< typename R > inline R util_SetBit( int i ) { return R( R(1) << i ); }; template< typename T > class cBasicBitFlagsProxy { public: cBasicBitFlagsProxy( int idx, cBasicBitFlags<T>* ptr ) : m_index(idx), m_bits(ptr) {} void operator = ( bool b ) { b ? m_bits->set(m_index) : m_bits->unset(m_index); } operator bool () const { return m_bits->isSet(m_index); } private: int m_index; cBasicBitFlags<T>* m_bits; }; template< typename T > class cBasicBitFlags { public: cBasicBitFlags(); cBasicBitFlags( T flags ); cBasicBitFlags( const cBasicBitFlags<T>& other ); bool isSet( int bit ) const; void set( int bit ); void unset( int bit ); int size() const; void setData( T t ); T data() const; // operator T () const; // this seems dangerous to have... cBasicBitFlags<T> operator | ( const cBasicBitFlags<T>& other ); cBasicBitFlags<T> operator & ( const cBasicBitFlags<T>& other ); cBasicBitFlags<T> operator ^ ( const cBasicBitFlags<T>& other ); cBasicBitFlags<T> operator ~ (); bool operator == ( const cBasicBitFlags<T>& other ) const; bool operator != ( const cBasicBitFlags<T>& other ) const; cBasicBitFlagsProxy<T> operator [] ( int idx ); const cBasicBitFlagsProxy<T> operator [] ( int idx ) const; /// /// Extracts a certain number of bits from the bitfield and places them at the /// starting bits in the returned bit field. cBasicBitFlags<T> extract( int idx, int num ); std::string toString() const; friend std::ostream& operator << ( std::ostream& o, cBasicBitFlags<T>& bits ); private: T m_flags; }; template< typename T > std::string cBasicBitFlags<T>::toString() const { std::string str; str.reserve( size() ); for( int i = 0; i < size(); ++i ) str += (isSet(i) ? "1" : "0"); return str; } template< typename T > inline std::ostream& operator << ( std::ostream& o, cBasicBitFlags<T>& bits ) { o<< bits.toString().c_str(); return o; } template< typename T > cBasicBitFlags<T>::cBasicBitFlags() : m_flags(0) {} template< typename T > cBasicBitFlags<T>::cBasicBitFlags( T flags ) : m_flags(flags) {} template< typename T > cBasicBitFlags<T>::cBasicBitFlags( const cBasicBitFlags<T>& other ) : m_flags(other.m_flags) {} template< typename T > bool cBasicBitFlags<T>::isSet( int bit ) const { return (m_flags & util_SetBit<T>(bit)) != 0; } template< typename T > void cBasicBitFlags<T>::set( int bit ) { m_flags |= util_SetBit<T>(bit); } template< typename T > void cBasicBitFlags<T>::unset( int bit ) { m_flags &= ~util_SetBit<T>(bit); } template< typename T > int cBasicBitFlags<T>::size() const { return sizeof(T) * 8; } template< typename T > cBasicBitFlagsProxy<T> cBasicBitFlags<T>::operator [] ( int idx ) { return cBasicBitFlagsProxy<T>(idx, this); } template< typename T > const cBasicBitFlagsProxy<T> cBasicBitFlags<T>::operator [] ( int idx ) const { return cBasicBitFlagsProxy<T>(idx, const_cast<cBasicBitFlags<T>*>(this) ); } template< typename T > T cBasicBitFlags<T>::data() const { return m_flags; } /* template< typename T > cBasicBitFlags<T>::operator T () const { return m_flags; } */ template< typename T > cBasicBitFlags<T> cBasicBitFlags<T>::operator | ( const cBasicBitFlags<T>& other ) { return cBasicBitFlags<T>( m_flags | other.data() ); } template< typename T > cBasicBitFlags<T> cBasicBitFlags<T>::operator & ( const cBasicBitFlags<T>& other ) { return cBasicBitFlags<T>( m_flags & other.data() ); } template< typename T > cBasicBitFlags<T> cBasicBitFlags<T>::operator ^ ( const cBasicBitFlags<T>& other ) { return cBasicBitFlags<T>( m_flags ^ other.data() ); } template< typename T > cBasicBitFlags<T> cBasicBitFlags<T>::operator ~ () { return cBasicBitFlags<T>( ~m_flags ); } template< typename T > bool cBasicBitFlags<T>::operator == ( const cBasicBitFlags<T>& other ) const { return m_flags == other.data(); } template< typename T > bool cBasicBitFlags<T>::operator != ( const cBasicBitFlags<T>& other ) const { return m_flags != other.data(); } template< typename T > cBasicBitFlags<T> cBasicBitFlags<T>::extract( int idx, int num ) { T d = m_flags << ( size() - (idx + num) ); d >>= (size() - num); return cBasicBitFlags<T>(d); } template< typename T > void cBasicBitFlags<T>::setData( T t ) { m_flags = t; } // Common bit sizes. typedef cBasicBitFlags<unsigned char> bits8_t; typedef cBasicBitFlags<unsigned short> bits16_t; typedef cBasicBitFlags<unsigned int> bits32_t; typedef cBasicBitFlags<unsigned __int64> bits64_t;
bladder is offline   Reply With Quote
Old 02-08-2005, 07:35 AM   #2
Dia Kharrat
DevMaster Staff
 
Join Date: Jan 2003
Posts: 1,201
Default

Awsome work! This can prove to be very useful for a recent thing I was working on

I just tested it, and it compiles and works like a charm.
Dia Kharrat is offline   Reply With Quote
Old 02-08-2005, 07:42 AM   #3
Mihail121
Senior Member
 
Mihail121's Avatar
 
Join Date: Jan 2003
Posts: 868
Default

I'm sure that thing will be useful to the people that are used to all that C++ mess but i'll have to port it to Java, C or Pascal to make it useful to me!
Mihail121 is offline   Reply With Quote
Old 02-08-2005, 08:18 AM   #4
Dia Kharrat
DevMaster Staff
 
Join Date: Jan 2003
Posts: 1,201
Default

If you're talking about templates, then C# and Java support "generics", which is supposed to be similar to C++ templates.
Dia Kharrat is offline   Reply With Quote
Old 02-28-2005, 09:33 AM   #5
SnprBoB86
Valued Member
 
Join Date: Aug 2004
Posts: 120
Default

Alternatively, you could use an array rather than templates.

Java users: without operator overloading you should just drop the "proxy" concept because you need to rely on setBit and getBit
There might even be a built in type for this.

C# users: just use System.Collections.BitArray
___________________________________________
Brandon Bloom
http://brandonbloom.name
SnprBoB86 is offline   Reply With Quote
Old 11-14-2005, 01:14 PM   #6
CobraLionz
Member
 
Join Date: Oct 2005
Posts: 54
Default Re: Bit flags

What in the world is this? If you're trying to get a bit from a byte or something it can be coded in less than 20 lines. What is a "bit size"? Last time i checked a bitsize is an intrinsic, 1/8 of a byte.
CobraLionz is offline   Reply With Quote
Old 11-14-2005, 01:32 PM   #7
Reedbeta
DevMaster Staff
 
Join Date: Oct 2004
Location: Seattle, WA
Posts: 3,707
Default Re: Bit flags

If you want to get a bit from a byte you can do it in one line. Bladder's contribution is a class that wraps those accesses, making them much more readable, i.e. by writing bits[i] = false instead of bits &= ~(1 << i).

That said, I believe most implementations of the STL have a specialization for std::vector<bool> that does basically the same thing as this, although it doesn't have all the bells and whistles like providing bitwise operators that work on the whole array at once.
___________________________________________
Currently working at Sucker Punch
reedbeta.com - OpenGL demos and other projects
Luabridge - a lightweight, dependency-free C++/Lua binding library.
CD Lite - an unobtrusive, minimal CD player application for Windows.
Reedbeta is offline   Reply With Quote
Old 11-14-2005, 09:36 PM   #8
CobraLionz
Member
 
Join Date: Oct 2005
Posts: 54
Default Re: Bit flags

Yeah well its still a convoulted mess. templated bit accessor makes no sense to me. I wrote a class like that in literally 20 lines and replaced a template with a ptr to unsigned char. Granted I didn't implement the bitwise overloads but that is extremely straightforward and shouldnt have made the code over 100 lines. Then all you need to do is i/8 to get the byte and i % 8 to get the bit and you can even get rid of the / and % if you don't like it and it works for arrays not just user-defined types.

Also if he wanted to make it a template he should have a template parameter indicating which end of the bit he wants to get. For ex, for jpeg decompression the first bit is 1<<i in the huffman decoding phase but for windows monochrome bitmaps the top left pixel is 128>>i of the first byte.
CobraLionz is offline   Reply With Quote
Old 11-15-2005, 06:10 AM   #9
.oisyn
DevMaster Staff
 
.oisyn's Avatar
 
Join Date: Sep 2005
Location: The Netherlands
Posts: 1,442
Default Re: Bit flags

What's wrong with std::bitset?

also, there are CHAR_BIT bits in a char (byte), which doesn't need to be 8
___________________________________________
C++ addict
-
Currently working on: the 3D engine for Tomb Raider: Underworld and Deus Ex 3.

Last edited by .oisyn : 11-15-2005 at 06:12 AM.
.oisyn is offline   Reply With Quote
Old 11-15-2005, 08:34 AM   #10
bladder
DevMaster Staff
 
bladder's Avatar
 
Join Date: Sep 2003
Location: Hell
Posts: 1,109
Default Re: Bit flags

CobraLionz: It's easier to save to and load from files with this thing. And it saves a lot of unnecessary typing and increases readability. It's faster then using division and %, and sometimes 32 bits is either unnecessary (char*) or is not enough. And bit access is standard, bit[0] is the least significant and bit[bit.size()-1] is the most significant. I havent found any need to add a second template parameter.

Quote:
What's wrong with std::bitset?

Good question, apparently nothing form what i've just read about it . Never thought of looking for something like this in std because I just assumed something like this didn't exist. All it doesnt have is that "extract" function.

Quote:
also, there are CHAR_BIT bits in a char (byte), which doesn't need to be 8

I always thought that a "char" data type was fixed to 8, but the short/int/long type sizes could vary. But ok.
___________________________________________
- TripleBuffer
- Me blog
bladder is offline   Reply With Quote
Old 11-15-2005, 09:26 AM   #11
monjardin
Senior Member
 
Join Date: Oct 2005
Location: Pensacola, FL
Posts: 1,028
Default Re: Bit flags

I'm writing two data link programs right now talking to search radars with 9 and 13-bit word lengths. There's a whole lot of bit shifting in my future!
___________________________________________
monjardin's JwN Meter (1,2,3,4,5,6):
|----|----|----|----|----|----|----|----|----|----|
*
monjardin is offline   Reply With Quote
Old 11-15-2005, 11:52 AM   #12
NomadRock
Senior Member
 
NomadRock's Avatar
 
Join Date: Aug 2004
Location: USA
Posts: 829
Default Re: Bit flags

Quote:
Originally Posted by Mihail121
I'm sure that thing will be useful to the people that are used to all that C++ mess but i'll have to port it to Java, C or Pascal to make it useful to me!

http://java.sun.com/j2se/1.5.0/docs/...il/BitSet.html

You're welcome
___________________________________________
Jesse Coyle
NomadRock is offline   Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Forum Jump


All times are GMT -7. The time now is 03:17 AM.


Powered by vBulletin
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.