love / src / common / runtime.h

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
/**
 * Copyright (c) 2006-2013 LOVE Development Team
 *
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors be held liable for any damages
 * arising from the use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would be
 *    appreciated but is not required.
 * 2. Altered source versions must be plainly marked as such, and must not be
 *    misrepresented as being the original software.
 * 3. This notice may not be removed or altered from any source distribution.
 **/

#ifndef LOVE_RUNTIME_H
#define LOVE_RUNTIME_H

// LOVE
#include "types.h"
#include "Object.h"

// Lua
extern "C" {
	#define LUA_COMPAT_ALL
	#include <lua.h>
	#include <lualib.h>
	#include <lauxlib.h>
}

namespace love
{

// Forward declarations.
class Module;
class Reference;

// Exposed mutex of the GC
extern void *_gcmutex;

/**
 * Registries represent special tables which can be accessed with
 * luax_insistregistry and luax_getregistry.
 **/
enum Registry
{
	REGISTRY_GC = 1,
	REGISTRY_MODULES,
	REGISTRY_TYPES
};

/**
 * This structure wraps all Lua-exposed objects. It exists in the
 * Lua state as a full userdata (so we can catch __gc "events"),
 * though the Object it refers to is light userdata in the sense
 * that it is not allocated by the Lua VM.
 **/
struct Proxy
{
	// Holds type information (see types.h).
	bits flags;

	// The light userdata (pointer to the love::Object).
	void *data;

	// The number of times release() should be called on GC.
	int retains;
};

/**
 * A Module with Lua wrapper functions and other data.
 **/
struct WrappedModule
{
	// The module containing the functions.
	Module *module;

	// The name for the table to put the functions in, without the 'love'-prefix.
	const char *name;

	// The type flags of this module.
	love::bits flags;

	// The functions of the module (last element {0,0}).
	const luaL_Reg *functions;

	// A list of functions which expose the types of the modules (last element 0).
	const lua_CFunction *types;

};

/**
 * Returns a reference to the top stack element (-1) if the value
 * is of the specified type. If the value is incorrect, zero is returned.
 *
 * In any case, the top stack element is popped, regardless of its type.
 **/
Reference *luax_refif(lua_State *L, int type);

/**
 * Prints the current contents of the stack. Only useful for debugging.
 * @param L The Lua state.
 **/
void luax_printstack(lua_State *L);

/**
 * Converts the value at idx to a bool. It follow the same rules
 * as lua_toboolean, but returns a bool instead of an int.
 * @param L The Lua state.
 * @param idx The index on the Lua stack.
 * @return True if the value evaluates to true, false otherwise.
 **/
bool luax_toboolean(lua_State *L, int idx);

/**
 * Pushes a bool onto the stack. It's the same as lua_pushboolean,
 * but with bool instead of int.
 * @param L The Lua state.
 * @param b The bool to push.
 **/
void luax_pushboolean(lua_State *L, bool b);

/**
 * Converts the value at idx to a bool, or if not present, b is returned.
 * @param L The Lua state.
 * @param idx The index of the Lua stack.
 * @param b The value to return if no value exist at the specified index.
 * @return True if the value evaluates to true, false otherwise.
 **/
bool luax_optboolean(lua_State *L, int idx, bool b);

/**
 * Converts the value at idx to a std::string. It takes care of the string
 * size and possible embedded nulls.
 * @param L The Lua state.
 * @param idx The index on the Lua stack.
 * @return Copy of the string at the specified index.
 **/
std::string luax_tostring(lua_State *L, int idx);

/**
 * Converts the value at idx to a std::string. It takes care of the string
 * size and possible embedded nulls.
 * @param L The Lua state.
 * @param idx The index on the Lua stack.
 * @return Copy of the string at the specified index.
 **/
std::string luax_checkstring(lua_State *L, int idx);

/**
 * Pushes a std::string onto the stack. It uses the length of the string
 * for lua_pushlstring's len argument.
 * @param L The Lua state.
 * @param str The string to push.
 **/
void luax_pushstring(lua_State *L, const std::string &str);


bool luax_boolflag(lua_State *L, int table_index, const char *key, bool defaultValue);
int luax_intflag(lua_State *L, int table_index, const char *key, int defaultValue);

/**
 * Convert the value at the specified index to an Lua number, and then
 * convert to a float.
 *
 * @param L The Lua state.
 * @param idx The index on the stack.
 */
inline float luax_tofloat(lua_State *L, int idx)
{
	return static_cast<float>(lua_tonumber(L, idx));
}

/**
 * Like luax_tofloat, but checks that the value is a number.
 *
 * @see luax_tofloat
 */
inline float luax_checkfloat(lua_State *L, int idx)
{
	return static_cast<float>(luaL_checknumber(L, idx));
}

/**
 * Require at least 'min' number of items on the stack.
 * @param L The Lua state.
 * @param min The minimum number of items on the stack.
 * @return Zero if conditions are met, otherwise a Lua error (longjmp).
 **/
int luax_assert_argc(lua_State *L, int min);

/**
 * Require at least 'min', but more than 'max' items on the stack.
 * @param L The Lua state.
 * @param min The minimum number of items on the stack.
 * @param max The maximum number of items on the stack.
 * @return Zero if conditions are met, otherwise a Lua error (longjmp).
 **/
int luax_assert_argc(lua_State *L, int min, int max);

/**
 * Require that the value at idx is a function.
 * @param L The Lua state.
 *@param idx The index on the stack.
 **/
int luax_assert_function(lua_State *L, int idx);

/**
 * Require that the value at idx is not nil. If it is, the function throws an
 * error using an optional error string at idx+1.
 * @param L The Lua state.
 * @param idx The index on the stack.
 **/
int luax_assert_nilerror(lua_State *L, int idx);

/**
 * Registers all functions in the array l (see luaL_Reg) into the table at the
 * top of the stack.
 * Similar to Lua 5.2's luaL_setfuncs without the upvalues, and to Lua 5.1's
 * luaL_register without the library name.
 **/
void luax_setfuncs(lua_State *L, const luaL_Reg *l);

/**
 * Register a module in the love table. The love table will be created if it does not exist.
 * @param L The Lua state.
 **/
int luax_register_module(lua_State *L, const WrappedModule &m);

/**
 * Inserts a module with 'name' into the package.preloaded table.
 * @param f The function to be called when the module is opened.
 * @param name The name of the module, with 'love'-prefix, for instance 'love.graphics'.
 **/
int luax_preload(lua_State *L, lua_CFunction f, const char *name);

/**
 * Register a new type.
 * @param tname The name of the type. This must not conflict with other type names,
 * even from other modules.
 * @param f The list of member functions for the type.
 **/
int luax_register_type(lua_State *L, const char *tname, const luaL_Reg *f = 0);

/**
 * Do a table.insert from C
 * @param L the state
 * @param tindex the stack index of the table
 * @param vindex the stack index of the value
 * @param pos the position to insert it in
 **/
int luax_table_insert(lua_State *L, int tindex, int vindex, int pos = -1);

/**
 * Register a new searcher function for package.loaders. This can for instance enable
 * loading of files through love.filesystem using standard require.
 * @param L The Lua state.
 * @param f The searcher function.
 * @param pos The position to insert the loader in.
 **/
int luax_register_searcher(lua_State *L, lua_CFunction f, int pos = -1);

/**
 * Pushes a Lua representation of the given object onto the stack, creating and
 * storing the Lua representation in a weak table if it doesn't exist yet.
 * @param L The Lua state.
 * @param name The name of the type. This must match the name used with luax_register_type.
 * @param flags The type information of the object.
 * @param data The pointer to the actual object.
 * @param own Set this to true (default) if the object should be released upon garbage collection.
 **/
void luax_pushtype(lua_State *L, const char *name, bits flags, love::Object *data, bool own = true);

/**
 * Creates a new Lua representation of the given object *without* checking if it
 * exists yet, and *without* storing it in a weak table.
 * This should only be used when performance is an extreme concern and the
 * object is not ever expected to be pushed to Lua again, as it prevents the
 * Lua-side objects from working in all cases when used as keys in tables.
 * @param L The Lua state.
 * @param name The name of the type. This must match the name used with luax_register_type.
 * @param flags The type information of the object.
 * @param data The pointer to the actual object.
 * @param own Set this to true (default) if the object should be released upon garbage collection.
 **/
void luax_rawnewtype(lua_State *L, const char *name, bits flags, love::Object *data, bool own = true);

/**
 * Checks whether the value at idx is a certain type.
 * @param L The Lua state.
 * @param idx The index on the stack.
 * @param type The type to check for.
 * @return True if the value is Proxy of the specified type, false otherwise.
 **/
bool luax_istype(lua_State *L, int idx, love::bits type);

/**
 * Gets the function love.module.function and puts it on top of the stack (alone). If the
 * love table, the module, or the function does not exist, an error is returned.
 * @return An error if nonexistent, or 1 if successful.
 **/
int luax_getfunction(lua_State *L, const char *module, const char *function);

/**
 * Converts an object into another object by the specified function love.module.function.
 * The conversion function must accept a single object of the relevant type as a parameter,
 * and returnone value. If the function does not exist (see luax_getfunction), an error is returned.
 *
 * Note that the initial object at idx is replaced by the new object.
 *
 * @param L The Lua state.
 * @param idx The index on the stack.
 * @param module The module in the love table.
 * @param function The function in the module.
 **/
int luax_convobj(lua_State *L, int idx, const char *module, const char *function);

/**
 * Converts an object into another object by the specified function love.module.function.
 * The conversion function must accept a single object of the relevant type as its first parameter,
 * and return one value. If the function does not exist (see luax_getfunction), an error is returned.
 *
 * Note that the initial object at idx is replaced by the new object.
 *
 * @param L The Lua state.
 * @param idxs An array of indices on the stack.
 * @param n How many arguments are being passed.
 * @param module The module in the love table.
 * @param function The function in the module.
 **/
int luax_convobj(lua_State *L, int idxs[], int n, const char *module, const char *function);

// pcall versions of the above
int luax_pconvobj(lua_State *L, int idx, const char *module, const char *function);
int luax_pconvobj(lua_State *L, int idxs[], int n, const char *module, const char *function);

/**
 * 'Insist' that a table 'k' exists in the table at idx. Insistence involves that the
 * table (k) is created if it does not exist in the table at idx. The table at idx must
 * pre-exist, however. Also note that if the a non-table value exists at the specified
 * location, it will be overwritten with a new table. The insisted table, and only the
 * insisted table, will be placed on top of the stack.
 *
 * @param idx The index on the stack containing a table.
 * @param k The name of the table we are insisting exist.
 **/
int luax_insist(lua_State *L, int idx, const char *k);

/**
 * Insist that a global table 'k' exists. See luax_insist.
 * @param k The name of the table we are insisting exist.
 **/
int luax_insistglobal(lua_State *L, const char *k);

/**
 * Insists that a table 'k' exists inside the 'love' table. See luax_insist.
 * @param k The name of the table we are insisting exist.
 **/
int luax_insistlove(lua_State *L, const char *k);

/**
 * Pushes the table 'k' in the love table onto the stack. Pushes nil if the
 * table doesn't exist.
 * @param k The name of the table we want to get.
 **/
int luax_getlove(lua_State *L, const char *k);

/**
 * Gets (creates if needed) the specified Registry, and pushes it into the
 * stack.
 * @param L The Lua state.
 * @param r The Registry to get.
 **/
int luax_insistregistry(lua_State *L, Registry r);

/**
 * Gets the specified Registry, and pushes it onto the stack. Pushes nil if the
 * registry hasn't been created (see luax_insistregistry.)
 * @param L The Lua state.
 * @param r The Registry to get.
 **/
int luax_getregistry(lua_State *L, Registry r);

extern "C" { // Also called from luasocket
	int luax_typerror(lua_State *L, int narg, const char *tname);
}

/**
 * Like luax_totype, but causes an error if the value at idx is not Proxy,
 * or is not the specified type.
 * @param L The Lua state.
 * @param idx The index on the stack.
 * @param name The name of the type.
 * @param type The type bit.
 **/
template <typename T>
T *luax_checktype(lua_State *L, int idx, const char *name, love::bits type)
{
	if (lua_isuserdata(L, idx) == 0)
		luax_typerror(L, idx, name);

	Proxy *u = (Proxy *)lua_touserdata(L, idx);

	if ((u->flags & type) != type)
		luax_typerror(L, idx, name);

	return (T *)u->data;
}

template <typename T>
T *luax_getmodule(lua_State *L, const char *k, love::bits type)
{
	luax_insistregistry(L, REGISTRY_MODULES);
	lua_getfield(L, -1, k);

	if (!lua_isuserdata(L, -1))
		luaL_error(L, "Tried to get nonexistant module %s.", k);

	Proxy *u = (Proxy *)lua_touserdata(L, -1);

	if ((u->flags & type) != type)
		luaL_error(L, "Incorrect module %s", k);

	lua_pop(L, 2);

	return (T *)u->data;
}

template <typename T>
T *luax_optmodule(lua_State *L, const char *k, love::bits type)
{
	luax_insistregistry(L, REGISTRY_MODULES);
	lua_getfield(L, -1, k);

	if (!lua_isuserdata(L, -1))
	{
		lua_pop(L, 2);
		return 0;
	}

	Proxy *u = (Proxy *)lua_touserdata(L, -1);

	if ((u->flags & type) != type)
		luaL_error(L, "Incorrect module %s", k);
	
	lua_pop(L, 2);
	
	return (T *) u->data;
}

/**
 * Converts the value at idx to the specified type without checking that
 * this conversion is valid. If the type has been previously verified with
 * luax_istype, then this can be safely used. Otherwise, use luax_checktype.
 * @param L The Lua state.
 * @param idx The index on the stack.
 * @param name The name of the type.
 * @param type The type bit.
 **/
template <typename T>
T *luax_totype(lua_State *L, int idx, const char * /* name */, love::bits /* type */)
{
	return (T *)(((Proxy *)lua_touserdata(L, idx))->data);
}

Type luax_type(lua_State *L, int idx);

/**
 * Macro for converting a LOVE exception into a Lua error.
 * lua_error (and luaL_error) cannot be called from inside the exception handler
 * because they use longjmp, which causes undefined behaviour when the
 * destructor of the exception would have been called.
 **/
#define EXCEPT_GUARD(A) \
{ \
	bool should_error = false; \
	try { A } \
	catch (love::Exception &e) \
	{ \
		should_error = true; \
		lua_pushstring(L, e.what()); \
	} \
	if (should_error) \
		return lua_error(L); \
}

} // love

#endif // LOVE_RUNTIME_H
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.