#ifndef C4DMISC_APIBASE_H__
#define C4DMISC_APIBASE_H__

/// @file
/// Main include file

#undef  _HAS_EXCEPTIONS
#define _HAS_EXCEPTIONS 0

#include <stddef.h>
#include <string.h>
#include <math.h>
#include <new>

#undef _HAS_COUNTER
#undef _HAS_STATIC_ASSERT
#define HAS_STD_TYPE_TRAITS

#if defined(__INTEL_COMPILER) &&  __INTEL_COMPILER>=1210 // right now the intel 12.1 beta compiler has 9999 as version number
	//#define _HAS_COUNTER doesnt work with the const string hack!!!
	#define _HAS_NULLPTR						// new feature of intel 12.1
	#define _HAS_MOVE_CONSTRUCTOR		// new feature of intel 12.0
	#define _HAS_DECLTYPE
	#define _HAS_STATIC_ASSERT
	#define _HAS_LAMBDAS
#elif defined(__INTEL_COMPILER) &&  __INTEL_COMPILER>=1200 // intel compiler 12.0
	//#define _HAS_COUNTER doesnt work with the const string hack!!!
	#undef _HAS_NULLPTR							// not supported by intel 12.0
	#define _HAS_MOVE_CONSTRUCTOR		// new feature of intel 12.0
	#define _HAS_DECLTYPE
	#define _HAS_STATIC_ASSERT
	#define _HAS_LAMBDAS
#elif defined(__clang__)
	#define _HAS_COUNTER
	#if __has_feature(cxx_rvalue_references)
		#define _HAS_MOVE_CONSTRUCTOR
	#endif
	#if __has_feature(cxx_nullptr)
		#define _HAS_NULLPTR
	#endif
	#if __has_feature(cxx_decltype)
		#if !defined(_HAS_DECLTYPE)
			#define _HAS_DECLTYPE 1
	#endif
	#endif
	#if __has_feature(cxx_static_assert)
		#define _HAS_STATIC_ASSERT
	#endif
	#if __has_feature(cxx_lambdas)
		#define _HAS_LAMBDAS
	#endif
	#if __has_feature(cxx_default_function_template_args)
		#define _HAS_DEFAULT_TEMPLATE_FUNCTION_ARGUMENTS
	#endif
	#define _HAS_BLOCKS
#elif (defined __PC)
	#define override  // override specifier not yet supported by MSVC, use empty macro
	#define _HAS_COUNTER
	#define _HAS_NULLPTR
	#define _HAS_MOVE_CONSTRUCTOR
	#if !defined(_HAS_DECLTYPE)
		#define _HAS_DECLTYPE 1
	#endif
	#define _HAS_STATIC_ASSERT
	#define _HAS_LAMBDAS
	#pragma warning(disable:4345)	// disable warning that new MSVC compilers (finally) do default-initalization of PODs like it is expected from the c++ standard
#elif defined(__GNUC__)
	#if ((__GNUC__ > 4) || (__GNUC_MINOR__ >= 6))
		// GCC >= 4.6 case (will be relevant for Linux)
		#define _HAS_NULLPTR
		#define _HAS_MOVE_CONSTRUCTOR
		#if !defined(_HAS_DECLTYPE)
			#define _HAS_DECLTYPE 1
		#endif
		#define _HAS_LAMBDAS
		#define _HAS_DEFAULT_TEMPLATE_FUNCTION_ARGUMENTS
	#elif defined(__MAC)	// GCC 4.2.1 on the Mac
// Theoretically gcc 4.2 and llvm gcc have blocks, but the gcc front end has a nasty bug that
// calls the destructor before the block is invoked (rdar://10007196 and  rdar://10258881).
//		#define _HAS_BLOCKS
	#endif
#endif

#ifdef _HAS_EXPLICIT_CONVERSION
	#define C4D_MISC_OPERATOR_BOOL explicit operator Bool
	#define C4D_MISC_OPERATOR_BOOL_TYPE Bool
	#define C4D_MISC_EXPLICIT_CONVERSION explicit
#else
	#define C4D_MISC_OPERATOR_BOOL operator void*
	#define C4D_MISC_OPERATOR_BOOL_TYPE (void*)
	#define C4D_MISC_EXPLICIT_CONVERSION
#endif

#ifndef _HAS_DECLTYPE
	// try the GCC extension typeof
	#define decltype typeof
#endif

#ifndef _HAS_STATIC_ASSERT
	#define static_assert(cond,str)														// dummy for old compiler
#endif

#ifdef _HAS_MOVE_CONSTRUCTOR
	#include <utility>																				// std::move defined here

	#ifndef APIBASE_H__
		#if !defined(_LIBCPP_UTILITY) && (defined(__MAC) || defined(__iOS) || (__LINUX && __INTEL_COMPILER>=1210))	// workaround for libstdc++ without move support

			#if !(__LINUX && __INTEL_COMPILER>=1210)
				#include <tr1/type_traits>
			#endif

			#undef HAS_STD_TYPE_TRAITS														// must use std::tr1 for type traits

			namespace std																					// add required c++11 support to old stdlib
			{
				template <typename T> struct remove_reference { typedef T type; };
				template <typename T> struct remove_reference<T&> { typedef T type; };
				template <typename T> struct remove_reference<T&&> { typedef T type;	};

				// accept either an lvalue or rvalue argument, and return it as an rvalue without triggering a copy construction
				template <typename T> typename remove_reference<T>::type&& move(T &&t)	{	return (typename remove_reference<T>::type&&) t; }

				// forward preserves the lvalue/rvalue-ness of the argument.
				template <typename T> T&& forward(typename remove_reference<T>::type& a) { return static_cast<T&&>(a); }

				template <typename T> struct remove_const { typedef T type; };
				template <typename T> struct remove_const<const T> { typedef T type; };

				// from windows std::lib
				// convenient template for integral constant types
				template<typename _Ty, _Ty _Val> struct integral_constant
				{
					static const _Ty value = _Val;
					typedef _Ty value_type;
					typedef integral_constant<_Ty, _Val> type;
				};

				typedef integral_constant<bool, true> true_type;
				typedef integral_constant<bool, false> false_type;

				// TEMPLATE CLASS is_lvalue_reference
				template<typename _Ty> struct is_lvalue_reference : false_type
				{	// determine whether _Ty is an lvalue reference
				};

				template<typename _Ty> struct is_lvalue_reference<_Ty&> : true_type
				{	// determine whether _Ty is an lvalue reference
				};

				// TEMPLATE CLASS is_rvalue_reference
				template<typename _Ty> struct is_rvalue_reference : false_type
				{	// determine whether _Ty is an rvalue reference
				};

				template<typename _Ty> struct is_rvalue_reference<_Ty&&> : true_type
				{	// determine whether _Ty is an rvalue reference
				};

				template<bool> struct _Cat_base;
				template<> struct _Cat_base<false> : false_type
				{	// base class for type predicates
				};

				template<> struct _Cat_base<true> : true_type
				{	// base class for type predicates
				};

				// TEMPLATE CLASS is_reference
				template<typename _Ty> struct is_reference : _Cat_base<is_lvalue_reference<_Ty>::value || is_rvalue_reference<_Ty>::value>
				{	// determine whether _Ty is a reference
				};
				// from windows std::lib
				template <typename T> struct is_const : false_type {};
				template <typename T> struct is_const<const T> : true_type {};

				#if !(__LINUX && __INTEL_COMPILER>=1210)
				// add supported type traits to std name space
				template <typename T> struct is_pod : public std::tr1::is_pod<T> {};
				#else
				template <typename T> struct is_pod { static const bool value = false; };
				#endif
			}
		#else																										// stdlib with c++11 support
			#include <type_traits>
		#endif

		// from boost.enable_if.hpp
		template <bool B, typename T = void> struct disable_if_c { typedef T type; };
		template <typename T> struct disable_if_c<true, T> {};
		template <typename COND, typename T = void> struct disable_if : public disable_if_c<COND::value, T> {};
		/// disable if macro to force the compiler to do the right things with overloaded && in templates
		#define DISABLE_IF_REFERENCE(TYPE,RET) typename disable_if< std::is_reference<TYPE>, RET>::type
	#endif

	#define C4D_MISC_FORWARD_PARAMETER(T) T&&
	#define C4D_MISC_MOVE_TYPE(T)					T&&
	#define C4D_MISC_MOVE_BASE_CLASS(src, ...)	__VA_ARGS__(std::move(src))
#else																												// no rvalues, dummy methods for move and forward
	#include <tr1/type_traits>
	#undef HAS_STD_TYPE_TRAITS																// must use std::tr1 for type traits
	#define DISABLE_IF_REFERENCE(TYPE,RET) RET

	namespace c4d_misc
	{
		// this template is just a wrapper around a class that does nothing except being used for
		template <typename T> struct MoveTypeWrapper : public T
		{
			T* operator &()																				// address operator must return T* instead of MoveTypeWrapper<T>*
			{
				return this;
			}
		};

		// specialization for all pointer types types since you can't inherit from them
		template <typename T> struct MoveTypeWrapper<T*>				{ operator T*&()									{ return *(T**) this; }	};

		// the following are the specializations for integral types since you can't inherit from them
		template <> struct MoveTypeWrapper<bool>								{ operator bool&()								{ return *(bool*) this; }	};
		template <> struct MoveTypeWrapper<char>								{ operator char&()								{ return *(char*) this; }	};
		template <> struct MoveTypeWrapper<short>								{ operator short&()								{ return *(short*) this; }	};
		template <> struct MoveTypeWrapper<int>									{ operator int&()									{ return *(int*) this; }	};
		template <> struct MoveTypeWrapper<long>								{ operator long&()								{ return *(long*) this; }	};
		template <> struct MoveTypeWrapper<long long>						{ operator long long&()						{ return *(long long*) this; }	};

		template <> struct MoveTypeWrapper<unsigned char>				{ operator unsigned char&()				{ return *(unsigned char*) this; }	};
		template <> struct MoveTypeWrapper<unsigned short>			{ operator unsigned short&()			{ return *(unsigned short*) this; }	};
		template <> struct MoveTypeWrapper<unsigned int>				{ operator unsigned int&()				{ return *(unsigned int*) this; }	};
		template <> struct MoveTypeWrapper<unsigned long>				{ operator unsigned long&()				{ return *(unsigned long*) this; }	};
		template <> struct MoveTypeWrapper<unsigned long long>	{ operator unsigned long long&()	{ return *(unsigned long long*) this; }	};

		template <> struct MoveTypeWrapper<float>								{ operator float&()								{ return *(float*) this; }	};
		template <> struct MoveTypeWrapper<double>							{ operator double&()							{ return *(double*) this; }	};
	}

	#ifndef APIBASE_H__
		namespace std
		{
			// std::move returns a c4d_misc::MoveTypeWrapper<T>&. For integral types there's an operator T&() that
			// converts this to T& and for classes MoveTypeWrapper<T>& inside a move constructor is equivalent to
			// T& because it inherits from T.
			template <typename T>	c4d_misc::MoveTypeWrapper<T>&  move(T& a)		{ return *(c4d_misc::MoveTypeWrapper<T>*) &a;	}
			template <typename T>	c4d_misc::MoveTypeWrapper<T>&  move(const T& a)		{ return *(c4d_misc::MoveTypeWrapper<T>*) &a;	}	// this one is a gcc 4.2 hack only
			template <typename T>	T& forward(T& a)	{ return a;	}			// does nothing
			template <typename T>	const T& forward(const T& a)	{ return a;	}			// does nothing

			template <typename T> struct remove_const { typedef T type; };
			template <typename T> struct remove_const<const T> { typedef T type; };

			// from windows std::lib
			// convenient template for integral constant types
			template<typename _Ty, _Ty _Val> struct integral_constant
			{
				static const _Ty value = _Val;
				typedef _Ty value_type;
				typedef integral_constant<_Ty, _Val> type;
			};

			typedef integral_constant<bool, true> true_type;
			typedef integral_constant<bool, false> false_type;

			template <typename T> struct is_const : false_type {};
			template <typename T> struct is_const<const T> : true_type {};

			// add supported type traits to std name space
			template <typename T> struct is_pod : public std::tr1::is_pod<T> {};
		}
	#endif

	#define C4D_MISC_FORWARD_PARAMETER(T) const T&

	// Objects that support CopyFrom() must support move semantics
	// if no move semantics are available we define our own type of move constructor
	// as soon as c++11 is mandatory we can replace the macro with T&& src and that's it
	#define C4D_MISC_MOVE_TYPE(T)	c4d_misc::MoveTypeWrapper<T>&

	// In the move constructor you can use std::move() to initialize class members. Extra care must be taken if you want to call
	// the move constructor of your base class. Instead of BaseClass(std::move(src)) you should call C4D_MISC_MOVE_BASE_CLASS(src, BaseClass).
	// For compilers with C++11 rvalue references this is equivalent to BaseClass(std::move(src)), but for older compilers it makes
	// sure that std::move() is called with a reference to src's base class (otherwise the compiler would try to call the copy constructor).
	#define C4D_MISC_MOVE_BASE_CLASS(src, ...)	__VA_ARGS__(std::move(static_cast<__VA_ARGS__&>(src)))
#endif

//#pragma optimize("",off)

#ifndef _HAS_NULLPTR
	const class NULLPTR
	{
		public:
			template<typename T> operator T*() const	{ return 0; }
			template<typename C, typename T>	operator T C::*() const	{ return 0; }
		private:
			void operator &() const;
	} nullptr = {};
#endif

#ifdef __GNUC__
	#define alignof __alignof__
#else
	#define alignof(C) SIZEOF(void*) // TODO: (sven) add something like http://llvm.org/docs/doxygen/html/AlignOf_8h_source.html
#endif


namespace c4d_misc {

/// \defgroup STRUCTURES Data Structures
/// @{
/// @}

// Use C4D_MISC_DLL_PUBLIC in the declaration of a variable or function to export symbols (project settings make them private by default), e.g.
// C4D_MISC_DLL_PUBLIC int variable;
// extern "C" C4D_MISC_DLL_PUBLIC void function();

#ifdef __PC
	#define	C4D_MISC_DLL_PUBLIC				__declspec(dllexport)
	#define	C4D_MISC_NO_INLINE				__declspec(noinline)
	#define C4D_MISC_ALIGN(_x_, _a_)	__declspec(align(_a_)) _x_
	#define	ATTRIBUTE_USED
#elif defined __ANDROID
	#define	C4D_MISC_DLL_PUBLIC				__attribute__((visibility("default")))
	#define	C4D_MISC_NO_INLINE				__attribute__ ((noinline))
	#define C4D_MISC_ALIGN(_x_, _a_)	_x_ __attribute__((aligned(_a_)))
	#define	ATTRIBUTE_USED						__attribute__((used))
#else
	#define	C4D_MISC_DLL_PUBLIC				__attribute__((visibility("default")))
	#define	C4D_MISC_NO_INLINE				__attribute__ ((noinline))
	#define C4D_MISC_ALIGN(_x_, _a_)	_x_ __attribute__((aligned(_a_)))

	// use ATTRIBUTE_USED to tell the linker it must not dead-strip a function or static variable (even if it determines that the rest of the program does not refer to the object)
	#define	ATTRIBUTE_USED						__attribute__((used))
#endif

#if (__LP64__ || _WIN64) && !defined(__C4D_64BIT)
	#define __C4D_64BIT
#endif

#ifdef __LINUX
	typedef short int	          Int16;
	typedef unsigned short int	UInt16;
	typedef signed int					Int32;  // m64 option makes int 32 bit
	typedef unsigned int				UInt32; // m64 option makes int 32 bit
#elif defined __MAC || defined __iOS
	typedef short int	Int16;
	typedef unsigned short int	UInt16;
	#ifdef __C4D_64BIT
		typedef int Int32;
		typedef unsigned int UInt32;
	#else
		typedef long Int32;
		typedef unsigned long	UInt32;
	#endif
#else
	typedef short			          Int16;	///< 16 bit signed int
	typedef unsigned short			UInt16;	///< 16 bit unsigned int
	typedef long 								Int32;	///< 32 bit signed int
	typedef unsigned long				UInt32;	///< 32 bit unsigned int
#endif

typedef bool                Bool;			///< boolean type, possible values are only false/true, 8 bit
typedef float								Float32;	///< 32 bit floating point value (float)
typedef double							Float64;	///< 64 bit floating point value (double)
typedef void*								Hndl;			///< pointer type (void*)
typedef char								Char;			///< signed 8 bit character
typedef unsigned char				UChar;		///< unsigned 8 bit character

#ifdef __C4D_64BIT
	#ifdef __INTEL_COMPILER
		#ifdef __LINUX
			typedef long									Int64;		// m64 option makes long 64 bit
			typedef unsigned long					UInt64;		// m64 option makes long 64 bit
			typedef long									Int;			// m64 option makes long 64 bit
			typedef unsigned long					UInt;			// m64 option makes long 64 bit
		#else
			typedef long long							Int64;
			typedef unsigned long long		UInt64;
			typedef signed long long			Int;
			typedef unsigned long long		UInt;
		#endif
	#elif defined __MAC || defined __iOS
		typedef signed long long				Int64;
		typedef unsigned long long			UInt64;
		typedef signed long long				Int;
		typedef unsigned long long			UInt;
	#elif defined __LINUX
		typedef signed long long				Int64;
		typedef unsigned long long			UInt64;
		typedef signed long long				Int;
		typedef unsigned long long			UInt;
	#else
		typedef __int64									Int64;
		typedef unsigned __int64				UInt64;
		typedef signed __int64					Int;
		typedef unsigned __int64				UInt;
	#endif
#else
	#ifdef __LINUX
		typedef long long								Int64;
		typedef unsigned long long			UInt64;
		typedef signed int							Int;
		typedef unsigned int						UInt;
	#elif defined __MAC || defined __iOS
		typedef signed long long				Int64;
		typedef unsigned long long			UInt64;
		typedef signed long							Int;
		typedef unsigned long						UInt;
	#elif	defined __ANDROID
		typedef signed long long				Int64;
		typedef unsigned long long			UInt64;
		typedef signed long							Int;
		typedef unsigned long						UInt;
	#else
		typedef __int64									Int64;		///< signed 64 bit int, always 64 bit even in 32 bit code
		typedef unsigned __int64				UInt64;		///< unsigned 64 bit int, always 64 bit even in 32 bit code
		typedef signed long							Int;			///< signed 32/64 bit int, size depends on the platform
		typedef unsigned long						UInt;			///< unsigned 32/64 bit int, size depends on the platform
	#endif
#endif

/// current floating point model.
/// right now it's adjusted to Float64==64 bit but maybe it's redefined to Float32 anytime
typedef Float64 Float;

static const Int InvalidArrayIndex = -1;	///< invalid array index (e.g. for array index out of bounds)

/// This statement needs to be used for any case in a switch the contains code, but does not call break.
/// An example:
/// @code
/// switch(condition)
/// {
///   case 0:
///     ...do something...
///   // SWITCH_FALLTHROUGH
///
///   case 1:
///     ...do something...
///		  break;
///  }
/// @endcode
#define SWITCH_FALLTHROUGH

#ifndef DISALLOW_COPY_AND_ASSIGN
/// This statement needs to be used at the beginning of any class that cannot be copied
/// An example:
/// @code
/// class MyClass
/// {
///   DISALLOW_COPY_AND_ASSIGN(MyClass);
///	  ...
///	};
///	@endcode

	#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
		TypeName(const TypeName&); \
		void operator =(const TypeName&);
#endif

#ifndef MOVE_ASSIGNMENT_OPERATOR
/// This statement automatically creates a move assignment operator from an existing move constructor. It needs to be written in the public: section.
/// An example:
/// @code
/// class MyClass
/// {
///   DISALLOW_COPY_AND_ASSIGN(MyClass);
/// public:
///   MOVE_ASSIGNMENT_OPERATOR(MyClass);
///	  ...
///	};
///	@endcode

	#define MOVE_ASSIGNMENT_OPERATOR(TypeName) \
		TypeName& operator =(C4D_MISC_MOVE_TYPE(TypeName) src) \
		{ \
			if (this != &src) \
			{ \
				this->~TypeName(); \
				new (this) TypeName(std::move(src)); \
			} \
			return *this; \
		}
#endif

//----------------------------------------------------------------------------------------
/// Automatic detection of CopyFrom() method using SFINAE.
/// If a class implements Bool CopyFrom(T& src) the constant TestForCopyFromMember<T>::IsSupported
/// will be true.
/// For this case the template argument deduction prefers the conversion of 0 to a pointer
/// (using Char TestForCopyFromFunction(TestForCopyFromWrapper<T, &T::CopyFrom>*)) over
/// binding to an ellipsis parameter (Int16 TestForCopyFromFunction(...)).
/// If a class does  not implement CopyFrom() only Int16 TestForCopyFromFunction(...) is available.
/// Both cases can be distinguished by having different size return values.
//----------------------------------------------------------------------------------------
template <typename T, Bool (T::*f)(const T&)> struct TestForCopyFromWrapper {};
template <typename T> Char  TestForCopyFromFunction(TestForCopyFromWrapper<T, &T::CopyFrom>*);	// template argument can only be dededuced if T contains a CopyFrom() method
template <typename T> Int16 TestForCopyFromFunction(...);		// default case for classes without CopyFrom(), must have different size return value
template <typename T> struct TestForCopyFromMember
{
	static const bool isSupported = sizeof(TestForCopyFromFunction<T>(0)) == sizeof(Char);
};

template <typename T, Bool hasCopyFrom> class ObjectConstructor
{
};

// for classes with copy constructor that cannot fail (may or may not support move semantics)
template <typename T> class ObjectConstructor<T, false>
{
public:
	//----------------------------------------------------------------------------------------
	/// Construct an object using new (dst) T(src), cannot fail.
	/// @param[out] dst								Copied object will be placed here (can be nullptr)
	/// @param[in] src								Object to be copied.
	/// @return												Same as dst.
	//----------------------------------------------------------------------------------------
	static T* Copy(T* dst, const T&src)
	{
		return new (dst) T(src);
	}

	//----------------------------------------------------------------------------------------
	/// Copy assignment, cannot fail.
	/// @param[out] dst								Copy will be placed here (dst must have already been constructed)
	/// @param[in] src								Object to be copied.
	/// @return												Always true.
	//----------------------------------------------------------------------------------------
	static Bool AssignCopy(T& dst, const T& src)
	{
		dst = src;
		return true;
	}
};

// for classes with complex copy constructor (implements CopyFrom() and move constructor)
template <typename T> class ObjectConstructor<T, true>
{
public:
	//----------------------------------------------------------------------------------------
	/// Construct an object using CopyFrom() (like new (dst) T(src) but with error check)
	/// If copy construction fails the object will be automatically destructed, dst will
	/// point to uninitialized memory like before the call.
	/// @param[out] dst								Copied object will be placed here (can be nullptr)
	/// @param[in] src								Object to be copied.
	/// @return												Same as dst or nullptr (CopyFrom() failed)
	//----------------------------------------------------------------------------------------
	static T* Copy(T* dst, const T&src)
	{
		if (dst)
		{
			new (dst) T();																				// initialize T
			if (dst->CopyFrom(src) == false)											// copy failed?
			{
				dst->~T();																					// destruct
				dst = nullptr;
			}
		}
		return dst;
	}

	//----------------------------------------------------------------------------------------
	/// Copy assignment using CopyFrom()
	/// @param[out] dst								Copy will be placed here (dst must have already been constructed)
	/// @param[in] src								Object to be moved.
	/// @return												True if successful.
	//----------------------------------------------------------------------------------------
	static Bool AssignCopy(T& dst, const T& src)
	{
		return dst.CopyFrom(src);
	}
};

//----------------------------------------------------------------------------------------
/// call new (dst) T(src) or dst->CopyFrom(src) for non-trivial objector copy constructor
//----------------------------------------------------------------------------------------
template <typename T> inline T* NewCopy(T* dst, const T& src)
{
	return ObjectConstructor<T, TestForCopyFromMember<T>::isSupported>::Copy(dst, src);
}

//----------------------------------------------------------------------------------------
/// copy assignment
//----------------------------------------------------------------------------------------
template <typename T> inline Bool AssignCopy(T& dst, const T& src)
{
	return ObjectConstructor<T, TestForCopyFromMember<T>::isSupported>::AssignCopy(dst, src);
}

template <typename T> struct AlwaysFalse { static bool const value = false; };


const Int64  MINVALUE_INT64  = -9223372036854775807LL - 1;			///< the minimum value an Int64 can represent
const Int64  MAXVALUE_INT64  =  9223372036854775807LL;					///< the maximum value an Int64 can represent
const UInt64 MAXVALUE_UINT64 =  0xffffffffffffffffULL;					///< the maximum value an UInt64 can represent

const Int32  MINVALUE_INT32  = -2147483647L - 1;								///< the minimum value an Int32 can represent
const Int32  MAXVALUE_INT32  =  2147483647L;										///< the maximum value an Int32 can represent
const UInt32 MAXVALUE_UINT32 =  (UInt32) 0xffffffffULL;					///< the maximum value an UInt32 can represent

const Int16  MINVALUE_INT16  = -32767 - 1;											///< the minimum value an Int16 can represent
const Int16  MAXVALUE_INT16  =  32767;													///< the maximum value an Int16 can represent
const UInt16 MAXVALUE_UINT16 =  0xffff;													///< the maximum value an UInt16 can represent

#ifdef __C4D_64BIT
	const Int64  MINVALUE_INT  = MINVALUE_INT64;
	const Int64  MAXVALUE_INT  = MAXVALUE_INT64;
	const UInt64 MAXVALUE_UINT = MAXVALUE_UINT64;
#else
	const Int  MINVALUE_INT    = MINVALUE_INT32;									///< the minimum value an Int can represent
	const Int  MAXVALUE_INT    = MAXVALUE_INT32;									///< the maximum value an Int can represent
	const UInt MAXVALUE_UINT   = MAXVALUE_UINT32;									///< the maximum value an UInt can represent
#endif

const Float32 MINVALUE_FLOAT32 = -3.402823466e+38f;							///< the minimum value a Float32 can represent
const Float32 MAXVALUE_FLOAT32 =  3.402823466e+38f;							///< the maximum value a Float32 can represent

const Float64 MINVALUE_FLOAT64 = -1.7976931348623158e+308;			///< the minimum value a Float64 can represent
const Float64 MAXVALUE_FLOAT64 =  1.7976931348623158e+308;			///< the maximum value a Float64 can represent

const Float   MINVALUE_FLOAT   = -1.7976931348623158e+308;			///< the minimum value a Float can represent
const Float   MAXVALUE_FLOAT   =  1.7976931348623158e+308;			///< the maximum value a Float can represent

const Float32 MINVALUE_INT32_FLOAT32  = -2147483520.0f;					///< minimum Float32 value that can be represented by Int32 (-0x7FFFFF80). Lower values will results in an overflow
const Float32 MAXVALUE_INT32_FLOAT32	=  2147483520.0f;					///< maximum Float32 value that can be represented by Int32 ( 0x7FFFFF80). Higher values will results in an overflow

const Float64 MINVALUE_INT64_FLOAT64  = -9223372036854775295.0; ///< minimum Float64 value that can be represented by Int64 (-0x7ffffffffffffdff). Lower values will results in an overflow
const Float64 MAXVALUE_INT64_FLOAT64  =  9223372036854775295.0; ///< maximum Float64 value that can be represented by Int64 ( 0x7ffffffffffffdff). Higher values will results in an overflow

const Float32 MINRANGE_FLOAT32	= -1.0e10f; ///< 'safe' minimum range for Float32. Guarantees that multiplication of two numbers doesn't produce an overflow
const Float32 MAXRANGE_FLOAT32	=  1.0e10f; ///< 'safe' maximum range for Float32. Guarantees that multiplication of two numbers doesn't produce an overflow

const Float   MINRANGE_FLOAT		= -1.0e100;	///< 'safe' minimum range for Float64. Guarantees that multiplication of two numbers doesn't produce an overflow
const Float   MAXRANGE_FLOAT		=  1.0e100; ///< 'safe' maximum range for Float64. Guarantees that multiplication of two numbers doesn't produce an overflow

const Float64 MINRANGE_FLOAT64  = -1.0e100;	///< 'safe' minimum range for Float. Guarantees that multiplication of two numbers doesn't produce an overflow
const Float64 MAXRANGE_FLOAT64	=  1.0e100; ///< 'safe' maximum range for Float. Guarantees that multiplication of two numbers doesn't produce an overflow

#ifndef NOTOK
	const Int NOTOK = -1; ///< constant used for special cases
#endif

/// floating point constant: PI
const Float64 PI			= 3.1415926535897932384626433832795;

/// floating point constant: 1.0 / PI
const Float64 PI_INV	= 0.31830988618379067153776752674508;

/// floating point constant: 2.0 * PI
const Float64 PI2			= 6.283185307179586476925286766559;

/// floating point constant: 1.0 / (2.0 * PI)
const Float64 PI2_INV	= 0.15915494309189533576888376337251;

/// floating point constant: 0.5 * PI
const Float64 PI05		= 1.5707963267948966192313216916398;

/// Clip a floating point number against the lower limit 0 and the upper limit 1. The result will be returned.
inline Float32 Clamp01(Float32 a) { if (a < 0.0f) return 0.0f; if (a > 1.0f) return 1.0f; return a; }

/// Clip a floating point number against the lower limit 0 and the upper limit 1. The result will be returned.
inline Float64 Clamp01(Float64 a) { if (a < 0.0) return 0.0; if (a > 1.0) return 1.0; return a; }

#if defined __MAC || defined __iOS
	inline Float32 Sin(Float32 val) { return sinf(val); }
	inline Float64 Sin(Float64 val) { return sin(val); }

	inline Float32 Cos(Float32 val) { return cosf(val); }
	inline Float64 Cos(Float64 val) { return cos(val); }

	inline Float32 Tan(Float32 val) { return tanf(val); }
	inline Float64 Tan(Float64 val) { return tan(val); }

	inline Float32 ATan(Float32 val) { return atanf(val); }
	inline Float64 ATan(Float64 val) { return atan(val); }

	inline Float32 ATan2(Float32 valA, Float32 valB) { return atan2f(valA, valB); }
	inline Float64 ATan2(Float64 valA, Float64 valB) { return atan2(valA, valB); }

	inline Float32 Exp(Float32 val) { return expf(val); }
	inline Float64 Exp(Float64 val) { return exp(val); }

	inline Float32 Ln(Float32 val) { return logf(val); }
	inline Float64 Ln(Float64 val) { return log(val); }

	inline Float32 Ln10(Float32 val) { return log10f(val); }
	inline Float64 Ln10(Float64 val) { return log10(val); }

	inline Float32 Sqrt(Float32 val) { return sqrtf(val); }
	inline Float64 Sqrt(Float64 val) { return sqrt(val); }

	inline Float32 Floor(Float32 val) { return floorf(val); }
	inline Float64 Floor(Float64 val) { return floor(val); }

	inline Float32 Ceil(Float32 val) { return ceilf(val); }
	inline Float64 Ceil(Float64 val) { return ceil(val); }

	inline Float32 Pow(Float32 v1, Float32 v2) { return powf(v1,v2); }
	inline Float64 Pow(Float64 v1, Float64 v2) { return pow(v1,v2); }

	inline Float32 Sinh(Float32 val) { return sinhf(val); }
	inline Float64 Sinh(Float64 val) { return sinh(val); }

	inline Float32 Cosh(Float32 val) { return coshf(val); }
	inline Float64 Cosh(Float64 val) { return cosh(val); }

	inline Float32 Tanh(Float32 val) { return tanhf(val); }
	inline Float64 Tanh(Float64 val) { return tanh(val); }

	inline Float32 FMod(Float32 v1, Float32 v2) { return fmodf(v1,v2); }
	inline Float64 FMod(Float64 v1, Float64 v2) { return fmod(v1,v2); }

	inline Float32 Abs(Float32 val) { return fabsf(val); }
	inline Float64 Abs(Float64 val) { return fabs(val); }
#else

	/// Calculates the sine of a value.
	inline Float32 Sin(Float32 val) { return sin(val); }
	/// Calculates the sine of a value.
	inline Float64 Sin(Float64 val) { return sin(val); }

	/// Calculates the cosine of a value.
	inline Float32 Cos(Float32 val) { return cos(val); }
	/// Calculates the cosine of a value.
	inline Float64 Cos(Float64 val) { return cos(val); }

	/// Calculates the tangent of a value. Note that the input needs to be checked for proper range, so that no exceptions will be generated.
	inline Float32 Tan(Float32 val) { return tan(val); }
	/// Calculates the tangent of a value. Note that the input needs to be checked for proper range, so that no exceptions will be generated.
	inline Float64 Tan(Float64 val) { return tan(val); }

	/// Calculates the arcustangens of a value.
	inline Float32 ATan(Float32 val) { return atan(val); }
	/// Calculates the arcustangens of a value.
	inline Float64 ATan(Float64 val) { return atan(val); }

	/// Calculates the arcustangens2 of a value.
	inline Float32 ATan2(Float32 valA, Float32 valB) { return atan2(valA, valB); }
	/// Calculates the arcustangens2 of a value.
	inline Float64 ATan2(Float64 valA, Float64 valB) { return atan2(valA, valB); }

	/// Calculates e^value.
	inline Float32 Exp(Float32 val) { return exp(val); }
	/// Calculates e^value.
	inline Float64 Exp(Float64 val) { return exp(val); }

	/// Calculates logarithm of a value. Note that the input needs to be positive, so that no exceptions will be generated.
	inline Float32 Ln(Float32 val) { return log(val); }
	/// Calculates logarithm of a value. Note that the input needs to be positive, so that no exceptions will be generated.
	inline Float64 Ln(Float64 val) { return log(val); }

	/// Calculates logarithm with base 10 of a value. Note that the input needs to be positive, so that no exceptions will be generated.
	inline Float32 Ln10(Float32 val) { return log10(val); }
	/// Calculates logarithm with base 10 of a value. Note that the input needs to be positive, so that no exceptions will be generated.
	inline Float64 Ln10(Float64 val) { return log10(val); }

	/// Calculates square root of a value. Note that the input must not be be negative, so that no exceptions will be generated.
	inline Float32 Sqrt(Float32 val) { return sqrt(val); }
	/// Calculates square root of a value. Note that the input must not be be negative, so that no exceptions will be generated.
	inline Float64 Sqrt(Float64 val) { return sqrt(val); }

	/// Calculates the largest previous integer number.
	inline Float32 Floor(Float32 val) { return floor(val); }
	/// Calculates the largest previous integer number.
	inline Float64 Floor(Float64 val) { return floor(val); }

	/// Calculates the smallest following integer number.
	inline Float32 Ceil(Float32 val) { return ceil(val); }
	/// Calculates the smallest following integer number.
	inline Float64 Ceil(Float64 val) { return ceil(val); }

	/// Calculates v1^v2
	inline Float32 Pow(Float32 v1, Float32 v2) { return pow(v1,v2); }
	/// Calculates v1^v2
	inline Float64 Pow(Float64 v1, Float64 v2) { return pow(v1,v2); }

	/// Calculates hyperbolic sine
	inline Float32 Sinh(Float32 val) { return sinh(val); }
	/// Calculates hyperbolic sine
	inline Float64 Sinh(Float64 val) { return sinh(val); }

	/// Calculates hyperbolic cosine
	inline Float32 Cosh(Float32 val) { return cosh(val); }
	/// Calculates hyperbolic cosine
	inline Float64 Cosh(Float64 val) { return cosh(val); }

	/// Calculates hyperbolic tangent
	inline Float32 Tanh(Float32 val) { return tanh(val); }
	/// Calculates hyperbolic tangent
	inline Float64 Tanh(Float64 val) { return tanh(val); }

	/// Calculates floating point modulo
	inline Float32 FMod(Float32 v1, Float32 v2) { return fmod(v1,v2); }
	/// Calculates floating point modulo
	inline Float64 FMod(Float64 v1, Float64 v2) { return fmod(v1,v2); }

	/// Calculates the absolute value of a floating point number.
	inline Float32 Abs(Float32 f) { return fabs(f); }
	/// Calculates the absolute value of a floating point number.
	inline Float64 Abs(Float64 f) { return fabs(f); }
#endif

/// Calculates the reciprocal value (multiplicative inverse). If the input value is zero, zero will be returned for safety to avoid exceptions.
inline Float32 Inverse(Float32 f) { return (f == 0.0f) ? 0.0f : 1.0f / f; }

/// Calculates the reciprocal value (multiplicative inverse). If the input value is zero, zero will be returned for safety to avoid exceptions.
inline Float64 Inverse(Float64 f) { return (f == 0.0) ? 0.0 : 1.0 / f; }

#ifndef SIZEOF
	/// Calculates the size of a datatype or element.
	#define SIZEOF(x) ((c4d_misc::Int)sizeof(x))
#endif

/// Calculates the absolute value of any data type
template <typename X> inline X Abs(X f) { if (f<0) return -f; return f; }

/// Calculates the minimum of two values and return it.
template <typename X> inline X Min(X a, X b) { if (a<b) return a; return b; }

/// Calculates the maximum of two values and return it.
template <typename X> inline X Max(X a, X b) { if (a<b) return b; return a; }

/// Swaps two values. If available, move semantics will be used.
template <typename X> inline void Swap(X &a, X &b) { X c(std::move(a)); a = std::move(b); b = std::move(c); }

/// Clips a value against a lower and upper limit. The new value is returned.
template <typename X> inline X Clamp(X value, X lowerLimit, X upperLimit) { if (value < lowerLimit) return lowerLimit; if (value > upperLimit) return upperLimit; return value; }

/// Calculates square difference of two values
template <typename X> inline Float Sqr(X a, X b) { X tmp = a-b; return tmp*tmp; }

/// Calculates square of a value
template <typename X> inline Float Sqr(X a) { return a*a; }

/// Calculates arcsine. The input value is clipped for safety to avoid exceptions.
inline Float32 ASin(Float32 val) { if(val>=1.0f) return Float32(PI05); else if (val<=-1.0f) return Float32(-PI05); return asinf(val); }

/// Calculates arcsine. The input value is clipped for safety to avoid exceptions.
inline Float64 ASin(Float64 val) { if(val>=1.0f) return Float32(PI05); else if(val<=-1.0f) return Float32(-PI05); return asin(val); }

/// Calculates arccosine. The input value is clipped for safety to avoid exceptions.
inline Float32 ACos(Float32 val) { if(val>=1.0f) return 0.0f; else if (val<=-1.0f) return Float32(PI); return acosf(val); }

/// Calculates arccosine. The input value is clipped for safety to avoid exceptions.
inline Float64 ACos(Float64 val) { if(val>=1.0f) return 0.0f; else if(val<=-1.0f) return Float32(PI); return acos(val); }

/// Calculates logarithm with base 2
inline Float32 Ld(Float32 r) { return Ln(r) / 0.69314718055994530941723212145818f; }

/// Calculates logarithm with base 2
inline Float64 Ld(Float64 r) { return Ln(r) / 0.69314718055994530941723212145818; }

/// Converts float value from degrees to radians
inline Float32 Rad(Float32 r)   { return ((r)*Float32(PI)/180.0f); }

/// Converts float value from degrees to radians
inline Float64 Rad(Float64 r)   { return ((r)*PI/180.0); }

/// Converts float value from radians to degrees
inline Float32 Deg(Float32 r)   { return ((r)*180.0f/Float32(PI)); }

/// Converts float value from radians to degrees
inline Float64 Deg(Float64 r)   { return ((r)*180.0/PI); }

/// Safely converts a 32 bit float value into Int32.
/// The resulting value will be clipped against the Int64 boundaries, without raising an exception.
inline Int32 SAFEINT32(Float32 x)
{
	if (x<=MINVALUE_INT32_FLOAT32)
		return MINVALUE_INT32;
	else if (x>=MAXVALUE_INT32_FLOAT32)
		return MAXVALUE_INT32;
	return Int32(x);
}

/// Safely converts a 64 bit float value into Int32.
/// The resulting value will be clipped against the Int64 boundaries, without raising an exception.
inline Int32 SAFEINT32(Float64 x)
{
	if (x<=(Float64)MINVALUE_INT32)
		return MINVALUE_INT32;
	else if (x>=(Float64)MAXVALUE_INT32)
		return MAXVALUE_INT32;
	return Int32(x);
}

/// Safely converts a 32 bit float value into Int64.
/// The resulting value will be clipped against the Int64 boundaries, without raising an exception.
inline Int64 SAFEINT64(Float32 x)
{
	if (x<=MINVALUE_INT32_FLOAT32)
		return (Int64)MINVALUE_INT32;
	else if (x>=MAXVALUE_INT32_FLOAT32)
		return (Int64)MAXVALUE_INT32;
	return Int64(x);
}

/// Safely converts a 64 bit float value into Int64.
/// The resulting value will be clipped against the Int64 boundaries, without raising an exception
inline Int64 SAFEINT64(Float64 x)
{
	if (x<=MINVALUE_INT64_FLOAT64)
		return MINVALUE_INT64;
	else if (x>=MAXVALUE_INT64_FLOAT64)
		return MAXVALUE_INT64;
	return Int64(x);
}

#ifdef __C4D_64BIT
	/// Safely converts a 64 bit float value into Int.
	/// The resulting value will be clipped against the Int boundaries, without raising an exception
	inline Int SAFEINT(Float64 x) { return SAFEINT64(x); }

	/// Safely converts a 32 bit float value into Int.
	/// The resulting value will be clipped against the Int boundaries, without raising an exception
	inline Int SAFEINT(Float32 x) { return SAFEINT64(x); }
#else
	/// Safely converts a 64 bit float value into Int.
	/// The resulting value will be clipped against the Int boundaries, without raising an exception
	inline Int SAFEINT(Float64 x) { return SAFEINT32(x); }

	/// Safely converts a 32 bit float value into Int.
	/// The resulting value will be clipped against the Int boundaries, without raising an exception
	inline Int SAFEINT(Float32 x) { return SAFEINT32(x); }
#endif

//----------------------------------------------------------------------------------------
/// Assigns the maximum of two values to the first value.
/// @param[in,out] a							First value.
/// @param[in] b									Second value.
//----------------------------------------------------------------------------------------
template <typename T> inline void SetMax(T& a, const T& b)
{
	if (b > a)
	{
		a = b;
	}
}

//----------------------------------------------------------------------------------------
/// Assigns the minimum of two values to the first value.
/// @param[in,out] a							First value.
/// @param[in] b									Second value.
//----------------------------------------------------------------------------------------
template <typename T> inline void SetMin(T& a, const T& b)
{
	if (b < a)
	{
		a = b;
	}
}

/// @}

inline Int Align(Int value, Int alignment)
{
	return (value + (alignment - 1)) & ~(alignment - 1);
}

template <typename T> inline T* Align(T* value, Int alignment)
{
	return (T*) Align((Int) value, alignment);
}

// use this in a statement like
// DerivedFromAssertion<T, B>();
// to assert at compile-time that T is derived from B (or the same)
template<typename T, typename B> struct DerivedFromAssertion
{
	static void Check(B* b) {}
	DerivedFromAssertion() {Check((T*) nullptr);}
};


typedef Char FalseType;
typedef Int TrueType;

#define IS_TRUE_TYPE(E) (sizeof(E) == sizeof(c4d_misc::TrueType))

// use Select<b, T, F>::Type to choose type T for b==true and type F for b==false
template <Bool, typename, typename> class Select;

template <typename T, typename F> class Select<false, T, F>
{
public:
	typedef F Type;
};

template <typename T, typename F> class Select<true, T, F>
{
public:
	typedef T Type;
};


// use ConstIf<b, T>::Type to choose type const T for b==true and type T for b==false
template <Bool, typename> class ConstIf;

template <typename T> class ConstIf<true, T>
{
public:
	typedef const T Type;
};

template <typename T> class ConstIf<false, T>
{
public:
	typedef T Type;
};


template <typename T, typename Check> class SFINAEHelper
{
public:
	typedef T Type;
};



// the following types and functions are needed for the NewObj macro

struct IsAllocType_False
{
	template <typename T> IsAllocType_False(const T&);
	IsAllocType_False();
};

struct IsAllocType_True: public IsAllocType_False
{
};

FalseType IsAllocType(IsAllocType_False);
TrueType IsAllocType(IsAllocType_True);


struct IsImplementationType_False
{
	template <typename T> IsImplementationType_False(const T&);
	IsImplementationType_False();
};

struct IsImplementationType_True: public IsImplementationType_False
{
};

FalseType IsImplementationType(IsImplementationType_False);
TrueType IsImplementationType(IsImplementationType_True);


// use C4D_MISC_ISEMPTY(__VA_ARGS__) to check if the arguments are empty (result will be 1) or not (result will be 0)

#ifdef _MSC_VER

// from http://stackoverflow.com/questions/2124339/c-preprocessor-va-args-number-of-arguments
#define C4D_MISC_ISEMPTY(...) _C4D_MISC_ISEMPTY((_C4D_MISC_ISEMPTY_PREFIX ## __VA_ARGS__ ## _C4D_MISC_ISEMPTY_POSTFIX, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
#define _C4D_MISC_ISEMPTY(__args) _C4D_MISC_ISEMPTY2 __args
#define _C4D_MISC_ISEMPTY_PREFIX_MISC_ISEMPTY_POSTFIX ,,,,, ,,,,, 1
#define _C4D_MISC_ISEMPTY2(__p0,__p1,__p2,__p3,__p4,__p5,__p6,__p7,__p8,__p9,__n,...) __n

#else

// from http://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/
#define C4D_MISC_ISEMPTY(...) _C4D_MISC_ISEMPTY( \
	_C4D_MISC_HAS_COMMA(__VA_ARGS__), /* test if there is just one argument, eventually an empty one */ \
	_C4D_MISC_HAS_COMMA(_C4D_MISC_TRIGGER_PARENTHESIS_ __VA_ARGS__), /* test if _TRIGGER_PARENTHESIS_ together with the argument adds a comma (if __VA_ARGS__ is parenthesized) */ \
	_C4D_MISC_HAS_COMMA(__VA_ARGS__ (~)), /* test if the argument together with a parenthesis adds a comma */ \
	_C4D_MISC_HAS_COMMA(_C4D_MISC_TRIGGER_PARENTHESIS_ __VA_ARGS__ (~))) /* this will have a comma if __VA_ARGS__ is empty (but also for other cases) */

#define _C4D_MISC_ARG16(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, ...) _15
#define _C4D_MISC_HAS_COMMA(...) _C4D_MISC_ARG16(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)
#define _C4D_MISC_TRIGGER_PARENTHESIS_(...) ,
#define _C4D_MISC_PASTE5(_0, _1, _2, _3, _4) _0 ## _1 ## _2 ## _3 ## _4
#define _C4D_MISC_ISEMPTY(_0, _1, _2, _3) _C4D_MISC_HAS_COMMA(_C4D_MISC_PASTE5(_C4D_MISC_IS_EMPTY_CASE_, _0, _1, _2, _3))
#define _C4D_MISC_IS_EMPTY_CASE_0001 ,

#endif


#define _C4D_MISC_PASTE(x, y) x ## y
#define C4D_MISC_PASTE(x, y) _C4D_MISC_PASTE(x, y)


typedef void (*DeleteFunction) (void* object);

template <typename T> inline DeleteFunction ToDeleteFunction(void (*fn) (T*))
{
	return (DeleteFunction) fn;
}


class IllegalEnumAccess
{
public:
	IllegalEnumAccess() {}
};

class IllegalFlagAccess
{
public:
	IllegalFlagAccess() {}
};

#ifndef DOXYGEN_SHOULD_SKIP_THIS

#ifndef ENUM_FLAGS
#define ENUM_FLAGS(X) ;\
	inline X operator |(X a, X b) { return X(UInt32(a)|UInt32(b)); } \
	inline X operator &(X a, X b) { return X(UInt32(a)&UInt32(b)); } \
	inline X operator >>(X a, X b) { return X(UInt32(a)<<UInt32(b)); } \
	inline X operator <<(X a, X b) { return X(UInt32(a)>>UInt32(b)); } \
	inline X operator ~(X a) { return X(~UInt32(a)); } \
	inline X& operator |=(X& a, X b) { a = X(UInt32(a)|UInt32(b)); return a; } \
	inline X& operator &=(X& a, X b) { a = X(UInt32(a)&UInt32(b)); return a; } \
	inline IllegalFlagAccess operator ++(X a) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator ++(X a, int) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator --(X a) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator --(X a, int) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator !=(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator !=(Int32 s2, X s1) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator ==(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator ==(Int32 s2, X s1) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator <(X s1, X s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator <(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator <(Int32 s2, X s1) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator <=(X s1, X s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator <=(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator <=(Int32 s2, X s1) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator >(X s1, X s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator >(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator >(Int32 s2, X s1) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator >=(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator >=(X s1, X s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator >=(Int32 s2, X s1) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator +(X s1, X s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator +(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator +(Int32 s1, X s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator -(X s1, X s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator -(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator -(Int32 s1, X s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator *(X s1, X s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator *(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator *(Int32 s1, X s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator /(X s1, X s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator /(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator /(Int32 s1, X s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator %(X s1, X s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator %(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator %(Int32 s1, X s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator ^(X s1, X s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator ^(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator ^(Int32 s1, X s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator |(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator |(Int32 s1, X s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator &(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator &(Int32 s1, X s2) { return IllegalFlagAccess(); }
#endif

#define CLASS_ENUM_FLAGS(X) ;\
	inline friend X operator |(X a, X b) { return X(UInt32(a)|UInt32(b)); } \
	inline friend X operator &(X a, X b) { return X(UInt32(a)&UInt32(b)); } \
	inline friend X operator >>(X a, X b) { return X(UInt32(a)<<UInt32(b)); } \
	inline friend X operator <<(X a, X b) { return X(UInt32(a)>>UInt32(b)); } \
	inline friend X operator ~(X a) { return X(~UInt32(a)); } \
	inline friend X operator |=(X& a, X b) { a = X(UInt32(a)|UInt32(b)); return a; } \
	inline friend X operator &=(X& a, X b) { a = X(UInt32(a)&UInt32(b)); return a; } \
	inline friend IllegalFlagAccess operator ++(X a) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator ++(X a, int) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator --(X a) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator --(X a, int) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator !=(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator !=(Int32 s2, X s1) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator ==(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator ==(Int32 s2, X s1) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator <(X s1, X s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator <(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator <(Int32 s2, X s1) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator <=(X s1, X s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator <=(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator <=(Int32 s2, X s1) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator >(X s1, X s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator >(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator >(Int32 s2, X s1) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator >=(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator >=(X s1, X s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator >=(Int32 s2, X s1) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator +(X s1, X s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator +(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator +(Int32 s1, X s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator -(X s1, X s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator -(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator -(Int32 s1, X s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator *(X s1, X s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator *(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator *(Int32 s1, X s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator /(X s1, X s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator /(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator /(Int32 s1, X s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator %(X s1, X s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator %(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator %(Int32 s1, X s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator ^(X s1, X s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator ^(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator ^(Int32 s1, X s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator |(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator |(Int32 s1, X s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator &(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator &(Int32 s1, X s2) { return IllegalFlagAccess(); }

#ifndef ENUM_LIST
#define ENUM_LIST(X) ;\
	inline IllegalEnumAccess operator |(X a, X b) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator &(X a, X b) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator ~(X a) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator ++(X a) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator ++(X a, int) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator --(X a) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator --(X a, int) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator ==(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator ==(Int32 s2, X s1) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator !=(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator !=(Int32 s2, X s1) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator !(X a) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator +(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator +(Int32 s1, X s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator -(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator -(Int32 s1, X s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator *(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator *(Int32 s1, X s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator /(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator /(Int32 s1, X s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator %(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator %(Int32 s1, X s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator <(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator <(Int32 s1, X s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator >(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator >(Int32 s1, X s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator <=(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator <=(Int32 s1, X s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator >=(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator >=(Int32 s1, X s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator <<(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator <<(Int32 s1, X s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator >>(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator >>(Int32 s1, X s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator ^(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator ^(Int32 s1, X s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator ||(X s1, X s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator ||(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator ||(Int32 s1, X s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator &&(X s1, X s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator &&(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline IllegalEnumAccess operator &&(Int32 s1, X s2) { return IllegalEnumAccess(); } \
	inline IllegalFlagAccess operator |(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator |(Int32 s1, X s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator &(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator &(Int32 s1, X s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator <(X s1, X s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator <=(X s1, X s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator >(X s1, X s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator >=(X s1, X s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator +(X s1, X s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator -(X s1, X s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator *(X s1, X s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator /(X s1, X s2) { return IllegalFlagAccess(); } \
	inline IllegalFlagAccess operator ^(X s1, X s2) { return IllegalFlagAccess(); }
#endif

#define CLASS_ENUM_LIST(X) ;\
	inline friend IllegalEnumAccess operator |(X a, X b) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator &(X a, X b) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator ~(X a) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator ++(X a) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator ++(X a, int) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator --(X a) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator --(X a, int) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator ==(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator ==(Int32 s2, X s1) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator !=(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator !=(Int32 s2, X s1) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator !(X a) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator +(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator +(Int32 s1, X s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator -(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator -(Int32 s1, X s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator *(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator *(Int32 s1, X s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator /(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator /(Int32 s1, X s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator %(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator %(Int32 s1, X s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator <(X s1, X s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator <(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator <(Int32 s1, X s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator >(X s1, X s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator >(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator >(Int32 s1, X s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator <=(X s1, X s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator <=(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator <=(Int32 s1, X s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator >=(X s1, X s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator >=(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator >=(Int32 s1, X s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator <<(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator <<(Int32 s1, X s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator >>(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator >>(Int32 s1, X s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator ^(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator ^(Int32 s1, X s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator ||(X s1, X s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator ||(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator ||(Int32 s1, X s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator &&(X s1, X s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator &&(X s1, Int32 s2) { return IllegalEnumAccess(); } \
	inline friend IllegalEnumAccess operator &&(Int32 s1, X s2) { return IllegalEnumAccess(); } \
	inline friend IllegalFlagAccess operator |(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator |(Int32 s1, X s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator &(X s1, Int32 s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator &(Int32 s1, X s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator +(X s1, X s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator -(X s1, X s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator *(X s1, X s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator /(X s1, X s2) { return IllegalFlagAccess(); } \
	inline friend IllegalFlagAccess operator ^(X s1, X s2) { return IllegalFlagAccess(); }

#endif

class String;

#if defined(__MAC) || defined(__LINUX)
	#define __debugbreak()	__asm__("int $3\n" : :);
#elif defined(__iOS)
	#if defined(__i386__) || defined(__x86_64__)
		#define __debugbreak()	__asm__("int $3\n" : :);
	#else
	#define __debugbreak()	//__asm__ __volatile__ ("mov r0, %0\nmov r1, %1\nmov r12, #37\nswi 128\n" : : "r" (getpid ()), "r" (SIGINT) : "r12", "r0", "r1", "cc");
	#endif
#elif !defined(__PC)
	#define __debugbreak()	{}
#endif

// debugging section

/// output flags for console output
enum OUTPUT
{
	OUTPUT_DIAGNOSTIC		= (1<<0),	 ///< diagnostic output, shows up if this group of output is activated. This is also the default
	OUTPUT_WARNING			= (1<<1),	 ///< warning output, shows up if this group of output is activated
	OUTPUT_CRITICAL			= (1<<2),	 ///< critical output, shows up if this group of output is activated

	OUTPUT_NOLINEBREAK  = (1<<29), ///< if set, no line break is added
	OUTPUT_HEADER				= (1<<30)  ///< if set, header with line number and file name is added
} ENUM_FLAGS(OUTPUT);

// private
extern c4d_misc::Bool		g_IsDebuggerPresent;

void _ConsoleOutput(OUTPUT flags, const Char* fmt, Int line, const Char* file, ...);
void _ConsoleOutput(OUTPUT flags, const String& fmt, Int line, const Char* file, ...);

// All routines that start with Debug (DebugOutput, DebugStop, DebugAssert) result in empty (non-speed critical) code in a release build

/// DebugOutput outputs text into the console.
/// It only has any effect in debug builds and does not cost any time in release builds.
/// It should be used for temporary output that must not be visible to a customer or external developer.
/// The full <a href="http://www.cplusplus.com/reference/clibrary/cstdio/printf">printf syntax</a> can be used for the format string.
/// THREADSAFE.
#ifdef _DEBUG
	#define DebugOutput(flags,fmt,...) _ConsoleOutput(flags,fmt,__LINE__,__FILE__,##__VA_ARGS__)
#else
	#define DebugOutput(flags,fmt,...) { }
#endif

/// DiagnosticOutput outputs text into the console.
/// The output is visible in debug builds or in a release build when the debug console with diagnostic output is activated.
/// The full <a href="http://www.cplusplus.com/reference/clibrary/cstdio/printf">printf syntax</a> can be used for the format string.
/// THREADSAFE.
#define DiagnosticOutput(fmt,...) _ConsoleOutput(c4d_misc::OUTPUT_DIAGNOSTIC,fmt,__LINE__,__FILE__,##__VA_ARGS__)

/// OutputWithFlags outputs text into the console.
/// The output is visible in debug builds or in a release build when the debug console with diagnostic output is activated.
/// The full <a href="http://www.cplusplus.com/reference/clibrary/cstdio/printf">printf syntax</a> can be used for the format string.
/// THREADSAFE.
#define OutputWithFlags(flags,fmt,...) _ConsoleOutput(flags,fmt,__LINE__,__FILE__,##__VA_ARGS__)

/// WarningOutput outputs text into the console.
/// The output is visible in debug builds or in a release build when the debug console with warning output is activated.
/// It should only be used to output unexpected, non-critical conditions.
/// It automatically shows header information and adds a line break.
/// The full <a href="http://www.cplusplus.com/reference/clibrary/cstdio/printf">printf syntax</a> can be used for the format string.
/// THREADSAFE.
#define WarningOutput(fmt,...) _ConsoleOutput(c4d_misc::OUTPUT_WARNING|c4d_misc::OUTPUT_HEADER,fmt,__LINE__,__FILE__,##__VA_ARGS__)

/// CriticalOutput outputs text into the console.
/// The output is visible in debug builds or in a release build when the debug console with critical output is activated.
/// It should only be used to output unexpected, critical conditions that would most likely result in instability, e.g. an illegal array access or corrupt object structure.
/// It can also be used for unexpected events, e.g. if a necessary module cannot be initialized.
/// It automatically shows header information and adds a line break.
/// It automatically stops the debugger if present.
/// The full <a href="http://www.cplusplus.com/reference/clibrary/cstdio/printf">printf syntax</a> can be used for the format string.
/// THREADSAFE.
#define CriticalOutput(fmt,...) { _ConsoleOutput(c4d_misc::OUTPUT_CRITICAL|c4d_misc::OUTPUT_HEADER,fmt,__LINE__,__FILE__,##__VA_ARGS__); if (c4d_misc::g_IsDebuggerPresent) __debugbreak(); }

inline const Char* AssertHelper(size_t len, const Char* msg1, const Char* msg2)
{
	return (strlen(msg2) > len) ? msg2 : msg1;
}

/// DebugStop stops the execution of the application if it is a debug build and a debugger is present. In case of a debug build the file and line number are output (critical output category).
/// A C string can be passed as argument that will be output as well.
/// THREADSAFE.
#ifdef _DEBUG
	#define DebugStop(...)	{ DebugOutput(c4d_misc::OUTPUT_CRITICAL|c4d_misc::OUTPUT_HEADER,c4d_misc::AssertHelper(strlen("Debug Stop: "), "Debug Stop", "Debug Stop: " __VA_ARGS__)); if (c4d_misc::g_IsDebuggerPresent) __debugbreak(); }
#else
	#define DebugStop(...)	{ }
#endif

/// CriticalStop stops the execution of the application if a debugger is present. The file and line number are output (critical output category).
/// A C string can be passed as argument that will be output as well.
/// THREADSAFE.
#define CriticalStop(...) { CriticalOutput(c4d_misc::AssertHelper(strlen("Stop: "), "Stop", "Stop: " __VA_ARGS__)); }

#ifdef __MAC
#define	__DEBUGGING__																				// avoid conflicts with DebugAssert() definition for the Mac
#endif

/// DebugAssert is a conditional DebugStop. It does the same as DebugStop() if 'condition' is false. A C string can be passed as optional argument for output.
/// THREADSAFE.
#if defined _DEBUG && !defined __LINUX
	#define DebugAssert(condition, ...) { if (!(condition)) { DebugOutput(c4d_misc::OUTPUT_CRITICAL|c4d_misc::OUTPUT_HEADER,c4d_misc::AssertHelper(strlen("Debug Assertion failed: "), "Debug Assertion failed: " #condition, "Debug Assertion failed: " __VA_ARGS__)); if (c4d_misc::g_IsDebuggerPresent) __debugbreak(); } }
#else
	#define DebugAssert(condition, ...) { }
#endif

/// CriticalAssert is a conditional CriticalStop. It does the same as CriticalStop() if 'condition' is false. A C string can be passed as optional argument for output.
/// THREADSAFE.
#define CriticalAssert(condition, ...) { if (!(condition)) { CriticalOutput(c4d_misc::AssertHelper(strlen("Assertion failed: "), "Assertion failed: " #condition, "Assertion failed: " __VA_ARGS__)); } }

/// SizeAssert is a static assert verified at compile-time. It checks if the passed type is of size 's'.
/// On failure an exception of negative STATICASSERT_CONDITION_FALSE is raised.
/// THREADSAFE.
#define SizeAssert(type,s) static_assert(sizeof(type)==s,"type is not of passed size")

/// data type for comparison results
enum COMPARERESULT
{
	COMPARERESULT_LESS			= -1,			///< result is less than
	COMPARERESULT_EQUAL			=  0,			///< result is equal
	COMPARERESULT_GREATER		=  1,			///< result is greater than
	COMPARERESULT_ILLEGAL		= -1000		///< compare doesn't exist for an operator
} ENUM_LIST(COMPARERESULT);


class DefaultCompare
{
public:

	template <typename T> static inline COMPARERESULT Compare(const T& a, const T& b)
	{
		CriticalStop();
		return COMPARERESULT_ILLEGAL;

// will end up in endless recursion ...
// 		const DataTypeInfo *typeInfo = GetTypeInfo<T>();
// 		if (!typeInfo)
// 		{
// 			CriticalAssert(false);
// 			return COMPARERESULT_ILLEGAL;
// 		}
// 		return typeInfo->_compare(&a,&b);
	}

	static inline COMPARERESULT Compare(Bool a, Bool b)
	{
		return (a < b) ? COMPARERESULT_LESS : ((a > b) ? COMPARERESULT_GREATER : COMPARERESULT_EQUAL );
	}

	static inline COMPARERESULT Compare(Char a, Char b)
	{
		return (a < b) ? COMPARERESULT_LESS : ((a > b) ? COMPARERESULT_GREATER : COMPARERESULT_EQUAL );
	}

	static inline COMPARERESULT Compare(UChar a, UChar b)
	{
		return (a < b) ? COMPARERESULT_LESS : ((a > b) ? COMPARERESULT_GREATER : COMPARERESULT_EQUAL );
	}

	static inline COMPARERESULT Compare(Int16 a, Int16 b)
	{
		return (a < b) ? COMPARERESULT_LESS : (a > b) ? COMPARERESULT_GREATER : COMPARERESULT_EQUAL;
	}

	static inline COMPARERESULT Compare(UInt16 a, UInt16 b)
	{
		return (a < b) ? COMPARERESULT_LESS : (a > b) ? COMPARERESULT_GREATER : COMPARERESULT_EQUAL;
	}

	static inline COMPARERESULT Compare(Int32 a, Int32 b)
	{
		return (a < b) ? COMPARERESULT_LESS : (a > b) ? COMPARERESULT_GREATER : COMPARERESULT_EQUAL;
	}

	static inline COMPARERESULT Compare(UInt32 a, UInt32 b)
	{
		return (a < b) ? COMPARERESULT_LESS : (a > b) ? COMPARERESULT_GREATER : COMPARERESULT_EQUAL;
	}

	static inline COMPARERESULT Compare(Int64 a, Int64 b)
	{
		return (a < b) ? COMPARERESULT_LESS : (a > b) ? COMPARERESULT_GREATER : COMPARERESULT_EQUAL;
	}

	static inline COMPARERESULT Compare(UInt64 a, UInt64 b)
	{
		return (a < b) ? COMPARERESULT_LESS : (a > b) ? COMPARERESULT_GREATER : COMPARERESULT_EQUAL;
	}

	static inline COMPARERESULT Compare(Float32 a, Float32 b)
	{
		return (a < b) ? COMPARERESULT_LESS : (a > b) ? COMPARERESULT_GREATER : COMPARERESULT_EQUAL;
	}

	static inline COMPARERESULT Compare(Float64 a, Float64 b)
	{
		return (a < b) ? COMPARERESULT_LESS : (a > b) ? COMPARERESULT_GREATER : COMPARERESULT_EQUAL;
	}

	static inline COMPARERESULT Compare(const Char* a, const Char* b)
	{
		int res = strcmp(a,b);
		return (res < 0) ? COMPARERESULT_LESS : (res > 0) ? COMPARERESULT_GREATER : COMPARERESULT_EQUAL;
	}

};


/// data type for uninitialized classes.
/// special datatype to implement uninitialized classes. e.g. Vectors usally init all components with (0,0,0). Vector v(DC); will create an uninitialized vector
enum _DONTCONSTRUCT
{
	DC
};

//////////////////////////////////////////////////////////////////////////

#ifdef __MAC
	#ifdef __x86_64__
		#define	_GetCurrentFramePointer(fpp) { asm ("movq	%%rbp, %0\t\n" : "=r" (*fpp) : : "cc" ); }
		#define	_GetCurrentStackPointer(spp) { asm ("movq	%%rsp, %0\t\n" : "=r" (*spp) : : "cc" ); }
	#elif defined(__i386__)
		#define	_GetCurrentFramePointer(fpp) { asm ("movl	%%ebp, %0\t\n" : "=r" (*fpp) : : "cc" ); }
		#define	_GetCurrentStackPointer(spp) { asm ("movl	%%esp, %0\t\n" : "=r" (*spp) : : "cc" ); }
	#endif
#endif

#if defined(__MAC)

inline void* GetStackPointer()
{
	Int	sp;

	_GetCurrentStackPointer(&sp);
#ifdef _DEBUG
	sp += 0x10;	// assume this was not inlined
#endif

	return (void*) sp;
}

inline void* GetProgramCounter()
{
	Int	pc;
	Int	fp;

	_GetCurrentFramePointer(&fp);
	pc = *(Int*) (fp + SIZEOF(Int));

	return (void*) pc;
}

inline void* GetFramePointer()
{
	Int	fp;
	_GetCurrentFramePointer(&fp);

#ifdef _DEBUG
	fp = *(Int*)fp;
#endif

	return (void*) fp;
}

#else
inline void* GetStackPointer() { return nullptr; }
inline void* GetProgramCounter() { return nullptr; }
inline void* GetFramePointer() { return nullptr; }
#endif

struct MemoryAllocLocationPOD
{
	const Char*	file;
	Int	lineAndFlags;
};

struct MemoryAllocLocationDebugPOD
{
	const Char*	file;
	Int	lineAndFlags;
	void*	pc;
	void*	sp;
	void* fp;
};

class MemoryAllocLocationDebug : public MemoryAllocLocationDebugPOD
{
public:
	MemoryAllocLocationDebug(const Char* f, Int l, void* rpc, void *rsp, void* rfp)
	{
	 file = f;
	 lineAndFlags = rpc ? l | FRAME_INFO_FLAG : l;
	 pc = rpc;
	 sp = rsp;
	 fp = rfp;
	}

	void*	GetInstructionPointer() const { return HasFrameInfo() ? pc : nullptr; }
	void*	GetStackPointer() const { return HasFrameInfo() ? sp : nullptr; }
	void*	GetFramePointer() const { return HasFrameInfo() ? fp : nullptr; }
	Bool	HasFrameInfo() const { return (lineAndFlags & FRAME_INFO_FLAG) != 0; }

	enum { FRAME_INFO_FLAG = 0x1000000, LINE_NUMBER_MASK = 0xffffff };	// struct carries extended debug info if FRAME_INFO_FLAG is set
};

#ifdef _MEMSTACKTRACE
typedef MemoryAllocLocationDebug	MemoryAllocLocation;
#else
class MemoryAllocLocation : public MemoryAllocLocationPOD
{
public:
	MemoryAllocLocation(const Char* f, Int l)
	{
		file = f;
		lineAndFlags = l;
	}

	const Char*	GetFile() const { return file; }
	Int	GetLine() const { return lineAndFlags & LINE_NUMBER_MASK; }
	void*	GetInstructionPointer() const { return nullptr; }
	void*	GetStackPointer() const { return nullptr; }
	void*	GetFramePointer() const { return nullptr; }
	Bool	HasFrameInfo() const { return (lineAndFlags & FRAME_INFO_FLAG) != 0; }

	enum { FRAME_INFO_FLAG = 0x1000000, LINE_NUMBER_MASK = 0xffffff };	// struct carries extended debug info if FRAME_INFO_FLAG is set
};
#endif

#ifdef _MEMSTACKTRACE
#define	C4D_MISC_ALLOC_LOCATION		c4d_misc::MemoryAllocLocation(__FILE__, __LINE__, c4d_misc::GetProgramCounter(), c4d_misc::GetStackPointer(), c4d_misc::GetFramePointer())
#else
#define	C4D_MISC_ALLOC_LOCATION		c4d_misc::MemoryAllocLocation(__FILE__, __LINE__)
#endif

#define	C4D_MISC_ALLOC_LOCATION_DECLARATION	const c4d_misc::MemoryAllocLocation& allocLocation
#define C4D_MISC_ALLOC_LOCATION_FORWARD			allocLocation

//clashes with C4D
//#define GOTO_ERROR; { DebugOutput(c4d_misc::OUTPUT_DIAGNOSTIC|c4d_misc::OUTPUT_HEADER,"Error Exit", __FILE__, __LINE__); goto Error; }
//#define RETURN_FALSE { DebugOutput(c4d_misc::OUTPUT_DIAGNOSTIC|c4d_misc::OUTPUT_HEADER,"Returned false", __FILE__, __LINE__); return false; }

} // C4D_MISC_END

#endif
