#ifndef ETL_ALIGNEMENT_INCLUDED
#define ETL_ALIGNEMENT_INCLUDED
#include <stdint.h>
#include "platform.h"
#include "type_traits.h"
#include "static_assert.h"
namespace etl
{
namespace private_alignment
{
template <const bool IS_MATCH, const size_t ALIGNMENT, typename T1 = void, typename T2 = void, typename T3 = void, typename T4 = void, typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void>
class type_with_alignment_matcher;
template <const size_t ALIGNMENT, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
class type_with_alignment_matcher <true, ALIGNMENT, T1, T2, T3, T4, T5, T6, T7, T8>
{
public:
typedef T1 type;
};
template <const size_t ALIGNMENT, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
class type_with_alignment_matcher <false, ALIGNMENT, T1, T2, T3, T4, T5, T6, T7, T8>
{
public:
typedef typename type_with_alignment_matcher<ALIGNMENT <= etl::alignment_of<T2>::value, ALIGNMENT, T2, T3, T4, T5, T6, T7, T8, void>::type type;
};
template <const size_t ALIGNMENT>
class type_with_alignment_matcher <false, ALIGNMENT, void, void, void, void, void, void, void, void>
{
public:
typedef char type;
};
template <const size_t ALIGNMENT, typename T1, typename T2 = void, typename T3 = void, typename T4 = void, typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void>
class type_with_alignment_helper
{
public:
typedef typename type_with_alignment_matcher<ALIGNMENT <= etl::alignment_of<T1>::value, ALIGNMENT, T1, T2, T3, T4, T5, T6, T7, T8>::type type;
};
}
template <const size_t ALIGNMENT>
class type_with_alignment
{
public:
typedef typename private_alignment::type_with_alignment_helper<ALIGNMENT, int_least8_t, int_least16_t, int32_t, int64_t, float, double, void*>::type type;
};
template <const size_t LENGTH, const size_t ALIGNMENT>
struct aligned_storage
{
struct type
{
template <typename T>
operator T& ()
{
ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
T* t = *this;
return *t;
}
template <typename T>
operator const T& () const
{
ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
const T* t = *this;
return *t;
}
template <typename T>
operator T* ()
{
ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
return reinterpret_cast<T*>(data);
}
template <typename T>
operator const T* () const
{
ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
return reinterpret_cast<const T*>(data);
}
template <typename T>
T& get_reference()
{
ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
T* t = *this;
return *t;
}
template <typename T>
const T& get_reference() const
{
ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
const T* t = *this;
return *t;
}
template <typename T>
T* get_address()
{
ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
return reinterpret_cast<T*>(data);
}
template <typename T>
const T* get_address() const
{
ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
return reinterpret_cast<const T*>(data);
}
union
{
char data[LENGTH];
typename etl::type_with_alignment<ALIGNMENT>::type etl_alignment_type;
};
};
};
template <const size_t LENGTH, typename T>
struct aligned_storage_as : public etl::aligned_storage<LENGTH, etl::alignment_of<T>::value>
{
};
}
#endif