#ifndef __SSDEFS_HPP
#define __SSDEFS_HPP

#include <cstddef>									// we need to include this

namespace SS
{

//------------------------------------------------------------------------
// Debug Build (react automatically to the _DEBUG macro)
//------------------------------------------------------------------------

#if defined(_DEBUG)											// debug build
#	undef SS_DEBUG
#	define SS_DEBUG
#endif // _DEBUG


#ifdef	SS_DEBUG
#define	SS_DEBUG_CODE(X) X
#else
#define	SS_DEBUG_CODE(X)
#endif

#if defined (_MSC_VER)
#	define SS_BUILD_MSC									// Microsoft Visual C++ (any version)
#	if (_MSC_VER == 1200)									
#		define SS_BUILD_MSC6								// Microsoft Visual C++ 6.0 or higher (also SS_BUILD_MSC defined)
#   endif
#	define SS_X86_RETURN_EAX								// even inline functions return parameters correctly in eax
#	define SS_COMPILER "Microsoft Visual C++"
#endif

#define SS_NULL_STATEMENT (static_cast<void>(0))			// no statement

//------------------------------------------------------------------------
// Compilation-time assertion. If the expression 'expr' evaluates to false,
// the compilation will be aborted and an error message will be given.
// Unfortunately the error message itself won't display the expression,
// so you will have to scan the source to the line given by the message
// to see which assertion went wrong. This variant of CT assertion can
// be used even inside class descriptions etc.
//
// Note that the CT assertion is evaluated in both release and debug
// builds (as it doesn't generate any real code).
//
//------------------------------------------------------------------------

#define SS_CT_ASSERT(expr) typedef bool SSCompilationTimeAssertion[(expr) ? 1 : -1] 

//------------------------------------------------------------------------
// Define 16-bit and 32-bit integers (modify code below with #ifdefs if 
// compiler asserts here about the size!)
//------------------------------------------------------------------------

typedef char					INT8;					//  8-bit signed integer
typedef unsigned char			UINT8;					//  8-bit unsigned integer
typedef short int				INT16;                  // 16-bit signed integer
typedef unsigned short int		UINT16;                 // 16-bit unsigned integer
typedef int						INT32;                  // 32-bit signed integer
typedef unsigned int			UINT32;                 // 32-bit unsigned integer

//------------------------------------------------------------------------
// Make sure that certain typedefs really do have specified sizes.
//------------------------------------------------------------------------

SS_CT_ASSERT(sizeof(INT16)==2);
SS_CT_ASSERT(sizeof(UINT16)==2);
SS_CT_ASSERT(sizeof(INT32)==4);
SS_CT_ASSERT(sizeof(UINT32)==4);

//------------------------------------------------------------------------
// The for() fix macro for MSVC (as Visual C++ does not respect the C++
// standard)
//------------------------------------------------------------------------

#if defined (SS_BUILD_MSC)
#	if !defined (for)
		inline bool getFalse (void) { return false; }
#		define for if(SS::getFalse()); else for
#	endif // for
#endif  // SS_BUILD_MSC

//------------------------------------------------------------------------
// Commonly used swap,min2,max2 templates
//------------------------------------------------------------------------

template <class T> inline void swap (T& a, T& b)
{
	T t = a;
	a = b;
	b = t;
}

template <class T> inline const T& min2 (const T& a, const T& b)	{ return a<=b ? a : b; }
template <class T> inline const T& max2 (const T& a, const T& b)	{ return a>=b ? a : b; }

//------------------------------------------------------------------------
// Float -> int casting
//------------------------------------------------------------------------

int		intChop		(const float&);				// extremely fast, always correct (int)(f)
int		intFloor	(const float&);				// extremely fast, always correct (int)(floor(f)) routine
int		intCeil 	(const float&);				// extremely fast, always correct (int)(ceil(f)) routine


//------------------------------------------------------------------------
// Abs and fabs
//------------------------------------------------------------------------

inline int		abs			(int i)		{ return i < 0 ? -i : i; }
inline float	fabs		(float f)	{ return f < 0 ? -f : f; }
inline double	fabs		(double f)	{ return f < 0 ? -f : f; }

//------------------------------------------------------------------------
// Some compilers define macros that may clash with out function naming
//------------------------------------------------------------------------

#undef min
#undef max

//------------------------------------------------------------------------
// Assertions for debug build ("assume construction" not used any more as
// it inteferes with code optimization on MSVC6)
//------------------------------------------------------------------------

void assertFail (const char* expr, const char* file, int line, const char* message); 

#if defined (SS_DEBUG) && !defined (SS_DISABLE_ASSERTS)
#	define SS_ASSERT(e)			((e) ? SS_NULL_STATEMENT : SS::assertFail(#e,__FILE__,__LINE__,""))
#	define SS_ASSERT_PRINT(a,b)	((a) ? SS_NULL_STATEMENT : SS::assertFail(#a,__FILE__,__LINE__,#b))
#	define SS_API_ASSERT(e)		((e) ? SS_NULL_STATEMENT : SS::assertFail("API Error:"#e,__FILE__,__LINE__,""))
#else
#	define SS_ASSERT(e)			(SS_NULL_STATEMENT)					
#	define SS_ASSERT_PRINT(a,b)	(SS_NULL_STATEMENT)					
#	define SS_API_ASSERT(e)		(SS_NULL_STATEMENT)					
#endif // SS_DEBUG

} // namespace SS


//------------------------------------------------------------------------
#endif // __SSDEFS_HPP
