Linux multi-monitor fullscreen support
[ryzomcore.git] / ryzom / tools / leveldesign / variable_parser / lua_helper.h
blobf80449a793b61c8f5160c0635c660a764d22db98
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #ifndef RZ_LUA_HELPER_H
18 #define RZ_LUA_HELPER_H
21 #include "nel/misc/types_nl.h"
22 #include "nel/misc/smart_ptr.h"
24 extern "C"
26 #include <lua.h>
30 class CLuaState;
32 // ***************************************************************************
33 /** Helper class to see if a stack is restored at its initial size (or with n return results).
34 * Check that the stack size remains unchanged when the object goes out of scope
36 class CLuaStackChecker
38 public:
39 CLuaStackChecker(CLuaState *state, int numWantedResults = 0);
40 ~CLuaStackChecker();
41 /** Increment exception context counter
42 * When an exception is thrown, lua stack checker do any assert bu will
43 * rather restore the lua stack at its original size, and will
44 * let the exception a chance to propagate
46 static void incrementExceptionContextCounter();
47 static void decrementExceptionContextCounter();
49 private:
50 CLuaState *_State;
51 int _FinalWantedSize;
52 static uint _ExceptionContextCounter;
56 // **************************************************************************
57 /** Helper class to restore the lua stack to the desired size when this object goes out of scope
59 class CLuaStackRestorer
61 public:
62 CLuaStackRestorer(CLuaState *state, int finalSize);
63 ~CLuaStackRestorer();
64 private:
65 int _FinalSize;
66 CLuaState *_State;
69 ////////////////
70 // EXCEPTIONS //
71 ////////////////
73 class ELuaError : public NLMISC::Exception
75 public:
76 ELuaError() { CLuaStackChecker::incrementExceptionContextCounter(); }
77 virtual ~ELuaError() throw() { CLuaStackChecker::decrementExceptionContextCounter(); }
78 ELuaError(const std::string &reason) : Exception(reason) { CLuaStackChecker::incrementExceptionContextCounter(); }
79 // what(), plus append the Reason
80 virtual std::string luaWhat() const throw() {return NLMISC::toString("LUAError: %s", what());}
83 // A parse error occurred
84 class ELuaParseError : public ELuaError
86 public:
87 ELuaParseError() {}
88 ELuaParseError(const std::string &reason) : ELuaError(reason) {}
89 virtual ~ELuaParseError() throw() { }
90 // what(), plus append the Reason
91 virtual std::string luaWhat() const throw() {return NLMISC::toString("ELuaParseError: %s", what());}
94 /** Exception thrown when something went wrong inside a wrapped function called by lua
96 class ELuaWrappedFunctionException : public ELuaError
98 public:
99 ELuaWrappedFunctionException(CLuaState *luaState);
100 ELuaWrappedFunctionException(CLuaState *luaState, const std::string &reason);
101 ELuaWrappedFunctionException(CLuaState *luaState, const char *format, ...);
102 virtual ~ELuaWrappedFunctionException() throw() { }
103 virtual const char *what() const throw() {return _Reason.c_str();}
104 protected:
105 void init(CLuaState *ls, const std::string &reason);
106 protected:
107 std::string _Reason;
110 // A execution error occurred
111 class ELuaExecuteError : public ELuaError
113 public:
114 ELuaExecuteError() {}
115 ELuaExecuteError(const std::string &reason) : ELuaError(reason) {}
116 virtual ~ELuaExecuteError() throw() { }
117 // what(), plus append the Reason
118 virtual std::string luaWhat() const throw() {return NLMISC::toString("ELuaExecuteError: %s", what());}
121 // A bad cast occurred when using lua_checkcast
122 class ELuaBadCast : public ELuaError
124 public:
125 ELuaBadCast() {}
126 ELuaBadCast(const std::string &reason) : ELuaError(reason) {}
127 // what(), plus append the Reason
128 virtual std::string luaWhat() const throw() {return NLMISC::toString("ELuaBadCast: %s", what());}
131 // Error when trying to indexate an object that is not a table
132 class ELuaNotATable : public ELuaError
134 public:
135 ELuaNotATable() {}
136 ELuaNotATable(const std::string &reason) : ELuaError(reason) {}
137 // what(), plus append the Reason
138 virtual std::string luaWhat() const throw() {return NLMISC::toString("ELuaNotATable: %s", what());}
142 // ***************************************************************************
143 // a function to be used with a CLuaState instance
144 typedef int (* TLuaWrappedFunction) (CLuaState &ls);
147 // ***************************************************************************
148 /** C++ version of a lua state
150 class CLuaState : public NLMISC::CRefCount
152 public:
153 typedef NLMISC::CRefPtr<CLuaState> TRefPtr;
155 // Create a new environement
156 CLuaState();
157 ~CLuaState();
160 /// \name Registering
161 // @{
162 // register a wrapped function
163 void registerFunc(const char *name, TLuaWrappedFunction function);
164 // @}
167 /// \name Script execution
168 // @{
170 /** Parse a script and push as a function in top of the LUA stack
171 * \throw ELuaParseError
172 * \param dbgSrc is a string for debug. Should be a filename (preceded with '@'), or a short script.
174 void loadScript(const std::string &code, const std::string &dbgSrc);
176 /** Execute a script from a string, possibly throwing an exception if there's a parse error
177 * \throw ELuaParseError, ELuaExecuteError
179 void executeScript(const std::string &code, int numRet = 0);
181 /** Execute a script from a string. If an errors occurs it is printed in the log
182 * \return true if script execution was successful
184 bool executeScriptNoThrow(const std::string &code, int numRet = 0);
186 /** Load a Script from a File (maybe in a BNP), and execute it
187 * \return false if file not found
188 * \throw ELuaParseError, ELuaExecuteError
190 bool executeFile(const std::string &pathName);
192 /** execute a very Small Script (a function call for instance)
193 * It is different from doString() in such there is a cache (where the key is the script itself)
194 * so that the second time this script is executed, there is no parsing
195 * Note: I experienced optim with about 10 times faster than a executeScript() on a simple "a= a+1;" script
196 * \throw ELuaParseError, ELuaExecuteError
198 void executeSmallScript(const std::string &script);
200 // @}
203 /// \name Stack Manipulation
204 // @{
205 // stack manipulation (indices start at 1)
206 void setTop(int index); // set new size of stack
207 void clear() { setTop(0); }
208 int getTop();
209 bool empty() { return getTop() == 0; }
210 void pushValue(int index); // copie nth element of stack to the top of the stack
211 void remove(int index); // remove nth element of stack
212 void insert(int index); // insert last element of the stack before the given position
213 void replace(int index); // replace nth element of the stack with the top of the stack
214 void pop(int numElem = 1); // remove n elements from the top of the stack
215 // test the type of an element in the stack
216 // return one of the following values :
217 // LUA_TNIL
218 // LUA_TNUMBER
219 // LUA_TBOOLEAN
220 // LUA_TSTRING
221 // LUA_TTABLE
222 // LUA_TFUNCTION
223 // LUA_TUSERDATA
224 // LUA_TTHREAD
225 // LUA_TLIGHTUSERDATA
226 int type(int index = -1);
227 const char *getTypename(int type);
228 bool isNil(int index = -1);
229 bool isBoolean(int index = -1);
230 bool isNumber(int index = -1);
231 bool isString(int index = -1);
232 bool isTable(int index = -1);
233 bool isFunction(int index = -1);
234 bool isCFunction(int index = -1);
235 bool isUserData(int index = -1);
236 bool isLightUserData(int index = -1);
237 // converting then getting a value from the stack
238 bool toBoolean(int index = -1);
239 lua_Number toNumber(int index = -1);
240 const char *toString(int index = -1);
241 void toString(int index, std::string &str); // convert to a std::string, with a NULL check.
242 size_t strlen(int index = -1);
243 lua_CFunction toCFunction(int index = -1);
244 void *toUserData(int index = -1);
245 const void *toPointer(int index = -1);
246 /** Helper functions : get value of the wanted type in the top table after conversion
247 * A default value is used if the stack entry is NULL.
248 * If conversion fails then an exception is thrown (with optional msg)
250 bool getTableBooleanValue(const char *name, bool defaultValue= false);
251 double getTableNumberValue(const char *name, double defaultValue= 0);
252 const char *getTableStringValue(const char *name, const char *defaultValue= NULL);
253 // pushing value onto the stack
254 void push(bool value);
255 void push(lua_Number value);
256 void push(const char *str);
257 void push(const char *str, int length);
258 void push(const std::string &str);
259 void pushNil();
260 void push(lua_CFunction f);
261 void push(TLuaWrappedFunction function);
262 void pushLightUserData(void *); // push a light user data (use newUserData to push a full userdata)
263 // metatables
264 bool getMetaTable(int index = -1);
265 bool setMetaTable(int index = -1); // set the metatable at top of stack to the object at 'index' (usually -2), then pop the metatable
266 // even if asignment failed
267 // comparison
268 bool equal(int index1, int index2);
269 bool rawEqual(int index1, int index2);
270 bool lessThan(int index1, int index2);
271 // concatenation of the n element at the top of the stack (using lua semantic)
272 void concat(int numElem);
273 // tables
274 void newTable(); // create a new table at top of the stack
275 void getTable(int index); // get value from a table at index 'index' (key is at top)
276 void rawGet(int index);
277 void setTable(int index); // set (key, value) from top of the stack into the given table
278 // both key and value are poped
279 void rawSet(int index);
280 bool next(int index); // table traversal
281 // UserData
282 void *newUserData(uint size);
283 // seting value by int index in a table
284 void rawSetI(int index, int n);
285 void rawGetI(int index, int n);
286 /** Calling functions (it's up to the caller to clear the results)
287 * The function should have been pushed on the stack
289 void call(int nargs, int nresults);
290 int pcall(int nargs, int nresults, int errfunc = 0);
291 /** Helper : Execute a function by name. Lookup for the function is done in the table at the index 'funcTableIndex'
292 * the behaviour is the same than with call of pcall.
294 int pcallByName(const char *functionName, int nargs, int nresults, int funcTableIndex = LUA_GLOBALSINDEX, int errfunc = 0);
296 // push a C closure (pop n element from the stack and associate with the function)
297 void pushCClosure(lua_CFunction function, int n);
298 // @}
301 /// \name Misc
302 // @{
303 /** Retrieve pointer to a CLuaState environment from its lua_State pointer, or NULL
304 * if there no such environment
306 static CLuaState *fromStatePointer(lua_State *state);
307 // Get state pointer. The state should not be closed (this object has ownership)
308 lua_State *getStatePointer() const {return _State;}
309 // check that an index is valid when accessing the stack
310 // an assertion is raised if the index is not valid
311 void checkIndex(int index);
313 // registering C function to use with a lua state pointer
314 void registerFunc(const char *name, lua_CFunction function);
316 // Garbage collector
317 int getGCCount(); // get memory in use in KB
318 int getGCThreshold(); // get max memory in KB
319 void setGCThreshold(int kb); // set max memory in KB (no-op with ref-counted version)
321 // handle garbage collector for ref-counted version of lua (no-op with standard version, in which case gc handling is automatic)
322 void handleGC();
324 /** For Debug: get the Stack context of execution (filename / line)
325 * \param stackLevel: get the context of execution of the given stackLevel.
326 * 0 for the current function
327 * 1 for the function that called 0
328 * 2 ....
329 * NB: if called from a C function called from LUA, remember that stackLevel 0 is the current function.
330 * Hence if you want to know what LUA context called you, pass stackLevel=1!
331 * \param ret string cleared if any error, else filled with formated FileName / LineNumber
333 void getStackContext(std::string &ret, uint stackLevel);
334 // @}
336 // for debug : dump the current content of the stack (no recursion)
337 void dumpStack();
338 static void dumpStack(lua_State *ls);
339 void getStackAsString(std::string &dest);
342 private:
343 lua_State *_State;
345 // Small Script Cache
346 uint _SmallScriptPool;
347 typedef std::map<std::string, uint> TSmallScriptCache;
348 TSmallScriptCache _SmallScriptCache;
349 static const char * _NELSmallScriptTableName;
351 private:
352 // this object isn't intended to be copied
353 CLuaState(const CLuaState &/* other */):NLMISC::CRefCount() { nlassert(0); }
354 CLuaState &operator=(const CLuaState &/* other */) { nlassert(0); return *this; }
356 void executeScriptInternal(const std::string &code, const std::string &dbgSrc, int numRet = 0);
361 // Access to lua function
362 // one should not include lua.h directly because if a debugger is present, lua
363 // function pointer will be taken from a dynamic library.
367 //=============================================================================================
368 // include implementation
369 #define RZ_INCLUDE_LUA_HELPER_INLINE
370 #include "lua_helper_inline.h"
371 #undef RZ_INCLUDE_LUA_HELPER_INLINE
374 #endif