more generic type-punning helper
This commit is contained in:
@@ -9,44 +9,6 @@ extern "C"
|
|||||||
#include "lua-5.1/src/lua.h"
|
#include "lua-5.1/src/lua.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Safely add an integer to an enum.
|
|
||||||
*
|
|
||||||
* This is illegal:
|
|
||||||
*
|
|
||||||
* ((int&)val) += iAmt;
|
|
||||||
*
|
|
||||||
* It breaks aliasing rules; the compiler is allowed to assume that "val" doesn't
|
|
||||||
* change (unless it's declared volatile), and in some cases, you'll end up getting
|
|
||||||
* old values for "val" following the add. (What's probably really happening is
|
|
||||||
* that the memory location is being added to, but the value is stored in a register,
|
|
||||||
* and breaking aliasing rules means the compiler doesn't know that the register
|
|
||||||
* value is invalid.)
|
|
||||||
*
|
|
||||||
* Always do these conversions through a union.
|
|
||||||
*/
|
|
||||||
template<typename T>
|
|
||||||
static inline void enum_add( T &val, int iAmt )
|
|
||||||
{
|
|
||||||
union conv
|
|
||||||
{
|
|
||||||
T value;
|
|
||||||
int i;
|
|
||||||
};
|
|
||||||
|
|
||||||
conv c;
|
|
||||||
c.value = val;
|
|
||||||
c.i += iAmt;
|
|
||||||
val = c.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
static inline T enum_add2( T val, int iAmt )
|
|
||||||
{
|
|
||||||
enum_add( val, iAmt );
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define FOREACH_ENUM_N( e, max, var ) for( e var=(e)0; var<max; enum_add<e>( var, +1 ) )
|
#define FOREACH_ENUM_N( e, max, var ) for( e var=(e)0; var<max; enum_add<e>( var, +1 ) )
|
||||||
#define FOREACH_ENUM( e, var ) for( e var=(e)0; var<NUM_##e; enum_add<e>( var, +1 ) )
|
#define FOREACH_ENUM( e, var ) for( e var=(e)0; var<NUM_##e; enum_add<e>( var, +1 ) )
|
||||||
#define FOREACH_ENUM2 FOREACH_ENUM
|
#define FOREACH_ENUM2 FOREACH_ENUM
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ bool GLExt_t::HasExtension( const RString &sExt ) const
|
|||||||
return g_glExts.find(sExt) != g_glExts.end();
|
return g_glExts.find(sExt) != g_glExts.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define F(n) { (void **) &GLExt.n , #n }
|
#define F(n) { &CastSimilarTypes<void *>(GLExt.n), #n }
|
||||||
|
|
||||||
struct func_t
|
struct func_t
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -115,6 +115,55 @@ inline void RemoveIf( Container& c, Predicate p )
|
|||||||
c.erase( remove_if(c.begin(), c.end(), p), c.end() );
|
c.erase( remove_if(c.begin(), c.end(), p), c.end() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Cast between types through a union, to avoid type-punning problems in gcc. */
|
||||||
|
template<typename TO, typename FROM>
|
||||||
|
TO &CastSimilarTypes( FROM &val )
|
||||||
|
{
|
||||||
|
union conv_union
|
||||||
|
{
|
||||||
|
TO to;
|
||||||
|
FROM from;
|
||||||
|
};
|
||||||
|
|
||||||
|
conv_union &u = (conv_union &) val;
|
||||||
|
return u.to;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
int &UnionCast( T &e )
|
||||||
|
{
|
||||||
|
return CastSimilarTypes<int,T>(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Safely add an integer to an enum.
|
||||||
|
*
|
||||||
|
* This is illegal:
|
||||||
|
*
|
||||||
|
* ((int&)val) += iAmt;
|
||||||
|
*
|
||||||
|
* It breaks aliasing rules; the compiler is allowed to assume that "val" doesn't
|
||||||
|
* change (unless it's declared volatile), and in some cases, you'll end up getting
|
||||||
|
* old values for "val" following the add. (What's probably really happening is
|
||||||
|
* that the memory location is being added to, but the value is stored in a register,
|
||||||
|
* and breaking aliasing rules means the compiler doesn't know that the register
|
||||||
|
* value is invalid.)
|
||||||
|
*
|
||||||
|
* Always do these conversions through a union.
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
static inline void enum_add( T &val, int iAmt )
|
||||||
|
{
|
||||||
|
UnionCast( val ) += iAmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static inline T enum_add2( T val, int iAmt )
|
||||||
|
{
|
||||||
|
enum_add( val, iAmt );
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We only have unsigned swaps; byte swapping a signed value doesn't make sense.
|
* We only have unsigned swaps; byte swapping a signed value doesn't make sense.
|
||||||
|
|||||||
Reference in New Issue
Block a user