/*************************************************************************/ /* File : XUtil.h */ /* Author : Aymeric Bard */ /* */ /* Virtools SDK */ /* Copyright (c) Virtools 2000, All Rights Reserved. */ /*************************************************************************/ #ifndef _XUTIL_H_ #define _XUTIL_H_ #include "math.h" #ifdef macintosh #include "VxMacHeader.h" #pragma cpp_extensions on #endif #ifdef _DEBUG #if defined(WIN32) || defined(_XBOX) #ifdef _WIN32_WCE #define _DEBUG_BREAKPOINT() #else #if _XBOX_VER<200 #define _DEBUG_BREAKPOINT() __asm { int 3 } #else #define _DEBUG_BREAKPOINT() DebugBreak(); #endif #endif #else #define _DEBUG_BREAKPOINT() #endif #else #define _DEBUG_BREAKPOINT() #endif #define _QUOTE(x) # x #define QUOTE(x) _QUOTE(x) #define __FILE__LINE__ __FILE__ "(" QUOTE(__LINE__) ") : " #undef NOTE #define NOTE( x ) message( x ) #define FILE_LINE message( __FILE__LINE__ ) #define TODO( x ) message( __FILE__LINE__"\n" \ " ------------------------------------------------\n" \ "| TODO : " #x "\n" \ " -------------------------------------------------\n" ) #define TOFIX( x ) message( __FILE__LINE__"\n" \ " ------------------------------------------------\n" \ "| TOFIX : " #x "\n" \ " -------------------------------------------------\n" ) #define todo( x ) message( __FILE__LINE__" TODO : " #x "\n" ) #define tofix( x ) message( __FILE__LINE__" TOFIX: " #x "\n" ) #ifndef XBYTE typedef unsigned char XBYTE; #endif #ifndef XBOOL typedef int XBOOL; #endif #ifndef XWORD typedef unsigned short XWORD; #endif #ifndef XDWORD typedef unsigned int XDWORD; #endif // TODO : specify which OS does not support assert here #ifndef _WIN32_WCE #if defined(PSX2) #ifdef DEBUG #define XASSERT(a) if(!(a)) { asm(" breakc 0x0"); asm(" nop");} #else #define XASSERT(a) #endif #elif defined(PSP) #ifdef _DEBUG #ifdef __MWERKS__ #define XASSERT(a) if(!(a)) { asm("breakc 0x0"); asm(" nop");} #else #define XASSERT(a) if(!(a)) { asm("break 0x0"); asm(" nop");} #endif #else #define XASSERT(a) #endif #elif defined (macintosh) #if defined (_DEBUG) || defined(DEBUG) #include #define XASSERT(a) assert(a) #else #define XASSERT(a) #endif #else #include #define XASSERT(a) assert(a) #endif #else #define XASSERT(a) #endif #ifndef VX_EXPORT #ifdef VX_LIB #define VX_EXPORT #else #ifdef VX_API #ifdef WIN32 #define VX_EXPORT __declspec(dllexport) // VC++ export option {secret} #elif macintosh #define VX_EXPORT __declspec(export) // CodeWarrior export pragma {secret} #elif _LINUX #define VX_EXPORT #endif #else #ifdef WIN32 #define VX_EXPORT __declspec(dllimport) // VC++ export option {secret} #elif macintosh #define VX_EXPORT __declspec(import) // CodeWarrior export pragma {secret} #elif _LINUX #define VX_EXPORT #endif #endif #endif #endif #ifdef WIN32 // Summary: Sort function prototype for XArray,XBinaryTree sort operations // typedef int (__cdecl *VxSortFunc)(const void *elem1, const void *elem2 ); #else typedef int (*VxSortFunc)(const void *elem1, const void *elem2 ); #endif //*************** X86 ASM DEFINES ************************************************* #if defined(WIN32) || defined(_XBOX) #ifndef _WIN32_WCE #if (_XBOX_VER<200) #define ASM_SUPPORTED #endif #endif #endif #ifdef ASM_SUPPORTED #pragma warning (disable:4035) // inline float XCos(float f) { __asm { fld dword ptr f fcos } } // inline float XSin(float f) { __asm { fld dword ptr f fsin } } #pragma warning (default:4035) #else inline float XCos(float f) { return cosf(f); } inline float XSin(float f) { return sinf(f); } #endif /************************************************* Summary: Enables the initialisation of a reference from two values. Arguments: iCond: TRUE to return iT1 , FALSE to return iT2; *************************************************/ template const T& ChooseRef(XBOOL iCond, const T& iT1, const T& iT2) { if (iCond) return iT1; else return iT2; } /************************************************* Summary: Forces a value in an interval. Arguments: t: value to threshold min: minimum valid value max: maximum valid value See Also: XMin,XMax *************************************************/ template void XThreshold(T& t,const T& min,const T& max) { if (t < min) t = min; else if (t > max) t = max; } /************************************************* Summary: Returns the minimum of two values. Remarks: Returns minimum between a and b. See Also: XMax *************************************************/ template const T& XMin(const T& a,const T& b) { if(a < b) return a; else return b; } #ifdef PSP inline int XMin(const int a,const int b) { return __builtin_allegrex_min(a,b); } inline float XMin(const float a,const float b) { if(a < b) return a; else return b; } #endif /************************************************* Summary: Returns the maximum of two values. Remarks: Returns maximum between a and b. See Also: XMax *************************************************/ template const T& XMax(const T& a,const T& b) { if(a > b) return a; else return b; } #ifdef PSP inline int XMax(const int a,const int b) { return __builtin_allegrex_max(a,b); } inline float XMax(const float a,const float b) { if(a > b) return a; else return b; } #endif /************************************************* Summary: Finds the minimum and maximum of 2 values. Remarks: Returns minimum and maximum between a,b. See Also: XMin,XMax *************************************************/ template void XMinMax(const T& a,const T& b, T& min, T& max) { if (a const T& XMin(const T& a,const T& b,const T& c) { return (a const T& XMax(const T& a,const T& b,const T& c) { return (a>b)?((c>a)?c:a):((c>b)?c:b); } /************************************************* Summary: Finds the minimum and maximum of 3 values. Remarks: Returns minimum and maximum between a,b and c. See Also: XMin,XMax *************************************************/ template void XMinMax(const T& a,const T& b,const T& c, T& min, T& max) { if (a void XMinMax(const T& a,const T& b,const T& c, T& min, T& med, T& max) { if (a void XSwap(T& a,T& b) { T c = a; a = b; b = c; } /************************************************* Summary: Returns the absolute value of a. Remarks: *************************************************/ template T XAbs(T a) { return (a>0)?a:-a; } // float specialization #ifdef macintosh template <> inline float XAbs(float a) {return (float)__fabs(a);} #else #ifdef PSP template <> inline float XAbs(float a) { register float fd; __asm__ ( "abs.s %0, %1\n" : "=f"(fd) : "f"(a) ); return (fd); } #else template <> inline float XAbs(float a) {return ::fabsf(a);} #endif #endif /************************************************* Summary: Returns the absolute value of a float. Remarks: *************************************************/ inline float XFabs(float a) { #ifdef macintosh return (float)__fabs(a); #elif defined(PSP) register float fd; __asm__ ( "abs.s %0, %1\n" : "=f"(fd) : "f"(a) ); return (fd); #else return ::fabsf(a); #endif } /************************************************* Summary: Returns the square root value of a float. Remarks: *************************************************/ inline float XSqrt(float a) { #if defined(PSP) return __builtin_allegrex_sqrt_s(a) ; #else return ::sqrtf(a); #endif } //------ Memory Management #define VxNew(a) (new unsigned char[a]) #define VxDelete(a) (delete[] (unsigned char*) a) template T* VxAllocate (int n); template void VxFree (T* t); inline int LowestBitMask(int v) { return ((v & -v)); } /************************************************* Summary: return true if num is a power of 2 Remarks: *************************************************/ inline XBOOL Is2Power(int x) { return x != 0 && x == LowestBitMask(x); } /************************************************* Summary: return the nearest superior power of 2 of v Remarks: *************************************************/ inline int Near2Power(int v) { int i = LowestBitMask(v); while(i < v) i <<= 1; return i; } #if defined(PSP) /************************************************* Summary: perform a right bit rotation (emulates _rotl & _rotr of Windows' Stdlib) Remarks: Macintosh only *************************************************/ inline int _rotr(int v, int shift) { const unsigned int invShift = 32 - shift; const unsigned int mask = (1 << invShift) - 1; return ((((unsigned int)v) >> shift) & mask) | (((unsigned int)v) << invShift); } /************************************************* Summary: perform a left bit rotation (emulates _rotl & _rotr of Windows' Stdlib) Remarks: Macintosh only *************************************************/ inline int _rotl(int v, int shift) { const unsigned int invShift = 32 - shift; const unsigned int mask = (1 << invShift) - 1; return ((((unsigned int)v) >> invShift) & mask) | (((unsigned int)v) << shift); } #endif #if defined(macintosh) /************************************************* Summary: perform a right bit rotation (emulates _rotl & _rotr of Windows' Stdlib) Remarks: Macintosh only *************************************************/ inline int _rotr(int v, int shift) { const int invShift = 32 - shift; const int mask = (1 << invShift) - 1; return ((v >> shift) & mask) | (v << invShift); } /************************************************* Summary: perform a left bit rotation (emulates _rotl & _rotr of Windows' Stdlib) Remarks: Macintosh only *************************************************/ inline int _rotl(int v, int shift) { const int invShift = 32 - shift; const int mask = (1 << invShift) - 1; return ((v >> invShift) & mask) | (v << shift); } #endif /******************************************************************************* Summary: Global Unique Identifier Struture. Remarks: Comparison operators are defined so XGUIDS can be compared with ==,!= ,<,> operators. *******************************************************************************/ class XGUID { public: explicit XGUID(XDWORD gd1=0,XDWORD gd2=0) : d1(gd1),d2(gd2) { } friend XBOOL operator==(const XGUID& v1,const XGUID& v2) { return ((v1.d1==v2.d1)&&(v1.d2==v2.d2)); } friend XBOOL operator!=(const XGUID& v1,const XGUID& v2) { return ((v1.d1!=v2.d1)||(v1.d2!=v2.d2)); } friend XBOOL operator<(const XGUID& v1,const XGUID& v2) { if(v1.d1(const XGUID& v1,const XGUID& v2) { if(v1.d1>v2.d1) return true; if(v1.d1==v2.d1) return (v1.d2>v2.d2); return false; } friend XBOOL operator>=(const XGUID& v1,const XGUID& v2) { return (v1.d1>=v2.d1); } XBOOL inline IsValid() { return d1&&d2; } XDWORD d1; XDWORD d2; }; /******************************************************************************* Summary: Handy macro that return the number of elements in a static array. *******************************************************************************/ #define sizeofarray(array) (sizeof(array) / sizeof((array)[0])) /******************************************************************************* Summary: Remove all elements that match the predicate in a sequential range. This occurs in place. The predicate object should be stateless and provide a () operator that receive the element to be tested, and returns true if it is to be deleted. The order of the remaining elements is preserved. Remarks: This function mimics the STL 'remove_if' function : it doesn't erase the last elements in a container, but returns a pointer on the new 'end' of the container. It is up to the caller to delete the ['new end', 'old end'] range in the container. It is needed because this function don't have a reference on the container. (It just knows about its iterator) *******************************************************************************/ template Iter XRemoveIf(Iter begin, Iter end, const Pred& predicate) { if (begin == end) return end; XASSERT(begin); XASSERT(end); Iter dest = begin; Iter curr = begin; // search first candidate for deletion (avoid needless self assignement) while (curr != end && !predicate(*curr)) { ++ curr; } dest = curr; ++ curr; // now shift elements, skipping elements that are to be deleted while (curr < end) { if (predicate(*curr)) { ++ curr; } else { *dest++ = *curr++; } } return dest; } /******************************************************************************* Summary: Remove all elements that match the predicate in a vector. This occurs in place. The predicate object should be stateless and provide a () operator that receive the element to be tested, and returns true if it is to be deleted. The order of the remaining elements is preserved. Remarks: This version relies on the 'ranged' version of remove_if, and takes care to resize the vector after the removal. *******************************************************************************/ template void XRemoveIf(Cont &cont, const Pred& predicate) { typename Cont::Iterator newEnd = XRemoveIf(cont.Begin(), cont.End(), predicate); cont.Resize(newEnd - cont.Begin()); } #endif