Tuesday, October 06, 2009

Bitmasking – A Blast From the Past

The topic of bitmasking came up recently and nearly made me fall out of my chair!  Had to whip something up to see if I could remember how...haven't done it in years (since my C/C++ days).  This code snippet below is in C# and is not nearly as elegant as it was in C/C++, but then again I never really cared for bit masking.  :)  There is some awkward casting I have to do because of language constraints, but the end result is pretty much who we did it in 'the good old days'.  I can't remember the last time I had to worry about bits, or bytes.  In hindsight I can clean that up using const values instead of an enum, but there you go.

Vipan Singala has an excellent article titled Bitwise Operators and Masks which I can recommend if your interested in this sort of thing.

The output of the sample below is as follows:

We are moving...
We are moving faster...
Not moving faster than light yet.
NOW we are moving faster than the speed of light...
Uh oh, looks like we've dropped out of faster than light travel!
But we are still moving moving fast...
We are still moving...
Removing all other flags..
Now we have stopped.

using System;

namespace BitMasking
{
    class Program
  
{

        enum SpeedFlags : byte
      
{
            Stopped = 0x00000000,
            Moving = 0x00000001,
            Faster = 0x00000002,
            FTL = 0x00000004
        }

        static void Main(string[] args)
        {

            bytestatus = (byte)SpeedFlags.Stopped;

            // set the 'Moving' bit
            //
          
status |= (byte)SpeedFlags.Moving;
           
            // set the 'Faster' bit
            //
          
status |= (byte) SpeedFlags.Faster;
           

            // status AND'ed with 'Moving' bit equals our 'Moving' bit, then its set
            //
          
if( (status & (byte)SpeedFlags.Moving) == (byte)SpeedFlags.Moving )
            {
                Console.WriteLine("We are moving...");
            }

            // check if faster bit is set
            //
          
if( (status & (byte)SpeedFlags.Faster) == (byte)SpeedFlags.Faster)
            {
                Console.WriteLine("We are moving faster...");
            }

            // our FTL bit is not set yet!!
            //
          
if((status & (byte)SpeedFlags.FTL) == (byte)SpeedFlags.FTL)
            {
                Console.WriteLine("We are moving faster than the speed of light...");
            }
            else
          
{
                Console.WriteLine("Not moving faster than light yet.");
            }

            // set the bit
            //
          
status |= (byte) SpeedFlags.FTL;

            // check to see if we've got the bit set
            //
          
if((status & (byte)SpeedFlags.FTL) == (byte)SpeedFlags.FTL)
            {
                Console.WriteLine("NOW we are moving faster than the speed of light...");
            }

            status ^= (byte) SpeedFlags.FTL;

            if((status & (byte)SpeedFlags.FTL) == (byte)SpeedFlags.FTL)
            {
                Console.WriteLine("We are still moving faster than the speed of light...");
            }
            else
          
{
                Console.WriteLine("Uh oh, looks like we've dropped out of faster than light travel!");
            }

            // check if faster bit is set
            //
          
if((status & (byte)SpeedFlags.Faster) == (byte)SpeedFlags.Faster)
            {
                Console.WriteLine("But we are still moving moving fast...");
            }
           
            // status AND'ed with 'Moving' bit equals our 'Moving' bit, then its set
            //
          
if((status & (byte)SpeedFlags.Moving) == (byte)SpeedFlags.Moving)
            {
                Console.WriteLine("We are still moving...");
            }

            Console.WriteLine("Removing all other flags..");
            status ^= (byte) SpeedFlags.Faster;
            status ^= (byte) SpeedFlags.Moving;

            if((status & (byte)SpeedFlags.Stopped) == (byte)SpeedFlags.Stopped)
            {
                Console.WriteLine("Now we have stopped.");
            }
        }
    }
}