/*****************************************************************************
 * $LastChangedDate: 2010-02-03 20:50:32 -0500 (Wed, 03 Feb 2010) $
 * @file
 * @author  Jim E. Brooks  http://www.palomino3d.org
 * @brief   Bits class and functions.
 *//*
 * LEGAL:   COPYRIGHT (C) 2004 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
 *****************************************************************************/

#ifndef BASE_BITS_HH
#define BASE_BITS_HH 1

namespace base {

////////////////////////////////////////////////////////////////////////////////
/////////////////////////////  functions  //////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

/// Pass address of bit-field struct.
/// CLEAR_BIT_FIELDS( &mBits );
#define CLEAR_BIT_FIELDS( BIT_FIELD_PTR ) ( *(reinterpret_cast<unsigned int*>( (BIT_FIELD_PTR) )) = 0 )

/*****************************************************************************
 * Trivial but convenient for enumerations.
 *****************************************************************************/
template<typename T>
inline T
SetBit( const T val, const int bit )
{
    return T( int(val) | int(bit) );
}

template<typename T>
inline T
ClearBit( const T val, const int bit )
{
    return T( int(val) & ~int(bit) );
}

////////////////////////////////////////////////////////////////////////////////
/// @brief Portable bit-field class.
///
/// This class is useful for accessing bits by index.
/// Doing so is unportable and wrong using a standard C bitfield
/// (which was meant for accessing bits by member name, not by index).
///
class Bits
{
public:
            Bits( uint bits = 0 ) : mBits(bits) { }
    bool    Get( uint idx ) const     { ASSERT(idx < BIT_COUNT); return (mBits & (1<<idx)) != 0; }  // get bit (true or false)
    void    Set( uint idx )           { ASSERT(idx < BIT_COUNT); mBits |= (1<<idx); }       // turn on bit
    void    Set( uint idx, bool set ) { if ( set ) Set(idx); else Clear(idx); }             // turn on/off bit
    void    Clear( uint idx )         { ASSERT(idx < BIT_COUNT); mBits &= ~(1<<idx); }      // turn off bit
    Bits&   operator=( uint bits )    { mBits = bits; return *this; }  // assign from uint
            operator uint() const     { return mBits; }                // convert to uint

private:
    CLASS_CONST uint BIT_COUNT = 32;
    uint             mBits;
};

} // namespace base

#endif // BASE_BITS_HH
