/****************************************************************************************

		BitField.h

		Copyright: (c) 2001 Eovia Corp. All rights reserved.

		Author:	Alec
		Date:	6/3/98

		Revision History

		when		who			what & why
		==========	==========	======================================================
		3/10/99		Alec		changed CastFromWord to do ptr instead of ref cast for VC
		3/1/99		EricG		Fixed SetMasked
		7/15/98		Craig		TestBit() and TestMasked() now always return 1 if bit is 
									set, so SetBitValue(8,GetBit(7)) works correctly.
		6/26/98		Alec		added TBitField64 typedef now that uint64 exists for mac
		6/4/98		Alec		added static members CastFromWord() for use with basic types
		6/4/98		Alec		fixed SetMasked/BitValue code to not pass this
		6/4/98		Alec		changed mind, all statics are now members, data public
		6/3/98		Alec		new today - bit field operations for 16,32,64 bits

*****************************************************************************************/

#ifndef BitField_H
#define BitField_H

#pragma once

#include "MCBasicTypes.h"

#define TT  template< class T >
#define TTi template< class T > inline

/// \addtogroup MCCore
/// \{

/// <P>This is a template for setting single bit values in a compiler supported
/// type.  Typically these are used when flags are plentiful and space is not.
/// The calls match corresponding operations in TBitArray.</P>
///
/// <P>Note that the bits field is public so that shift operations and other built
/// in compiler bit ops are possible.</P>
///						
/// <P>What about multi-bit values, probably add new classes for this
/// like TBitFieldN<T> and implement 2,3,4,... with just Test/SetBitValue ops.
/// RotateLeft/Right and other non-standard bit operations would be nice too.</P>
///
TT class TBitField : public TMCObject
{	
public:
		/// use this for declaring masks, enums may not work for 64-bit ints
		typedef T TMask;
		
	public:
		inline TBitField( void );
		inline TBitField(
				const T initialBits );
		
		// these are conversion casts from a basic word to bits
		inline static TBitField<T>& CastFromWord( 
				T& word );
		inline static const TBitField<T>& CastFromWord( 
				const T& word );
				
		// accessors to the data (to avoid direct access)
		inline T& GetBits( void );
		inline const T& GetBits( void ) const;
		
		// masked bit operations, caller already has a bit mask
		inline boolean TestMasked(
				const T  		mask ) const;
		inline void ClearMasked(
				const T			mask );
		inline void SetMasked(
				const T			mask );
		inline void ToggleMasked(
				const T			mask );
	
		inline void SetMaskedValue(
				const T 		mask,
				const boolean 	value );		
				
		// numbered bit operations (match TBitArray calls)
		inline boolean TestBit(
				const uint32 	elemNum ) const;
		inline void ClearBit(
				const uint32 	elemNum );
		inline void SetBit(
				const uint32 	elemNum );
		inline void ToggleBit(
				const uint32 	elemNum );
		
		inline void SetBitValue(
				const uint32 	elemNum,
				const boolean 	value );
		
		// en mass operations
		inline void ClearAllBits( void );
		inline void SetAllBits( void );
		inline void ToggleAllBits( void );

		inline void SetAllBitValues(
				const boolean 	value );
				
	public:
		T bits;
};

/// \}



TTi TBitField< T >::TBitField( void )
	{ }

TTi TBitField< T >::TBitField(
		const T initialBits )
	: bits( initialBits )
	{ } 

// these are conversion casts from a basic word to bits
TTi TBitField<T>& TBitField< T >::CastFromWord( 
		T& word )
	{ return *(TBitField<T>*)&word; }
TTi const TBitField<T>& TBitField< T >::CastFromWord( 
		const T& word )
	{ return *(const TBitField<T>*)&word; }
				
// accessors to the data (to avoid direct access)
TTi T& TBitField< T >::GetBits( void )
	{ return bits; }

TTi const T& TBitField< T >::GetBits( void ) const
	{ return bits; }
					
// masked bit operations
TTi boolean TBitField< T >::TestMasked(
		const T  		mask ) const
	{ return 0 != (bits & mask); }
TTi void TBitField< T >::ClearMasked(
		const T  		mask )
	{ bits &= ~mask; }
TTi void TBitField< T >::SetMasked(
		const T  		mask )
	{ bits |= mask; }
TTi void TBitField< T >::ToggleMasked(
		const T  		mask )
	{
		if ( bits & mask ) // tst
			bits &= ~mask; // clear
		else
			bits |= mask;  // set
	}
	
TTi void TBitField< T >::SetMaskedValue(
		const T  		mask,
		const boolean 	value )
	{
		if ( value )
			SetMasked( mask );
		else
			ClearMasked( mask );
	}		


// numbered bit operations
TTi boolean TBitField< T >::TestBit(
		const uint32 	elemNum ) const
	{ return 0 != ( bits & ( ((T)1) << elemNum )); }
TTi void TBitField< T >::ClearBit(
		const uint32 	elemNum )
	{ bits &= ~( ((T)1) << elemNum ); }
TTi void TBitField< T >::SetBit(
		const uint32 	elemNum )
	{ bits |= ( ((T)1) << elemNum ); }
TTi void TBitField< T >::ToggleBit(
		const uint32 	elemNum )
	{
		const T mask = ( ((T)1) << elemNum );
		
		if ( bits & mask ) // tst
			bits &= ~mask; // clear
		else
			bits |= mask;  // set
	}
			
TTi void TBitField< T >::SetBitValue(
		const uint32 	elemNum,
		const boolean 	value )
	{
		if ( value )
			SetBit( elemNum );
		else
			ClearBit( elemNum );
	}

// en mass operations
TTi void TBitField< T >::ClearAllBits( void )
	{ bits = 0; }
TTi void TBitField< T >::SetAllBits( void )
	{ bits = ~0; }
TTi void TBitField< T >::ToggleAllBits( void )
	{ bits = ~bits; }
TTi void TBitField< T >::SetAllBitValues(
		const boolean	value )
	{ bits = (value) ? ~0 : 0; }
				
#undef TT
#undef TTi

// ---------------------------------

// these are the defined bit fields, please use the 64-bit field sparingly as 
// native processor support may still be limited.  	The mask typedefs are just for 
// notational convenience.

typedef class TBitField< uint8 >	TBitField8;		
typedef class TBitField< uint16 >	TBitField16;
typedef class TBitField< uint32 >	TBitField32;
typedef class TBitField< uint64 > 	TBitField64; 

#endif // BitField_H
