Exemplo n.º 1
0
static lua_result_t
lua_do_call_custom(lua_t* env, const char* method, size_t length, lua_arg_t* arg) {
	lua_State* state;
	lua_result_t result;
	int numargs, i;
	int stacksize;
	size_t start, next;
	string_const_t part;

	state = env->state;
	stacksize = lua_gettop(state);
	result = LUA_OK;

	++env->calldepth;

	next = string_find(method, length, '.', 0);
	if (next != STRING_NPOS) {
		part = string_const(method, next);
		lua_getlglobal(state, part.str, part.length);
		if (lua_isnil(state, -1)) {
			log_errorf(HASH_LUA, ERROR_INVALID_VALUE,
			           STRING_CONST("Invalid script call, '%.*s' is not set (%.*s)"),
			           STRING_FORMAT(part), (int)length, method);
			--env->calldepth;
			lua_pop(state, lua_gettop(state) - stacksize);
			return LUA_ERROR;
		}
		else if (!lua_istable(state, -1)) {
			log_errorf(HASH_LUA, ERROR_INVALID_VALUE,
			           STRING_CONST("Invalid script call, existing data '%.*s' in '%.*s' is not a table"),
			           STRING_FORMAT(part), (int)length, method);
			--env->calldepth;
			lua_pop(state, lua_gettop(state) - stacksize);
			return LUA_ERROR;
		}
		//Top of stack is now table
		FOUNDATION_ASSERT(lua_istable(state, -1));
		++next;
		start = next;

		next = string_find(method, length, '.', next);
		while (next != STRING_NPOS) {
			part = string_const(method + start, next - start);
			lua_pushlstring(state, part.str, part.length);
			lua_gettable(state, -2);
			if (lua_isnil(state, -1)) {
				log_errorf(HASH_LUA, ERROR_INVALID_VALUE,
				           STRING_CONST("Invalid script call, '%.*s' is not set (%.*s)"),
				           STRING_FORMAT(part), (int)next, method);
				--env->calldepth;
				lua_pop(state, lua_gettop(state) - stacksize);
				return LUA_ERROR;
			}
			else if (!lua_istable(state, -1)) {
				log_errorf(HASH_LUA, ERROR_INVALID_VALUE,
				           STRING_CONST("Invalid script call, existing data '%.*s' in '%.*s' is not a table"),
				           STRING_FORMAT(part), (int)next, method);
				--env->calldepth;
				lua_pop(state, lua_gettop(state) - stacksize);
				return LUA_ERROR;
			}
			//Top of stack is now table
			FOUNDATION_ASSERT(lua_istable(state, -1));

			++next;
			start = next;
			next = string_find(method, length, '.', next);
		}

		part = string_const(method + start, length - start);
		lua_pushlstring(state, part.str, part.length);
		lua_gettable(state, -2);
	}
	else {
		lua_getlglobal(state, method, length);
	}

	if (lua_isnil(state, -1)) {
		--env->calldepth;
		lua_pop(state, lua_gettop(state) - stacksize);

		//Method does not exist in Lua context
		log_errorf(HASH_LUA, ERROR_INVALID_VALUE,
		           STRING_CONST("Invalid script call, '%.*s' is not a function"), (int)length, method);
		return LUA_ERROR;
	}

	numargs = 0;
	if (arg) {
		numargs = (arg->num < LUA_MAX_ARGS) ? arg->num : LUA_MAX_ARGS;
		for (i = 0; i < numargs; ++i) {
			switch (arg->type[i]) {
			case LUADATA_PTR:
				lua_pushlightuserdata(state, arg->value[i].ptr);
				break;

			case LUADATA_OBJ:
				lua_pushobject(state, arg->value[i].obj);
				break;

			case LUADATA_INT:
				lua_pushinteger(state, arg->value[i].ival);
				break;

			case LUADATA_REAL:
				lua_pushnumber(state, arg->value[i].val);
				break;

			case LUADATA_STR:
				lua_pushlstring(state, arg->value[i].str, arg->size[i]);
				break;

			case LUADATA_BOOL:
				lua_pushboolean(state, arg->value[i].flag);
				break;

			case LUADATA_INTARR: {
					const int* values = arg->value[i].ptr;
					lua_newtable(state);
					for (uint16_t ia = 0; ia < arg->size[i]; ++ia) {
						lua_pushinteger(state, ia + 1);
						lua_pushinteger(state, values[ia]);
						lua_settable(state, -3);
					}
					break;
				}

			case LUADATA_REALARR: {
					const real* values = arg->value[i].ptr;
					lua_newtable(state);
					for (uint16_t ia = 0; ia < arg->size[i]; ++ia) {
						lua_pushinteger(state, ia + 1);
						lua_pushnumber(state, values[ia]);
						lua_settable(state, -3);
					}
					break;
				}

			default:
				--numargs;
				break;
			}
		}
	}

	//TODO: Parse return value from call
	if (lua_pcall(state, numargs, 0, 0) != 0) {
		string_const_t errmsg = {0, 0};
		errmsg.str = lua_tolstring(state, -1, &errmsg.length);
		log_errorf(HASH_LUA, ERROR_INTERNAL_FAILURE, STRING_CONST("Calling %.*s : %.*s"),
		           (int)length, method, STRING_FORMAT(errmsg));
		result = LUA_ERROR;
	}

	--env->calldepth;

	lua_pop(state, lua_gettop(state) - stacksize);

	return result;
}
Exemplo n.º 2
0
lua_result_t
lua_do_bind(lua_t* env, const char* property, size_t length, lua_command_t cmd, lua_value_t val) {
	lua_State* state;
	int stacksize;
	size_t start, next;
	string_const_t part;

	if (!env || !length)
		return LUA_ERROR;

	state = env->state;
	stacksize = lua_gettop(state);

	next = string_find(property, length, '.', 0);
	if (next != STRING_NPOS) {
		int tables;
		unsigned int numtables = 0;
		part = string_const(property, next);

		lua_getlglobal(state, part.str, part.length);
		if (lua_isnil(state, -1)) {
			//Create global table
			lua_pop(state, 1);
			lua_newtable(state);
			lua_pushvalue(state, -1);
			lua_setlglobal(state, part.str, part.length);
			log_debugf(HASH_LUA, STRING_CONST("Created global table: %.*s"), STRING_FORMAT(part));
		}
		else if (!lua_istable(state, -1)) {
			log_errorf(HASH_LUA, ERROR_INVALID_VALUE,
			           STRING_CONST("Invalid script bind call, existing data '%.*s' in '%.*s' is not a table"),
			           STRING_FORMAT(part), (int)length, property);
			lua_pop(state, lua_gettop(state) - stacksize);
			return LUA_ERROR;
		}
		//Top of stack is now table
		FOUNDATION_ASSERT(lua_istable(state, -1));

		++next;
		start = next;
		++numtables;

		next = string_find(property, length, '.', next);
		while (next != STRING_NPOS) {
			part = string_const(property + start, next - start);
			lua_pushlstring(state, part.str, part.length);
			lua_gettable(state, -2);
			if (lua_isnil(state, -1)) {
				//Create sub-table
				lua_pop(state, 1);
				lua_newtable(state);
				lua_pushlstring(state, part.str, part.length);
				lua_pushvalue(state, -2);
				lua_settable(state, -4);
				log_debugf(HASH_LUA, STRING_CONST("Created table: %.*s"), next, property);
			}
			else if (!lua_istable(state, -1)) {
				log_errorf(HASH_LUA, ERROR_INVALID_VALUE,
				           STRING_CONST("Invalid script bind call, existing data '%.*s' in '%.*s' is not a table"),
				           STRING_FORMAT(part), (int)next, property);
				lua_pop(state, lua_gettop(state) - stacksize);
				return LUA_ERROR;
			}
			//Top of stack is now table
			FOUNDATION_ASSERT(lua_istable(state, -1));

			++next;
			start = next;
			next = string_find(property, length, '.', next);
			++numtables;
		}

		part = string_const(property + start, length - start);

		switch (cmd) {
		case LUACMD_BIND:
			lua_push_method(state, STRING_ARGS(part), val.fn);
			break;
		case LUACMD_BIND_INT:
			lua_push_integer(state, STRING_ARGS(part), val.ival);
			break;
		case LUACMD_BIND_VAL:
			lua_push_number(state, STRING_ARGS(part), val.val);
			break;
		default:
			break;
		}

		tables = lua_gettop(state) - stacksize;
		lua_pop(state, tables);

		FOUNDATION_ASSERT(tables == (int)numtables);
	}
	else {
		part = string_const(property, length);
		switch (cmd) {
		case LUACMD_BIND:
			lua_push_method_global(state, STRING_ARGS(part), val.fn);
			break;
		case LUACMD_BIND_INT:
			lua_push_integer_global(state, STRING_ARGS(part), val.ival);
			break;
		case LUACMD_BIND_VAL:
			lua_push_number_global(state, STRING_ARGS(part), val.val);
			break;
		default:
			break;
		}
	}
	return LUA_OK;
}