/** SGX

The   sss    gggg x   x   
     s      g      x x    Engine
      sss   g  gg   x
         s  g   g  x x          Copyright 1995-2009.
     ssss    gggg x   x         Steven Goodwin. All Rights Reserved.
    
This version has been released under the GNU Public License v2.0.

Please see the license files for details.

File: sgx/include/sgx/core/types/endian.hpp

*/

#ifndef SGX_CORE_TYPES_DATATYPE_ENDIAN_HPP
#define SGX_CORE_TYPES_DATATYPE_ENDIAN_HPP	1


SGX_INLINE tUINT16 sgxEndianSwap16(tUINT16 var)
{
   return (tUINT16)((((var)&0xff)<<8) | ( ((var)>>8)&0xff));
}

SGX_INLINE tUINT32 sgxEndianSwap32(tUINT32 var)
{
   return ((((var)&0xff)<<24) | ((((var)>>8)&0xff)<<16) |
          ((((var)>>16)&0xff)<<8) | ((((var)>>24)&0xff)) );
}

// run-time check for safety
// Little endian machines : x86, Xbox, PS2
SGX_INLINE tBOOL sgxIsLittleEndian() 
{
	tUINT16 uint16;

    uint16 = 1;
    if (*(tBYTE *)&uint16 == 1) {
		return TRUE;
	} else {
		return FALSE;
	}
}

// Big endian machines : Xbox360, Gamecube, PPC
SGX_INLINE tBOOL sgxIsBigEndian() 
{
	return !sgxIsLittleEndian();
}

#if SGX_ENDIAN_LITTLE==1
	#define sgxEndianToBig16(_v)          sgxEndianSwap16(_v)
	#define sgxEndianToLittle16(_v)
	#define sgxEndianToBig32(_v)          sgxEndianSwap32(_v)
	#define sgxEndianToLittle32(_v)

	SGX_INLINE tUINT16 sgxMakeInt16(tBYTE byte1, tBYTE byte2)
	{
	   return (byte2 << 8) | byte1;
	}

	SGX_INLINE tUINT16 sgxMakeInt16(tBYTE *ptr)
	{
	   return (*(ptr+1) << 8) | *(ptr+0);
	}

	SGX_INLINE tUINT32 sgxMakeInt32(tBYTE byte1, tBYTE byte2, tBYTE byte3, tBYTE byte4)
	{
	   return (byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1;
	}

	SGX_INLINE tUINT32 sgxMakeInt32(tBYTE *ptr)
	{
	   return (*(ptr+3) << 24) | (*(ptr+2) << 16) | (*(ptr+1) << 8) | *(ptr+0);
	}

#elif SGX_ENDIAN_BIG==1
	#define sgxEndianToBig16(_v)
	#define sgxEndianToLittle16(_v)       sgxEndianSwap16(_v)
	#define sgxEndianToBig32(_v)
	#define sgxEndianToLittle32(_v)       sgxEndianSwap32(_v)

	SGX_INLINE tUINT16 sgxMakeInt16(tBYTE byte1, tBYTE byte2)
	{
	   return (tUINT16)((byte1 << 8) | byte2);
	}
#ifdef __cplusplus
	SGX_INLINE tUINT16 sgxMakeInt16(tBYTE *ptr)
	{
	   return (tUINT16)((*(ptr+0) << 8) | *(ptr+1));
	}
#endif
	SGX_INLINE tUINT32 sgxMakeInt32(tBYTE byte1, tBYTE byte2, tBYTE byte3, tBYTE byte4)
	{
	   return (tUINT32)((byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4);
	}
#ifdef __cplusplus
	SGX_INLINE tUINT32 sgxMakeInt32(tBYTE *ptr)
	{
	   return (tUINT32)((*(ptr+0) << 24) | (*(ptr+1) << 16) | (*(ptr+2) << 8) | *(ptr+4));
	}
#endif
#else
	sgxCompileError("No Endian is set");

	#define sgxEndianToBig16(_v)
	#define sgxEndianToLittle16(_v)
	#define sgxEndianToBig32(_v)
	#define sgxEndianToLittle32(_v)

	SGX_INLINE tUINT16 sgxMakeInt16(tBYTE byte1, tBYTE byte2)
	{
		sgxCompileError("No Endian is set - This function may return incorrect results for your platform");
		return (tUINT16)((byte1 << 8) | byte2);
	}

	SGX_INLINE tUINT16 sgxMakeInt16(tBYTE *ptr)
	{
		sgxCompileError("No Endian is set - This function may return incorrect results for your platform");
	   return (tUINT16)((*(ptr+0) << 8) | *(ptr+1));
	}

	SGX_INLINE tUINT32 sgxMakeInt32(tBYTE byte1, tBYTE byte2, tBYTE byte3, tBYTE byte4)
	{
		sgxCompileError("No Endian is set - This function may return incorrect results for your platform");
	   return (tUINT32)((byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4(tUINT32)(;
	}

	SGX_INLINE tUINT32 sgxMakeInt32(tBYTE *ptr)
	{
		sgxCompileError("No Endian is set - This function may return incorrect results for your platform");
		return (tUINT32)((*(ptr+0) << 24) | (*(ptr+1) << 16) | (*(ptr+2) << 8) | *(ptr+4);
	}


#endif

#endif /* SGX_CORE_TYPES_DATATYPE_ENDIAN_HPP */
