
///////////////////////////////////////////////////////////////////////////////
//
// File   : Asura_Endian.h
// Author : Andy Tate
// Date   : 8-Sep-2005
//
// Copyright (C) 2005 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

#ifdef ASURA_USE_PRAGMA_ONCE
	#pragma once
#endif   // ifdef ASURA_USE_PRAGMA_ONCE

#ifndef __ASURA_ENDIAN_H__
#define __ASURA_ENDIAN_H__

////////////////////////////////////////////////////////////////////////////////
// Include files...
////////////////////////////////////////////////////////////////////////////////

#include "Debugging/Asura_Assert.h"


////////////////////////////////////////////////////////////////////////////////
// Forward class declarations...
////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
// Class declaration...
////////////////////////////////////////////////////////////////////////////////

class Asura_Endian
{
public:
	// Public functions...
	static void SwapBytes(char* pcBuffer, size_t uSize)
	{
		Asura_Assert	(uSize <= 4, "Endian mangler cannot deal with types larger than 4 bytes.");
		switch (uSize)
		{
			case 2:
			{
				const char cTemp = pcBuffer[0];

				pcBuffer[0]	= pcBuffer[1];
				pcBuffer[1]	= cTemp;
				break;
			}

			case 4:
			{
				const char ucTemp0 = pcBuffer[0];
				const char ucTemp1 = pcBuffer[1];

				pcBuffer[0]	= pcBuffer[3];
				pcBuffer[1]	= pcBuffer[2];
				pcBuffer[2]	= ucTemp1;
				pcBuffer[3]	= ucTemp0;
				break;
			}

			default:
			{
				// Either 1-byte or too many bytes - do nothing
			}
		}		// End of switch.
	}

	template<typename T> static T SwapBytes (const T xValue)
	{
		T xDest = xValue;
		SwapBytes(reinterpret_cast<char*>(&xDest), sizeof(T));
		return xDest;
	}

	template<typename T> static T SwapBits (const T xValue, const bool bSwapBitsInBytes = false)
	{
		T	xSource	= xValue;
		T	xDest	= 0;

		// Reverse all of the bits...
		for (int i = 0; i < sizeof(T) * 8; i++, xSource >>= 1)
		{
			xDest	= (xDest << 1) | (xSource & 1);
		}

		// Output the result...
		return	((bSwapBitsInBytes) ? SwapBytes(xDest) : xDest);
	}


protected:
	// Protected variables...


	// Protected functions...


private:
	// Private variables...


	// Private functions...

	Asura_Endian  (void);
	Asura_Endian  (const Asura_Endian& xOther);
	~Asura_Endian ();

	Asura_Endian&	operator=	(const Asura_Endian& xOther);

};   // End of class 'Asura_Endian'.



#endif   // ifndef __ASURA_ENDIAN_H__


/// End of file. ///
