1 /*
2  * This source file is part of libRocket, the HTML/CSS Interface Middleware
3  *
4  * For the latest information, see http://www.librocket.com
5  *
6  * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and associated documentation files (the "Software"), to deal
10  * in the Software without restriction, including without limitation the rights
11  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12  * copies of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24  * THE SOFTWARE.
25  *
26  */
27 
28 #ifndef ROCKETCORELUALUATYPE_H
29 #define ROCKETCORELUALUATYPE_H
30 
31 #include <Rocket/Core/Lua/Header.h>
32 #include <Rocket/Core/Lua/lua.hpp>
33 
34 
35 //As an example, if you used this macro like
36 //LUAMETHOD(Unit,GetId)
37 //it would result in code that looks like
38 //{ "GetId", UnitGetId },
39 //Which would force you to create a global function named UnitGetId in C with the correct function signature, usually int(*)(lua_State*,type*);
40 #define LUAMETHOD(type,name) { #name, type##name },
41 
42 //See above, but the method must match the function signature int(*)(lua_State*) and as example:
43 //LUAGETTER(Unit,Id) would mean you need a function named UnitGetAttrId
44 //The first stack position will be the userdata
45 #define LUAGETTER(type,varname) { #varname, type##GetAttr##varname },
46 
47 //Same method signature as above, but as example:
48 //LUASETTER(Unit,Id) would mean you need a function named UnitSetAttrId
49 //The first stack position will be the userdata, and the second will be value on the other side of the equal sign
50 #define LUASETTER(type,varname) { #varname, type##SetAttr##varname },
51 
52 #define CHECK_BOOL(L,narg) (lua_toboolean((L),(narg)) > 0 ? true : false )
53 #define LUACHECKOBJ(obj) if((obj) == NULL) { lua_pushnil(L); return 1; }
54 
55  /** Used to remove repetitive typing at the cost of flexibility. When you use this, you @em must have
56  functions with the same name as defined in the macro. For example, if you used @c Element as type, you would
57  have to have functions named @c ElementMethods, @c ElementGetters, @c ElementSetters that return the appropriate
58  types.
59  @param is_reference_counted true if the type inherits from Rocket::Core::ReferenceCountable, false otherwise*/
60 #define LUACORETYPEDEFINE(type,is_ref_counted) \
61     template<> const char* GetTClassName<type>() { return #type; } \
62     template<> RegType<type>* GetMethodTable<type>() { return type##Methods; } \
63     template<> luaL_Reg* GetAttrTable<type>() { return type##Getters; } \
64     template<> luaL_Reg* SetAttrTable<type>() { return type##Setters; } \
65     template<> bool IsReferenceCounted<type>() { return (is_ref_counted); } \
66 
67 //We can't use LUACORETYPEDEFINE due to namespace issues
68 #define LUACONTROLSTYPEDEFINE(type,is_ref_counted) \
69     template<> const char* GetTClassName<type>() { return #type; } \
70     template<> RegType<type>* GetMethodTable<type>() { return Rocket::Controls::Lua::type##Methods; } \
71     template<> luaL_Reg* GetAttrTable<type>() { return Rocket::Controls::Lua::type##Getters; } \
72     template<> luaL_Reg* SetAttrTable<type>() { return Rocket::Controls::Lua::type##Setters; } \
73     template<> bool IsReferenceCounted<type>() { return (is_ref_counted); } \
74 
75 /** Used to remove repetitive typing at the cost of flexibility. It creates function prototypes for
76 getting the name of the type, method tables, and if it is reference counted.
77 When you use this, you either must also use
78 the LUACORETYPEDEFINE macro, or make sure that the function signatures are @em exact.*/
79 #define LUACORETYPEDECLARE(type) \
80     template<> ROCKETLUA_API const char* GetTClassName<type>(); \
81     template<> ROCKETLUA_API RegType<type>* GetMethodTable<type>(); \
82     template<> ROCKETLUA_API luaL_Reg* GetAttrTable<type>(); \
83     template<> ROCKETLUA_API luaL_Reg* SetAttrTable<type>(); \
84     template<> ROCKETLUA_API bool IsReferenceCounted<type>(); \
85 
86 /** Used to remove repetitive typing at the cost of flexibility. It creates function prototypes for
87 getting the name of the type, method tables, and if it is reference counted.
88 When you use this, you either must also use
89 the LUACORETYPEDEFINE macro, or make sure that the function signatures are @em exact.*/
90 #define LUACONTROLSTYPEDECLARE(type) \
91     template<> ROCKETLUA_API const char* GetTClassName<type>(); \
92     template<> ROCKETLUA_API RegType<type>* GetMethodTable<type>(); \
93     template<> ROCKETLUA_API luaL_Reg* GetAttrTable<type>(); \
94     template<> ROCKETLUA_API luaL_Reg* SetAttrTable<type>(); \
95     template<> ROCKETLUA_API bool IsReferenceCounted<type>(); \
96 
97 namespace Rocket {
98 namespace Core {
99 namespace Lua {
100 //replacement for luaL_Reg that uses a different function pointer signature, but similar syntax
101 template<typename T>
102 struct ROCKETLUA_API RegType
103 {
104     const char* name;
105     int (*ftnptr)(lua_State*,T*);
106 };
107 
108 /** For all of the methods available from Lua that call to the C functions. */
109 template<typename T> ROCKETLUA_API RegType<T>* GetMethodTable();
110 /** For all of the function that 'get' an attribute/property */
111 template<typename T> ROCKETLUA_API luaL_Reg* GetAttrTable();
112 /** For all of the functions that 'set' an attribute/property  */
113 template<typename T> ROCKETLUA_API luaL_Reg* SetAttrTable();
114 /** String representation of the class */
115 template<typename T> ROCKETLUA_API const char* GetTClassName();
116 /** bool for if it is reference counted */
117 template<typename T> ROCKETLUA_API bool IsReferenceCounted();
118 /** gets called from the LuaType<T>::Register function, right before @c _regfunctions.
119 If you want to inherit from another class, in the function you would want
120 to call @c _regfunctions<superclass>, where method is metatable_index - 1. Anything
121 that has the same name in the subclass will be overwrite whatever had the
122 same name in the superclass.    */
123 template<typename T> ROCKETLUA_API void ExtraInit(lua_State* L, int metatable_index);
124 
125 /**
126     This is mostly the definition of the Lua userdata that C++ gives to the user, plus
127     some helper functions.
128 
129     @author Nathan Starkey
130 */
131 template<typename T>
132 class ROCKETLUA_API LuaType
133 {
134 public:
135     typedef int (*ftnptr)(lua_State* L, T* ptr);
136     /** replacement for luaL_Reg that uses a different function pointer signature, but similar syntax */
137     typedef struct { const char* name; ftnptr func; } RegType;
138 
139     /** Registers the type T as a type in the Lua global namespace by creating a
140      metatable with the same name as the class, setting the metatmethods, and adding the
141      functions from _regfunctions */
142     static inline void Register(lua_State *L);
143     /** Pushes on to the Lua stack a userdata representing a pointer of T
144     @param obj[in] The object to push to the stack
145     @param gc[in] If the obj should be deleted or decrease reference count upon the garbage collection
146     metamethod being called from the object in Lua
147     @return Position on the stack where the userdata resides   */
148     static inline int push(lua_State *L, T* obj, bool gc=false);
149     /** Statically casts the item at the position on the Lua stack
150     @param narg[in] Position of the item to cast on the Lua stack
151     @return A pointer to an object of type T or @c NULL   */
152     static inline T* check(lua_State* L, int narg);
153 
154     /** For calling a C closure with upvalues. Used by the functions defined by RegType
155     @return The value that RegType.func returns   */
156     static inline int thunk(lua_State* L);
157     /** String representation of the pointer. Called by the __tostring metamethod  */
158     static inline void tostring(char* buff, void* obj);
159     //these are metamethods
160     /** The __gc metamethod. If the object was pushed by push(lua_State*,T*,bool) with the third
161     argument as true, it will either decrease the reference count or call delete depending on if
162     the type is reference counted. If the third argument to push was false, then this does nothing.
163     @return 0, since it pushes nothing on to the stack*/
164     static inline int gc_T(lua_State* L);
165     /** The __tostring metamethod.
166     @return 1, because it pushes a string representation of the userdata on to the stack  */
167     static inline int tostring_T(lua_State* L);
168     /** The __index metamethod. Called whenever the user attempts to access a variable that is
169     not in the immediate table. This handles the method calls and calls tofunctions in __getters    */
170     static inline int index(lua_State* L);
171     /** The __newindex metamethod. Called when the user attempts to set a variable that is not
172     int the immediate table. This handles the calls to functions in __setters  */
173     static inline int newindex(lua_State* L);
174 
175     /** Registers methods,getters,and setters to the type. In Lua, the methods exist in the Type name's
176     metatable, and the getters exist in __getters and setters in __setters. The reason for __getters and __setters
177     is to have the objects use a 'dot' syntax for properties and a 'colon' syntax for methods.*/
178     static inline void _regfunctions(lua_State* L, int meta, int method);
179 private:
180     LuaType(); //hide constructor
181 
182 };
183 
184 
185 }
186 }
187 }
188 
189 #include "LuaType.inl"
190 #endif