Lua: partial implementation of struct reference wrapping, which has led into a shitlo...
[fail.git] / lua / typecheck.h
blob601b9b69a26fb77a129f3fc0b82cc109b17aac09
1 #ifndef AWFUL_LUA_TYPECHECK_H
2 #define AWFUL_LUA_TYPECHECK_H
4 namespace awful { namespace LuaImpl
6 enum e_CheckingPolicy
8 cp_NoCheck,
9 cp_NoThrow,
10 cp_Throw
13 // The address of the dummy field of that class is unique
14 // for each class compiled in the executable.
15 // This provides a simple way to identify type, that can be embedded
16 // into a lua light user data to be used as keys in lua tables.
18 // This would not work portably with the address of std::type_info structures, because
19 // comparing type_info addresses is not portable (as with some systems/compiler/linkers
20 // you may end up with several instances of the same type_info in the final binary)
21 // and lua assumes that a light user data contains an address that it can directly
22 // hash when used as a table key.
23 template< typename T > struct type_tag
25 static char dummy;
27 template< typename T > char type_tag< T >::dummy;
29 // Structs come wrapped in two flavors: by value or by reference.
30 // This handy enum allows the struct typeconverter to distinguish both case.
31 enum e_TypeCheckResult
33 tcr_Fail, // Not of the required type
34 tcr_Type1, // Of the type represented by the first metatable index
35 tcr_Type2 // Of the type represented by the second metatable index
38 template< e_CheckingPolicy Checking > struct TypeChecker
40 static bool CheckType( lua_State* pLS, int Index_, int ExpectedType_ )
42 return true;
45 template< class C > static e_TypeCheckResult CheckObjectType( lua_State* pLS, int Index_ )
47 return tcr_Type1;
50 template< class C > static e_TypeCheckResult CheckStructType( lua_State* pLS, int Index_ )
52 return tcr_Type1;
55 /* template< class C > static e_TypeCheckResult CheckObjectType( lua_State* pLS, int Index_ )
57 return CheckUserDataAndMetatable
58 ( pLS, Index_, &type_tag< C& >::dummy );
61 template< class C > static e_TypeCheckResult CheckStructType( lua_State* pLS, int Index_ )
63 return CheckUserDataAndMetatable
64 ( pLS, Index_, &type_tag< C& >::dummy, &type_tag< C* >::dummy );
65 }*/
68 template<> struct TypeChecker< cp_NoThrow >
70 static bool CheckType( lua_State* pLS, int Index_, int ExpectedType_ )
72 int type = lua_type( pLS, Index_ );
73 if( type != ExpectedType_ )
74 return false;
76 return true;
79 static e_TypeCheckResult CheckUserDataAndMetatable( lua_State* pLS, int Index_, void* MTRegistryIndex_, void* MTRegistryIndex2_ = NULL )
81 if( !CheckType( pLS, Index_, LUA_TUSERDATA ) )
82 return tcr_Fail;
84 if( !lua_getmetatable( pLS, Index_ ) )
85 return tcr_Fail;
87 lua_pushlightuserdata( pLS, MTRegistryIndex_ );
88 lua_gettable( pLS, LUA_REGISTRYINDEX );
90 bool bRes = lua_rawequal( pLS, -1, -2 );
91 lua_pop( pLS, 2 );
92 if( bRes )
93 return tcr_Type1;
95 if( !bRes && MTRegistryIndex2_ )
97 lua_pushlightuserdata( pLS, MTRegistryIndex2_ );
98 lua_gettable( pLS, LUA_REGISTRYINDEX );
100 bool bRes = lua_rawequal( pLS, -1, -2 );
101 lua_pop( pLS, 2 );
102 if( bRes )
103 return tcr_Type2;
106 return tcr_Fail;
109 template< class C > static e_TypeCheckResult CheckObjectType( lua_State* pLS, int Index_ )
111 return CheckUserDataAndMetatable
112 ( pLS, Index_, &type_tag< C& >::dummy );
115 template< class C > static e_TypeCheckResult CheckStructType( lua_State* pLS, int Index_ )
117 return CheckUserDataAndMetatable
118 ( pLS, Index_, &type_tag< C& >::dummy, &type_tag< C* >::dummy );
122 template<> struct TypeChecker< cp_Throw >
124 static bool CheckType( lua_State* pLS, int Index_, int ExpectedType_ )
126 int type = lua_type( pLS, Index_ );
127 if( type != ExpectedType_ )
128 throw Error::TypeMismatch( type, ExpectedType_ );
130 return true;
133 static e_TypeCheckResult CheckUserDataAndMetatable( lua_State* pLS, int Index_, void* MTRegistryIndex_, void* MTRegistryIndex2_ = NULL )
135 CheckType( pLS, Index_, LUA_TUSERDATA );
137 if( !lua_getmetatable( pLS, Index_ ) )
138 throw Error::TypeMismatch();
140 lua_pushlightuserdata( pLS, MTRegistryIndex_ );
141 lua_gettable( pLS, LUA_REGISTRYINDEX );
143 bool bRes = lua_rawequal( pLS, -1, -2 );
144 lua_pop( pLS, 2 );
145 if( bRes )
146 return tcr_Type1;
148 if( !bRes && MTRegistryIndex2_ )
150 lua_pushlightuserdata( pLS, MTRegistryIndex2_ );
151 lua_gettable( pLS, LUA_REGISTRYINDEX );
153 bool bRes = lua_rawequal( pLS, -1, -2 );
154 lua_pop( pLS, 2 );
155 if( bRes )
156 return tcr_Type2;
159 throw Error::TypeMismatch();
162 template< class C > static e_TypeCheckResult CheckObjectType( lua_State* pLS, int Index_ )
164 return CheckUserDataAndMetatable
165 ( pLS, Index_, &type_tag< C& >::dummy );
168 template< class C > static e_TypeCheckResult CheckStructType( lua_State* pLS, int Index_ )
170 return CheckUserDataAndMetatable
171 ( pLS, Index_, &type_tag< C& >::dummy, &type_tag< C* >::dummy );
175 // bool CheckType_nothrow( lua_State* pLS, int Index_, int ExpectedType_ );
176 /* void CheckUserDataAndMetatable( lua_State* pLS, int Index_,
177 void* MTRegistryIndex_, void* MTRegistryIndex2_ = NULL );
178 e_TypeCheckResult CheckUserDataAndMetatable_nothrow( lua_State* pLS, int Index_,
179 void* MTRegistryIndex1_, void* MTRegistryIndex2_ = NULL );*/
181 /*template< class C > static void CheckObjectType( lua_State* pLS, int Index_ )
183 CheckUserDataAndMetatable
184 ( pLS, Index_, &type_tag< C& >::dummy );
187 template< class C > static void CheckStructType( lua_State* pLS, int Index_ )
189 CheckUserDataAndMetatable
190 ( pLS, Index_, &type_tag< C& >::dummy, &type_tag< C* >::dummy );
196 #endif