Blob Blame Raw
#pragma once

#ifndef TCG_ALIGNMENT_H
#define TCG_ALIGNMENT_H

#include "macros.h"

/*! \file alignment.h

  This file contains C++ utilities about types alignment.
*/

namespace tcg
{

//**************************************************************************
//    Private  stuff
//**************************************************************************

// From http://stackoverflow.com/questions/6959261/how-can-i-simulate-alignast

union _MaxAlign {
	int i;
	long l;
	long long ll;
	long double ld;
	double d;
	void *p;
	void (*pf)();
	_MaxAlign *ps;
};

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

template <typename T, bool>
struct _AlignTypeDetail;

template <typename T>
struct _AlignTypeDetail<T, false> {
	typedef T type;
};

template <typename T>
struct _AlignTypeDetail<T, true> {
	typedef char type;
};

template <size_t alignment, typename U>
struct _AlignType {
	typedef typename _AlignTypeDetail<U, (alignment < sizeof(U))>::type type;
};

template <typename T>
struct _Aligner {
	char c;
	T t;
};

//**************************************************************************
//    TCG alignment  unions
//**************************************************************************

template <int alignment>
union aligner_type {
private:
	typename _AlignType<alignment, char>::type c;
	typename _AlignType<alignment, short>::type s;
	typename _AlignType<alignment, int>::type i;
	typename _AlignType<alignment, long>::type l;
	typename _AlignType<alignment, long long>::type ll;
	typename _AlignType<alignment, float>::type f;
	typename _AlignType<alignment, double>::type d;
	typename _AlignType<alignment, long double>::type ld;
	typename _AlignType<alignment, void *>::type pc;
	typename _AlignType<alignment, _MaxAlign *>::type ps;
	typename _AlignType<alignment, void (*)()>::type pf;
};

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

template <typename T>
union aligned_buffer {
	typedef aligner_type<sizeof(_Aligner<T>) - sizeof(T)> aligner_type;

	aligner_type m_aligner;
	char m_buf[sizeof(T)];

private:
	TCG_STATIC_ASSERT(sizeof(_Aligner<T>) - sizeof(T) ==
					  sizeof(_Aligner<aligner_type>) - sizeof(aligner_type));
};

//**************************************************************************
//    TCG alignment  traits
//**************************************************************************

template <typename T>
struct alignment_traits {
	static const int alignment = sizeof(_Aligner<T>) - sizeof(T);

	typedef aligner_type<alignment> aligner_type;
	typedef aligned_buffer<T> buffer_type;
};

} // namespace tcg

#endif // TCG_ALIGNMENT_H