30978Fermer30980
bearbecueLe 08/05/2017 à 11:01
namespace	Internal
{
	template<hh_u32 _FootprintInBytes> struct	TNativeSwapper		: public FalseType {};
	template<> struct							TNativeSwapper<1>	: public TrueType { static void SwapInPlace(void *data, hh_u32 count) { } };
	template<> struct							TNativeSwapper<2>	: public TrueType { static void SwapInPlace(void *data, hh_u32 count) { Mem::SwapEndian16(data, count); } };
	template<> struct							TNativeSwapper<4>	: public TrueType { static void SwapInPlace(void *data, hh_u32 count) { Mem::SwapEndian32(data, count); } };
	template<> struct							TNativeSwapper<8>	: public TrueType { static void SwapInPlace(void *data, hh_u32 count) { Mem::SwapEndian64(data, count); } };

	template<typename _Type>
	struct	TStreamEndianSwapperHelpers
	{
		static void	SwapInPlace(_Type *data, hh_u32 count)
		{
			for (hh_u32 i = 0; i < count; i++)
			{
				PKSwapEndianInPlace(data\[i]);
			}
		}
	};

	template<> struct	TStreamEndianSwapperHelpers<hh_u8> { static void	SwapInPlace(hh_u8 *data, hh_u32 count) { TNativeSwapper<sizeof(*data)>::SwapInPlace(data, count); } };
	template<> struct	TStreamEndianSwapperHelpers<hh_i8> { static void	SwapInPlace(hh_i8 *data, hh_u32 count) { TNativeSwapper<sizeof(*data)>::SwapInPlace(data, count); } };
	template<> struct	TStreamEndianSwapperHelpers<hh_u16> { static void	SwapInPlace(hh_u16 *data, hh_u32 count) { TNativeSwapper<sizeof(*data)>::SwapInPlace(data, count); } };
	template<> struct	TStreamEndianSwapperHelpers<hh_i16> { static void	SwapInPlace(hh_i16 *data, hh_u32 count) { TNativeSwapper<sizeof(*data)>::SwapInPlace(data, count); } };
	template<> struct	TStreamEndianSwapperHelpers<hh_u32> { static void	SwapInPlace(hh_u32 *data, hh_u32 count) { TNativeSwapper<sizeof(*data)>::SwapInPlace(data, count); } };
	template<> struct	TStreamEndianSwapperHelpers<hh_i32> { static void	SwapInPlace(hh_i32 *data, hh_u32 count) { TNativeSwapper<sizeof(*data)>::SwapInPlace(data, count); } };
	template<> struct	TStreamEndianSwapperHelpers<float> { static void	SwapInPlace(float *data, hh_u32 count) { TNativeSwapper<sizeof(*data)>::SwapInPlace(data, count); } };
}

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

template<typename _Type>
void	PKSwapEndianInPlace(const TMemoryView<_Type> &object)
{
	Internal::TStreamEndianSwapperHelpers<_Type>::SwapInPlace(object.Data(), object.Count());
}

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

template<typename _Type, hh_i32 _FootprintInBytes>
void	PKSwapEndianInPlace(const TStridedMemoryView<_Type, _FootprintInBytes> &object)
{
	if ((sizeof(_Type) == _FootprintInBytes ||		// compile-time culling : compact footprint
		_FootprintInBytes % sizeof(_Type) == 0) &&	// compile-time culling : footprint is a multiple of sizeof(_Type), we can reinterpret as a contiguous array of _Type objects and patch the count
		Internal::TNativeSwapper<sizeof(_Type)>::True &&	// we know how to endian-swap this type
		object.Stride() == _FootprintInBytes)
	{
		Internal::TStreamEndianSwapperHelpers<_Type>::SwapInPlace(object.Data(), object.Count() * (_FootprintInBytes / sizeof(_Type)));
		TMemoryView<_Type>	contiguousView = object.ToMemoryViewIFP();
		if (!contiguousView.Empty())
		{
			PKSwapEndianInPlace(contiguousView);
			return;
		}
	}

	for (hh_u32 i = 0; i < object.Count(); i++)
	{
		PKSwapEndianInPlace(object\[i]);
	}
}