#ifndef ARRAY_INCLUDED
#define ARRAY_INCLUDED
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

#define DEBUG_ARRAY_ACCESS 0

#ifdef _WIN32
  #define ASSERT( x ) { if( !( x ) ) __debugbreak(); }
#else // !_WIN32
  #define ASSERT( x ) { if( !( x ) ) __builtin_trap (); }
#endif // _WIN32

inline void* m_aligned_malloc( size_t size , unsigned int alignment )
{
	// Allocate with enough room for a pointer and padding for alignment
	void* ptr = malloc( size + sizeof(size_t) + (alignment-1 ) );
	if( !ptr ) return NULL;

	// Offset into the pointer and round to the alignment
	void* data_ptr = (void*)( ( (size_t)ptr ) + (alignment-1) + sizeof(size_t) );
	data_ptr = (void*)( ( (size_t)data_ptr ) - ( ( (size_t)data_ptr )%alignment ) );

	// Set the address of the pointer
	*( (void**)( ( (size_t)data_ptr )-sizeof(size_t) ) ) = ptr;

	// Return the array
	return data_ptr;
}
#define m_aligned_free( ptr ) free( *( (void**)( ( (size_t)ptr ) - sizeof(size_t) ) ) )


#if DEBUG_ARRAY_ACCESS
#include "Array.inl"
#define      Pointer( ... )      Array< __VA_ARGS__ >
#define ConstPointer( ... ) ConstArray< __VA_ARGS__ >
template< class C > Array< C >        AllocArray( size_t size ,                          const char* name=NULL ){ return Array< C >( size , 1         , false , name ); }
template< class C > Array< C > AlignedAllocArray( size_t size , unsigned int alignment , const char* name=NULL ){ return Array< C >( size , alignment , false , name ); }
template< class C > void         FreeArray( Array< C >& a ) { a.Free( ); }
template< class C > void  AlignedFreeArray( Array< C >& a ) { a.Free( ); }
template< class C > Array< C > NullPointer( void ) { return Array< C >( ); }
template< class C > C*      PointerAddress( Array< C >& a ) { return a.pointer(); }
template< class C > Array< C >  GetPointer( C& c , size_t max=1 ) { return Array< C >::FromPointer( &c , 0 , max ); }
#else // !DEBUG_ARRAY_ACCESS
#define      Pointer( ... )       __VA_ARGS__*
#define ConstPointer( ... ) const __VA_ARGS__*
template< class C > C*     AllocArray( size_t size , const char* name=NULL ){ return (C*)malloc( sizeof(C) * size ); }
#define                     FreeArray( ptr ) if( ptr ) free( ptr ) , ptr = NULL
template< class C > C* AlignedAllocArray( size_t size , unsigned int alignment , const char* name=NULL ){ return (C*)m_aligned_malloc( sizeof(C)*size , alignment ); }
#define                 AlignedFreeArray( ptr ) if( ptr ) m_aligned_free( ptr ) , ptr = NULL

template< class C > C*    NullPointer( void ){ return NULL; }
template< class C > C* PointerAddress( C* c ){ return c; }
template< class C > C*     GetPointer( C& c , size_t max=1 ){ return &c; }
#endif // DEBUG_ARRAY_ACCESS
#endif // ARRAY_INCLUDED
