mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-30 08:57:00 +02:00
258 lines
4.3 KiB
C++
258 lines
4.3 KiB
C++
/*
|
|
* 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/json/JsonNode.h"
|
|
#include "../../lib/int3.h"
|
|
|
|
VCMI_LIB_NAMESPACE_BEGIN
|
|
|
|
namespace 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
|