Advertisement
Guest User

Untitled

a guest
Aug 2nd, 2015
194
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.83 KB | None | 0 0
  1. // Copyright 2015 Sammy James
  2.  
  3. #pragma once
  4.  
  5. #include <lua.hpp>
  6. #include <utility>
  7. #include <functional>
  8. #include <list>
  9.  
  10. template< class T >
  11. class TLuaClass
  12. {
  13. public:
  14. struct PropertyType
  15. {
  16. const char* Name;
  17.  
  18. int32 ( T::*Getter )( lua_State* );
  19. int32 ( T::*Setter )( lua_State* );
  20. };
  21.  
  22. struct FunctionType
  23. {
  24. const char* Name;
  25. int32 Call( lua_State* L, void* Object ) const
  26. {
  27. return InternalCall( L, Object );
  28. }
  29.  
  30. FunctionType( const char* InName )
  31. : Name( InName )
  32. {
  33.  
  34. }
  35.  
  36. private:
  37. virtual int32 InternalCall( lua_State* L, void* Object ) const { return 0; }
  38. };
  39.  
  40. template< typename >
  41. struct TFunctionType : public FunctionType
  42. {
  43. };
  44.  
  45. template< typename Result, typename C, typename... Args >
  46. struct TFunctionType< Result( C::* )( Args... ) > : public FunctionType
  47. {
  48. typedef Result( C::*Type )( Args... );
  49.  
  50. TFunctionType( const char* Name, Type Method )
  51. : FunctionType( Name )
  52. , m_Method( Method )
  53. {
  54.  
  55. }
  56.  
  57. private:
  58. Type m_Method;
  59.  
  60. virtual int32 InternalCall( lua_State* L, void* Object ) const override
  61. {
  62. TLuaFunction< Type >::ArgType Arguments = TLuaFunction< Type >::Call( L );
  63. Result RetVal = Apply( Object, Arguments, std::make_index_sequence< std::tuple_size< TLuaFunction< Type >::ArgType >::value >{} );
  64. TLuaPush< Result >::Push( L, RetVal );
  65. return 1;
  66. }
  67.  
  68. template< typename Tup, size_t... Index >
  69. Result Apply( void* Object, Tup&& Tuple, std::index_sequence< Index... > ) const
  70. {
  71. C* ClassObject = static_cast<C*>( Object );
  72. return ( ClassObject->*(m_Method) )( std::get< Index >( Tuple )... );
  73. }
  74. };
  75.  
  76. template< typename C, typename... Args >
  77. struct TFunctionType< void( C::* )( Args... ) > : public FunctionType
  78. {
  79. typedef void( C::*Type )( Args... );
  80.  
  81. TFunctionType( const char* Name, Type Method )
  82. : FunctionType( Name )
  83. , m_Method( Method )
  84. {
  85. }
  86.  
  87. private:
  88. Type m_Method;
  89.  
  90. virtual int32 InternalCall( lua_State* L, void* Object ) const override
  91. {
  92. TLuaFunction< Type >::ArgType Arguments = TLuaFunction< Type >::Call( L );
  93. Apply( Object, Arguments, std::make_index_sequence< std::tuple_size< TLuaFunction< Type >::ArgType >::value >{} );
  94. return 0;
  95. }
  96.  
  97. template< typename Tup, size_t... Index >
  98. void Apply( void* Object, Tup&& Tuple, std::index_sequence< Index... > ) const
  99. {
  100. C* ClassObject = static_cast<C*>( Object );
  101. ( ClassObject->*( m_Method ) )( std::get< Index >( Tuple )... );
  102. }
  103. };
  104.  
  105. template< typename Result, typename C >
  106. struct TFunctionType< Result( C::* )( void ) > : public FunctionType
  107. {
  108. typedef Result( C::*Type )( void );
  109.  
  110. TFunctionType( const char* Name, Type Method )
  111. : FunctionType( Name )
  112. , m_Method( Method )
  113. {
  114. }
  115.  
  116. private:
  117. Type m_Method;
  118.  
  119. virtual int32 InternalCall( lua_State* L, void* Object ) const override
  120. {
  121. if ( !TEqualType< Result, void >::Value )
  122. {
  123. Result RetVal = Apply( Object );
  124. TLuaPush< Result >::Push( L, RetVal );
  125. return 1;
  126. }
  127. else
  128. {
  129. Apply( Object );
  130. return 0;
  131. }
  132. }
  133.  
  134. Result Apply( void* Object ) const
  135. {
  136. C* ClassObject = static_cast<C*>( Object );
  137. return ( ClassObject->*( m_Method ) )();
  138. }
  139. };
  140.  
  141. template< typename C >
  142. struct TFunctionType< void( C::* )( void ) > : public FunctionType
  143. {
  144. typedef void( C::*Type )( void );
  145.  
  146. TFunctionType( const char* Name, Type Method )
  147. : FunctionType( Name )
  148. , m_Method( Method )
  149. {}
  150.  
  151. private:
  152. Type m_Method;
  153.  
  154. virtual int32 InternalCall( lua_State* L, void* Object ) const override
  155. {
  156. Apply( Object );
  157. return 0;
  158. }
  159.  
  160. void Apply( void* Object ) const
  161. {
  162. C* ClassObject = static_cast<C*>( Object );
  163. ( ClassObject->*( m_Method ) )( );
  164. }
  165. };
  166.  
  167. template< typename Result, typename C, typename... Args >
  168. struct TFunctionType< Result( C::* )( Args... ) const > : public FunctionType
  169. {
  170. typedef Result( C::*Type )( Args... ) const;
  171.  
  172. TFunctionType( const char* Name, Type Method )
  173. : FunctionType( Name )
  174. , m_Method( Method )
  175. {
  176.  
  177. }
  178. private:
  179. Type m_Method;
  180.  
  181. virtual void InternalCall( lua_State* L, void* Object ) const override
  182. {
  183. TLuaFunction< Type >::ArgType Arguments = TLuaFunction< Type >::Call( L );
  184. if ( !TEqualType< Result, void >::Value )
  185. {
  186. Result RetVal = Apply( Object, Arguments, std::make_index_sequence< std::tuple_size< TLuaFunction< Type >::ArgType >::value >{} );
  187. TLuaPush< Result >::Push( L, RetVal );
  188. return 1;
  189. }
  190. else
  191. {
  192. Apply( Object, Arguments, std::make_index_sequence< std::tuple_size< TLuaFunction< Type >::ArgType >::value >{} );
  193. return 0;
  194. }
  195.  
  196. return 0;
  197. }
  198.  
  199. template< typename Tup, size_t... Index >
  200. Result Apply( void* Object, Tup&& Tuple, std::index_sequence< Index... > ) const
  201. {
  202. C* ClassObject = static_cast<C*>( Object );
  203. return ( ClassObject->*( m_Method ) )( std::get< Index >( Tuple )... );
  204. }
  205. };
  206.  
  207. template< typename C, typename... Args >
  208. struct TFunctionType< void( C::* )( Args... ) const > : public FunctionType
  209. {
  210. typedef void( C::*Type )( Args... ) const;
  211.  
  212. TFunctionType( const char* Name, Type Method )
  213. : FunctionType( Name )
  214. , m_Method( Method )
  215. {}
  216.  
  217. private:
  218. Type m_Method;
  219.  
  220. virtual int32 InternalCall( lua_State* L, void* Object ) const override
  221. {
  222. TLuaFunction< Type >::ArgType Arguments = TLuaFunction< Type >::Call( L );
  223. Apply( Object, Arguments, std::make_index_sequence< std::tuple_size< TLuaFunction< Type >::ArgType >::value >{} );
  224. return 0;
  225. }
  226.  
  227. template< typename Tup, size_t... Index >
  228. void Apply( void* Object, Tup&& Tuple, std::index_sequence< Index... > ) const
  229. {
  230. C* ClassObject = static_cast<C*>( Object );
  231. ( ClassObject->*( m_Method ) )( std::get< Index >( Tuple )... );
  232. }
  233. };
  234.  
  235. template< typename Result, typename C >
  236. struct TFunctionType< Result( C::* )( void ) const > : public FunctionType
  237. {
  238. typedef Result( C::*Type )( void ) const;
  239.  
  240. TFunctionType( const char* Name, Type Method )
  241. : FunctionType( Name )
  242. , m_Method( Method )
  243. {}
  244.  
  245. private:
  246. Type m_Method;
  247.  
  248. virtual int32 InternalCall( lua_State* L, void* Object ) const override
  249. {
  250. if ( !TEqualType< Result, void >::Value )
  251. {
  252. Result RetVal = Apply( Object );
  253. TLuaPush< Result >::Push( L, RetVal );
  254. return 1;
  255. }
  256. else
  257. {
  258. Apply( Object );
  259. return 0;
  260. }
  261. }
  262.  
  263. Result Apply( void* Object ) const
  264. {
  265. C* ClassObject = static_cast<C*>( Object );
  266. return ( ClassObject->*( m_Method ) )( );
  267. }
  268. };
  269.  
  270. template< typename C >
  271. struct TFunctionType< void( C::* )( void ) const > : public FunctionType
  272. {
  273. typedef void( C::*Type )( void ) const;
  274.  
  275. TFunctionType( const char* Name, Type Method )
  276. : FunctionType( Name )
  277. , m_Method( Method )
  278. {}
  279.  
  280. private:
  281. Type m_Method;
  282.  
  283. virtual int32 InternalCall( lua_State* L, void* Object ) const override
  284. {
  285. Apply( Object );
  286. return 0;
  287. }
  288.  
  289. void Apply( void* Object ) const
  290. {
  291. C* ClassObject = static_cast<C*>( Object );
  292. ( ClassObject->*( m_Method ) )( );
  293. }
  294. };
  295.  
  296. static void Register( lua_State* L, const char* Namespace = nullptr )
  297. {
  298. if ( Namespace && strlen( Namespace ) )
  299. {
  300. lua_getglobal( L, Namespace );
  301. if ( lua_isnil( L, -1 ) )
  302. {
  303. lua_newtable( L );
  304. lua_pushvalue( L, -1 );
  305. lua_setglobal( L, Namespace );
  306. }
  307.  
  308. lua_pushcfunction( L, &TLuaClass< T >::New );
  309. lua_setfield( L, -2, T::GetClassName() );
  310. lua_pop( L, 1 );
  311. }
  312. else
  313. {
  314. lua_pushcfunction( L, &TLuaClass< T >::New );
  315. lua_setglobal( L, T::GetClassName() );
  316. }
  317.  
  318. luaL_newmetatable( L, T::GetClassName() );
  319. const int32 Metatable = lua_gettop( L );
  320.  
  321. lua_pushstring( L, "__gc" );
  322. lua_pushcfunction( L, &TLuaClass< T >::Collect );
  323. lua_settable( L, Metatable );
  324.  
  325. lua_pushstring( L, "__tostring" );
  326. lua_pushcfunction( L, &TLuaClass< T >::ToString );
  327. lua_settable( L, Metatable );
  328.  
  329. lua_pushstring( L, "__eq" );
  330. lua_pushcfunction( L, &TLuaClass< T >::Equals );
  331. lua_settable( L, Metatable );
  332.  
  333. lua_pushstring( L, "__index" );
  334. lua_pushcfunction( L, &TLuaClass< T >::Get );
  335. lua_settable( L, Metatable );
  336.  
  337. lua_pushstring( L, "__newindex" );
  338. lua_pushcfunction( L, &TLuaClass< T >::Set );
  339. lua_settable( L, Metatable );
  340.  
  341. const PropertyType* Properties = T::GetProperties();
  342. for ( int32 i = 0; Properties[ i ].Name; ++i )
  343. {
  344. lua_pushstring( L, Properties[ i ].Name );
  345. lua_pushinteger( L, i );
  346. lua_settable( L, Metatable );
  347. }
  348.  
  349. const FunctionType** Functions = T::GetFunctions();
  350. for ( int32 i = 0; Functions[ i ]->Name; ++i )
  351. {
  352. lua_pushstring( L, Functions[ i ]->Name );
  353. lua_pushinteger( L, i | ( 1 << 8 ) );
  354. lua_settable( L, Metatable );
  355. }
  356. }
  357.  
  358. static int32 New( lua_State* L )
  359. {
  360. T* Result = new T();
  361. T** Light = static_cast<T**>( lua_newuserdata( L, sizeof( T* ) ) );
  362.  
  363. *Light = Result;
  364.  
  365. luaL_getmetatable( L, T::GetClassName() );
  366. lua_setmetatable( L, -2 );
  367.  
  368. return 1;
  369. }
  370.  
  371. static int32 Get( lua_State* L )
  372. {
  373. lua_getmetatable( L, 1 );
  374. lua_pushvalue( L, 2 );
  375. lua_rawget( L, -2 );
  376.  
  377. if ( lua_isinteger( L, -1 ) )
  378. {
  379. const int32 Index = (int32)lua_tointeger( L, -1 );
  380.  
  381. T** Object = static_cast<T**>( lua_touserdata( L, 1 ) );
  382. lua_pushvalue( L, 3 );
  383.  
  384. if ( Index & ( 1 << 8 ) ) // function
  385. {
  386. lua_pushinteger( L, Index ^ ( 1 << 8 ) );
  387. lua_pushlightuserdata( L, Object );
  388. lua_pushcclosure( L, &TLuaClass< T >::Apply, 2 );
  389. return 1;
  390. }
  391.  
  392. lua_pop( L, 2 );
  393. lua_remove( L, 1 );
  394. lua_remove( L, 1 );
  395.  
  396. return ( ( *Object )->*( T::GetProperties()[ Index ].Getter ) )( L );
  397. }
  398.  
  399. return 1;
  400. }
  401.  
  402. static int32 Set( lua_State* L )
  403. {
  404. lua_getmetatable( L, 1 );
  405. lua_pushvalue( L, 2 );
  406. lua_rawget( L, -2 );
  407.  
  408. if ( lua_isinteger( L, -1 ) )
  409. {
  410. const int32 Index = (int32)lua_tointeger( L, -1 );
  411.  
  412. T** Object = static_cast<T**>( lua_touserdata( L, 1 ) );
  413. if ( !Object || !*Object )
  414. {
  415. luaL_error( L, "Error: No object provided to setter." );
  416. return 0;
  417. }
  418.  
  419. if ( Index >> 8 ) // function
  420. {
  421. char buffer[ 128 ];
  422. sprintf_s( buffer, "Error: Trying to set the method [%s] of class [%s].", ( *Object )->T::GetFunctions()[ Index ^ ( 1 << 8 ) ]->Name, T::GetClassName() );
  423. luaL_error( L, buffer );
  424. return 0;
  425. }
  426.  
  427. lua_pop( L, 2 );
  428. lua_remove( L, 1 );
  429. lua_remove( L, 1 );
  430.  
  431. return ( ( *Object )->*( T::GetProperties()[ Index ].Setter ) )( L );
  432. }
  433.  
  434. return 0;
  435. }
  436.  
  437. static int32 Apply( lua_State* L )
  438. {
  439. const int32 Index = (int32)lua_tointeger( L, lua_upvalueindex( 1 ) );
  440. T** Object = static_cast<T**>( lua_touserdata( L, lua_upvalueindex( 2 ) ) );
  441.  
  442. const TLuaClass< T >::FunctionType** Functions = T::GetFunctions();
  443. const TLuaClass< T >::FunctionType* Func = Functions[ Index ];
  444.  
  445. return Func->Call( L, *Object );
  446. }
  447.  
  448. static int32 Collect( lua_State* L )
  449. {
  450. T** Object = static_cast<T**>( lua_touserdata( L, -1 ) );
  451. if ( Object && *Object )
  452. {
  453. delete *Object;
  454. }
  455.  
  456. return 0;
  457. }
  458.  
  459. static int32 ToString( lua_State* L )
  460. {
  461. T** Object = static_cast<T**>( lua_touserdata( L, -1 ) );
  462. if ( Object )
  463. {
  464. lua_pushfstring( L, "%s (%p)", T::GetClassName(), (void*)*Object );
  465. }
  466. else
  467. {
  468. lua_pushstring( L, "Empty" );
  469. }
  470.  
  471. return 1;
  472. }
  473.  
  474. static int32 Equals( lua_State* L )
  475. {
  476. T** Left = static_cast<T**>( lua_touserdata( L, -1 ) );
  477. T** Right = static_cast<T**>( lua_touserdata( L, 1 ) );
  478.  
  479. lua_pushboolean( L, *Left == *Right );
  480.  
  481. return 1;
  482. }
  483. };
  484.  
  485. template< typename T >
  486. struct TLuaFunction
  487. {
  488. public:
  489. typedef typename TFunctionArgs< T >::Type ArgType;
  490. typedef typename TFunctionResult< T >::Type ResultType;
  491.  
  492. static ArgType Call( lua_State* L )
  493. {
  494. return Helper( L, std::make_index_sequence< std::tuple_size< ArgType >::value >{} );
  495. }
  496.  
  497. private:
  498. template< typename U >
  499. static std::tuple< U > Work( int32& Index, lua_State* L )
  500. {
  501. return std::make_tuple( TLuaRead< U >::Read( L, Index++ ) );
  502. }
  503.  
  504. template< typename U1, typename U2, typename... US >
  505. static std::tuple< U1, U2, US... > Work( int32& Index, lua_State* L )
  506. {
  507. std::tuple< U1 > Start = Work< U1 >( Index, L );
  508. return std::tuple_cat( Start, Work< U2, US... >( Index, L ) );
  509. }
  510.  
  511. template< size_t... Index >
  512. static ArgType Helper( lua_State* L, std::index_sequence< Index... > )
  513. {
  514. int32 IndexHelper = 1;
  515. return Work< std::tuple_element_t< Index, ArgType >... >( IndexHelper, L );
  516. }
  517. };
  518.  
  519. #define DECLARE_LUA_CLASS( ClassType ) \
  520. private: \
  521. using TProperty = TLuaClass< class ClassType >::PropertyType; \
  522. using TFunction = TLuaClass< class ClassType >::FunctionType; \
  523. static const TProperty Properties[]; \
  524. static const TFunction* Functions[]; \
  525. public: \
  526. static const char* GetClassName() { return #ClassType; } \
  527. static const TProperty* GetProperties() { return Properties; } \
  528. static const TFunction** GetFunctions() { return Functions; } \
  529. private:
  530.  
  531. #define INITIALIZE_LUA_PROPERTIES( ClassType ) const ClassType::TProperty ClassType::Properties[] = { { nullptr } };
  532.  
  533. #define INITIALIZE_LUA_FUNCTIONS( ClassType ) const ClassType::TFunction* ClassType::Functions[] = {
  534. #define FINALIZE_LUA_FUNCTIONS( ClassType ) new ClassType::TFunction{ nullptr } };
  535.  
  536. #define DECLARE_LUA_FUNCTION( ClassType, Function ) new TLuaClass< ClassType >::TFunctionType< decltype( &ClassType::Function ) >{ #Function, &ClassType::Function }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement