#ifndef AVS_ALIGNMENT_H
#define AVS_ALIGNMENT_H
#define IS_POWER2(n) ((n) && !((n) & ((n) - 1)))
#define IS_PTR_ALIGNED(ptr, align) (((uintptr_t)ptr & ((uintptr_t)(align-1))) == 0)
#define ALIGN_NUMBER(n, align) (((n) + (align)-1) & (~((align)-1)))
#define ALIGN_POINTER(ptr, align) (((uintptr_t)(ptr) + (align)-1) & (~(uintptr_t)((align)-1)))
#ifdef __cplusplus
#include <cassert>
#include <cstdlib>
#include <cstdint>
#include <avs/config.h>
#if defined(MSVC)
#define avs_alignas(x) __declspec(align(x))
#else
#define avs_alignas(x) alignas(x)
#endif
template<typename T>
static bool IsPtrAligned(T* ptr, size_t align)
{
assert(IS_POWER2(align));
return (bool)IS_PTR_ALIGNED(ptr, align);
}
template<typename T>
static T AlignNumber(T n, T align)
{
assert(IS_POWER2(align));
return ALIGN_NUMBER(n, align);
}
template<typename T>
static T* AlignPointer(T* ptr, size_t align)
{
assert(IS_POWER2(align));
return (T*)ALIGN_POINTER(ptr, align);
}
extern "C"
{
#else
#include <stdlib.h>
#endif
inline void* avs_malloc(size_t nbytes, size_t align)
{
if (!IS_POWER2(align))
return NULL;
size_t offset = sizeof(void*) + align - 1;
void *orig = malloc(nbytes + offset);
if (orig == NULL)
return NULL;
void **aligned = (void**)(((uintptr_t)orig + (uintptr_t)offset) & (~(uintptr_t)(align-1)));
aligned[-1] = orig;
return aligned;
}
inline void avs_free(void *ptr)
{
if (ptr == NULL)
return;
free(((void**)ptr)[-1]);
}
#ifdef __cplusplus
}
#undef IS_PTR_ALIGNED
#undef ALIGN_NUMBER
#undef ALIGN_POINTER
#endif
#endif