⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 class_rep.cpp

📁 魔兽世界的私服源程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		// this block is needed to make sure the std::string is destructed before
		// lua_error() is called
		{
			std::string msg = "call of overloaded constructor '";
			msg += crep->m_name;
			msg +=  "(";
			msg += stack_content_by_name(L, 2);
			msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";

			std::vector<const overload_rep_base*> candidates;
			find_exact_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), min_match, num_params, candidates);
			msg += get_overload_signatures_candidates(L, candidates.begin(), candidates.end(), crep->name());

			lua_pushstring(L, msg.c_str());
		}
		lua_error(L);
	}

#endif

#ifndef LUABIND_NO_EXCEPTIONS

	try
	{

#endif

		void* object_ptr = rep->overloads[match_index].construct(L);

		void* obj_rep;
		void* held;

		boost::tie(obj_rep,held) = crep->allocate(L);

		if (crep->has_holder())
		{
			crep->m_construct_holder(held, object_ptr);
			object_ptr = held;
		}
		new(obj_rep) object_rep(object_ptr, crep, object_rep::owner, crep->destructor());

		detail::getref(L, crep->m_instance_metatable);
		lua_setmetatable(L, -2);
		return 1;

#ifndef LUABIND_NO_EXCEPTIONS

	}

	catch(const std::exception& e)
	{
		lua_pushstring(L, e.what());
	}
	catch(const char* s)
	{
		lua_pushstring(L, s);
	}
	catch(...)
	{
		{
			std::string msg = crep->name();
			msg += "() threw an exception";
			lua_pushstring(L, msg.c_str());
		}
	}

	// we can only reach this line if an exception was thrown
	lua_error(L);
	return 0; // will never be reached

#endif

}

// TODO: remove
/*
 int luabind::detail::class_rep::implicit_cast(const class_rep* from, const class_rep* to, int& pointer_offset)
{
	int offset = 0;
	if (LUABIND_TYPE_INFO_EQUAL(from->type(), to->type())) return 0;

	for (std::vector<class_rep::base_info>::const_iterator i = from->bases().begin(); i != from->bases().end(); ++i)
	{
		int steps = implicit_cast(i->base, to, offset);
		pointer_offset = offset + i->pointer_offset;
		if (steps >= 0) return steps + 2;
	}
	return -1;
}
*/


// the functions dispatcher assumes the following:
// there is one upvalue that points to the method_rep that this dispatcher is to call
// the first parameter on the lua stack is an object_rep that points to the object the
// call is being made on
int luabind::detail::class_rep::function_dispatcher(lua_State* L)
{
	method_rep* rep = static_cast<method_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
	object_rep* obj = reinterpret_cast<object_rep*>(lua_touserdata(L, 1));

#ifndef LUABIND_NO_ERROR_CHECKING

	if (is_class_object(L, 1) == 0)
	{
		{
			std::string msg = "No self reference given as first parameter to member function '";
			msg += rep->crep->name();
			msg += ":";
			msg += rep->name;
			msg += "'. Have you used '.' instead of ':'?";

			lua_pushstring(L, msg.c_str());
		}
		lua_error(L);
	}

	int p;
	if (implicit_cast(obj->crep(), rep->crep->type(), p) < 0)
	{
		{
			std::string msg = "invalid self reference given to '";
			msg += rep->crep->name();
			msg += ":";
			msg += rep->name;
			msg += "'";
			lua_pushstring(L, msg.c_str());
		}
		lua_error(L);
	}

#endif

	bool ambiguous = false;
	int match_index = -1;
	int min_match = std::numeric_limits<int>::max();
	bool found;

#ifdef LUABIND_NO_ERROR_CHECKING
	if (rep->overloads().size() == 1)
	{
		match_index = 0;
	}
	else
	{
#endif

		int num_params = lua_gettop(L) - 1;
		found = find_best_match(L, &rep->overloads().front(), rep->overloads().size(), sizeof(overload_rep), ambiguous, min_match, match_index, num_params);

#ifdef LUABIND_NO_ERROR_CHECKING

	}

#else

	if (!found)
	{
		{
			std::string msg = "no overload of  '";
			msg += rep->crep->name();
			msg += ":";
			msg += rep->name;
			msg += "' matched the arguments (";
			msg += stack_content_by_name(L, 2);
			msg += ")\ncandidates are:\n";

			std::string function_name;
			function_name += rep->crep->name();
			function_name += ":";
			function_name += rep->name;

			msg += get_overload_signatures(L, rep->overloads().begin(), rep->overloads().end(), function_name);

			lua_pushstring(L, msg.c_str());
		}
		lua_error(L);
	}
	else if (ambiguous)
	{
		{
			std::string msg = "call of overloaded  '";
			msg += rep->crep->name();
			msg += ":";
			msg += rep->name;
			msg += "(";
			msg += stack_content_by_name(L, 2);
			msg += ")' is ambiguous\nnone of the overloads have a best conversion:\n";

			std::vector<const overload_rep_base*> candidates;
			find_exact_match(L, &rep->overloads().front(), rep->overloads().size(), sizeof(overload_rep), min_match, num_params, candidates);

			std::string function_name;
			function_name += rep->crep->name();
			function_name += ":";
			function_name += rep->name;

			msg += get_overload_signatures_candidates(L, candidates.begin(), candidates.end(), function_name);

			lua_pushstring(L, msg.c_str());
		}
		lua_error(L);
	}

#endif

#ifndef LUABIND_NO_EXCEPTIONS

	try
	{

#endif

		const overload_rep& o = rep->overloads()[match_index];
		return o.call(L, *obj);

#ifndef LUABIND_NO_EXCEPTIONS

	}
	catch(const std::exception& e)
	{
		lua_pushstring(L, e.what());
	}
	catch (const char* s)
	{
		lua_pushstring(L, s);
	}
	catch(...)
	{
		std::string msg = rep->crep->name();
		msg += ":";
		msg += rep->name;
		msg += "() threw an exception";
		lua_pushstring(L, msg.c_str());
	}
	// we can only reach this line if an exception was thrown
	lua_error(L);
	return 0; // will never be reached

#endif
			
}

void luabind::detail::class_rep::add_base_class(const luabind::detail::class_rep::base_info& binfo)
{
	// If you hit this assert you are deriving from a type that is not registered
	// in lua. That is, in the class_<> you are giving a baseclass that isn't registered.
	// Please note that if you don't need to have access to the base class or the
	// conversion from the derived class to the base class, you don't need
	// to tell luabind that it derives.
	assert(binfo.base && "You cannot derive from an unregistered type");

	class_rep* bcrep = binfo.base;

	// import all functions from the base
	for (std::map<const char*, method_rep, ltstr>::const_iterator i = bcrep->m_methods.begin();
			i != bcrep->m_methods.end(); ++i)
	{
		// If we would assume that our base class will not be garbage collected until 
		// this class is collected, we wouldn't had to copy these strings.
#ifndef LUABIND_DONT_COPY_STRINGS
		m_strings.push_back(dup_string(i->first));
		method_rep& m = m_methods[m_strings.back()];
#else
		method_rep& m = m_methods[i->first];
#endif
		m.name = i->first;
		m.crep = this;

		for (std::vector<overload_rep>::const_iterator j = i->second.overloads().begin(); 
				j != i->second.overloads().end(); ++j)
		{
			overload_rep o = *j;
			o.add_offset(binfo.pointer_offset);
			m.add_overload(o);
		}
	}

	// import all getters from the base
	for (std::map<const char*, callback, ltstr>::const_iterator i = bcrep->m_getters.begin(); 
			i != bcrep->m_getters.end(); ++i)
	{
#ifndef LUABIND_DONT_COPY_STRINGS
		m_strings.push_back(dup_string(i->first));
		callback& m = m_getters[m_strings.back()];
#else
		callback& m = m_getters[i->first];
#endif
		m.pointer_offset = i->second.pointer_offset + binfo.pointer_offset;
		m.func = i->second.func;
	}

	// import all setters from the base
	for (std::map<const char*, callback, ltstr>::const_iterator i = bcrep->m_setters.begin(); 
			i != bcrep->m_setters.end(); ++i)
	{
#ifndef LUABIND_DONT_COPY_STRINGS
		// TODO: optimize this by not copying the string if it already exists in m_setters.
		// This goes for m_getters, m_static_constants and m_functions too. Both here
		// in add_base() and in the add_function(), add_getter() ... functions.
		m_strings.push_back(dup_string(i->first));
		callback& m = m_setters[m_strings.back()];
#else
		callback& m = m_setters[i->first];
#endif
		m.pointer_offset = i->second.pointer_offset + binfo.pointer_offset;
		m.func = i->second.func;
	}

	// import all static constants
	for (std::map<const char*, int, ltstr>::const_iterator i = bcrep->m_static_constants.begin(); 
			i != bcrep->m_static_constants.end(); ++i)
	{
#ifndef LUABIND_DONT_COPY_STRINGS
		m_strings.push_back(dup_string(i->first));
		int& v = m_static_constants[m_strings.back()];
#else
		int& v = m_static_constants[i->first];
#endif
		v = i->second;
	}

	// import all operators
	for (int i = 0; i < number_of_operators; ++i)
	{
		for (std::vector<operator_callback>::const_iterator j = bcrep->m_operators[i].begin(); 
				j != bcrep->m_operators[i].end(); ++j)
			m_operators[i].push_back(*j);
	}

	// also, save the baseclass info to be used for typecasts
	m_bases.push_back(binfo);
}
/*
void luabind::detail::class_rep::add_function(const char* name, const overload_rep& o)
{

#ifdef LUABIND_DONT_COPY_STRINGS
	detail::method_rep& method = m_methods[name];
	method.name = name;
#else
	m_strings.push_back(dup_string(name));
	detail::method_rep& method = m_methods[m_strings.back()];
	method.name = m_strings.back();
#endif

	method.add_overload(o);
	method.crep = this;
}

void luabind::detail::class_rep::add_getter(const char* name, const boost::function2<int, lua_State*, int>& g)
{
	callback c;
	c.func = g;
	c.pointer_offset = 0;
#ifndef LUABIND_DONT_COPY_STRINGS
	m_strings.push_back(dup_string(name));
	m_getters[m_strings.back()] = c;
#else
	m_getters[name] = c;
#endif
}

void luabind::detail::class_rep::add_setter(const char* name, const boost::function2<int, lua_State*, int>& s)
{
	callback c;
	c.func = s;
	c.pointer_offset = 0;
#ifndef LUABIND_DONT_COPY_STRINGS
	m_strings.push_back(dup_string(name));
	m_setters[m_strings.back()] = c;
#else
	m_setters[name] = c;
#endif
}

#ifndef LUABIND_NO_ERROR_CHECKING
void luabind::detail::class_rep::add_operator(lua_State*, int op_id,  int(*func)(lua_State*), int(*matcher)(lua_State*), void(*sig)(lua_State*, std::string&), int arity)
#else
void luabind::detail::class_rep::add_operator(lua_State*, int op_id,  int(*func)(lua_State*), int(*matcher)(lua_State*), int arity)
#endif
{
	operator_callback o;
	o.set_fun(func);
	o.set_match_fun(matcher);
	o.set_arity(arity);

#ifndef LUABIND_NO_ERROR_CHECKING

	o.set_sig_fun(sig);

#endif
	m_operators[op_id].push_back(o);
}

void luabind::detail::class_rep::add_static_constant(const char* name, int val)
{
#ifndef LUABIND_DONT_COPY_STRINGS
	m_strings.push_back(dup_string(name));
	m_static_constants[m_strings.back()] = val;
#else
	m_static_constants[name] = val;
#endif
}
*/
 int luabind::detail::class_rep::super_callback(lua_State* L)
{
	int args = lua_gettop(L);
		
	object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, lua_upvalueindex(2)));
	class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
	class_rep* base = crep->bases()[0].base;

	if (base->get_class_type() == class_rep::lua_class)
	{
		if (base->bases().empty())
		{
			obj->set_flags(obj->flags() & ~object_rep::call_super);

			lua_pushstring(L, "super");
			lua_pushnil(L);
			lua_settable(L, LUA_GLOBALSINDEX);
		}
		else
		{
			lua_pushstring(L, "super");
			lua_pushlightuserdata(L, base);
			lua_pushvalue(L, lua_upvalueindex(2));
			lua_pushcclosure(L, super_callback, 2);
			lua_settable(L, LUA_GLOBALSINDEX);
		}

		detail::getref(L, base->table_ref());
		lua_pushstring(L, "__init");
		lua_gettable(L, -2);
		lua_insert(L, 1);
		lua_pop(L, 1);

		lua_pushvalue(L, lua_upvalueindex(2));
		lua_insert(L, 2);

		lua_call(L, args + 1, 0);

		// TODO: instead of clearing the global variable "super"
		// store it temporarily in the registry. maybe we should
		// have some kind of warning if the super global is used?
		lua_pushstring(L, "super");
		lua_pushnil(L);
		lua_settable(L, LUA_GLOBALSINDEX);
	}
	else
	{
		obj->set_flags(obj->flags() & ~object_rep::call_super);

		// we need to push some garbage at index 1 to make the construction work
		lua_pushboolean(L, 1);
		lua_insert(L, 1);

		construct_rep* rep = &base->m_constructor;

		bool ambiguous = false;
		int match_index = -1;
		int min_match = std::numeric_limits<int>::max();
		bool found;
			
#ifdef LUABIND_NO_ERROR_CHECKING

		if (rep->overloads.size() == 1)
		{
			match_index = 0;
		}
		else
		{

#endif

			int num_params = lua_gettop(L) - 1;
			found = find_best_match(L, &rep->overloads.front(), rep->overloads.size(), sizeof(construct_rep::overload_t), ambiguous, min_match, match_index, num_params);

#ifdef LUABIND_NO_ERROR_CHECKING

		}

#else
				
		if (!found)
		{
			{
				std::string msg = "no constructor of '";
				msg += base->m_name;
				msg += "' matched the arguments (";
				msg += stack_content_by_name(L, 2);
				msg += ")";
				lua_pushstring(L, msg.c_str());
			}
			lua_error(L);
		}
		else if (ambiguous)
		{
			{
				std::string msg = "call of overloaded constructor '";
				msg += base->m_name;
				msg +=  "(";
				msg += stack_content_by_name(L, 2);
				msg += ")' is ambiguous";
				lua_pushstring(L, msg.c_str());
			}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -