| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 | /* * LuaStack.cpp, part of VCMI engine * * Authors: listed in file AUTHORS in main folder * * License: GNU General Public License v2.0 or later * Full text of license available in license.txt file, in main folder * */#include "StdInc.h"#include "LuaStack.h"#include "../../lib/JsonNode.h"#include "../../lib/int3.h"VCMI_LIB_NAMESPACE_BEGINnamespace scripting{LuaStack::LuaStack(lua_State * L_):	L(L_),	initialTop(lua_gettop(L)){}void LuaStack::balance(){	lua_settop(L, initialTop);}void LuaStack::clear(){	lua_settop(L, 0);}void LuaStack::pushByIndex(lua_Integer index){	lua_pushvalue(L, index);}void LuaStack::pushNil(){	lua_pushnil(L);}void LuaStack::pushInteger(lua_Integer value){	lua_pushinteger(L, value);}void LuaStack::push(bool value){	lua_pushboolean(L, value);}void LuaStack::push(const char * value){	lua_pushstring(L, value);}void LuaStack::push(const std::string & value){	lua_pushlstring(L, value.c_str(), value.size());}void LuaStack::push(const int3 & value){	push(value.x);	push(value.y);	push(value.z);}void LuaStack::push(const JsonNode & value){	switch(value.getType())	{	case JsonNode::JsonType::DATA_BOOL:		{			push(value.Bool());		}		break;	case JsonNode::JsonType::DATA_FLOAT:		{			lua_pushnumber(L, value.Float());		}		break;	case JsonNode::JsonType::DATA_INTEGER:		{			pushInteger(value.Integer());		}		break;	case JsonNode::JsonType::DATA_STRUCT:		{			lua_newtable(L);			for(const auto & keyValue : value.Struct())			{				push(keyValue.first);				push(keyValue.second);				lua_rawset(L, -3);			}		}		break;	case JsonNode::JsonType::DATA_STRING:		push(value.String());		break;	case JsonNode::JsonType::DATA_VECTOR:		{			lua_newtable(L);			for(int idx = 0; idx < value.Vector().size(); idx++)			{				pushInteger(idx + 1);				push(value.Vector()[idx]);				lua_rawset(L, -3);			}		}		break;	default:		pushNil();		break;	}}bool LuaStack::tryGet(int position, bool & value){	if(!lua_isboolean(L, position))		return false;	value = (lua_toboolean(L, position) != 0);	return true;}bool LuaStack::tryGet(int position, double & value){	if(!lua_isnumber(L, position))		return false;	value = lua_tonumber(L, position);	return true;}bool LuaStack::tryGetInteger(int position, lua_Integer & value){	if(!lua_isnumber(L, position))		return false;	value = lua_tointeger(L, position);	return true;}bool LuaStack::tryGet(int position, std::string & value){	if(!lua_isstring(L, position))		return false;	size_t len = 0;	const auto *raw = lua_tolstring(L, position, &len);	value = std::string(raw, len);	return true;}bool LuaStack::tryGet(int position, int3 & value){	return tryGet(position, value.x) && tryGet(position+1, value.y) && tryGet(position+2, value.z);}bool LuaStack::tryGet(int position, JsonNode & value){	auto type = lua_type(L, position);	switch(type)	{	case LUA_TNIL:		value.clear();		return true;	case LUA_TNUMBER:		return tryGet(position, value.Float());	case LUA_TBOOLEAN:		value.Bool() = (lua_toboolean(L, position) != 0);		return true;	case LUA_TSTRING:		return tryGet(position, value.String());	case LUA_TTABLE:		{			JsonNode asVector(JsonNode::JsonType::DATA_VECTOR);			JsonNode asStruct(JsonNode::JsonType::DATA_STRUCT);			lua_pushnil(L);  /* first key */			while(lua_next(L, position) != 0)			{				/* 'key' (at index -2) and 'value' (at index -1) */				JsonNode fieldValue;				if(!tryGet(lua_gettop(L), fieldValue))				{					lua_pop(L, 2);					value.clear();					return false;				}				lua_pop(L, 1); //pop value				if(lua_type(L, -1) == LUA_TNUMBER)				{					auto key = lua_tointeger(L, -1);					if(key > 0)					{						if(asVector.Vector().size() < key)							asVector.Vector().resize(key);						--key;						asVector.Vector().at(key) = fieldValue;					}				}				else if(lua_isstring(L, -1))				{					std::string key;					tryGet(-1, key);					asStruct[key] = fieldValue;				}			}			if(!asVector.Vector().empty())			{				std::swap(value, asVector);			}			else			{				std::swap(value, asStruct);			}		}		return true;	default:		value.clear();		return false;	}}int LuaStack::retNil(){	clear();	pushNil();	return 1;}int LuaStack::retVoid(){	clear();	return 0;}}VCMI_LIB_NAMESPACE_END
 |